Compare commits

...

92 Commits

Author SHA1 Message Date
galister cb3aa42bd9 Release 26.8.0 2026-08-10 03:32:27 +09:00
Aleksander e6c5142476 dash-frontend: btn_supporter ui fix [skip ci] 2026-08-09 18:06:34 +02:00
Aleksander b02cfa446f wgui: label: fix color palette not triggering any color update 2026-08-09 18:02:11 +02:00
Aleksander 8ad055a483 wayvr: translation strings for notify_send 2026-08-09 21:48:40 +09:00
Aleksander f13562c7dc wayvr: baked toasts 2026-08-09 21:48:40 +09:00
galister 669043035e
Supporter chance (#624)
* refactor SupporterTier

* supporter carousel weighted chance

* fix light mode woes
2026-08-09 20:54:14 +09:00
galister 77b5004541 add tests for translation jsons 2026-08-09 18:34:27 +09:00
oo8dev 1a44b54d98
Supporters list (#622)
* Supporters list

* dash-frontend: Random supporter on main screen, wgui: prevent unnecessary redraws

* more creative sponsor messages

---------

Co-authored-by: galister <22305755+galister@users.noreply.github.com>
2026-08-09 17:48:52 +09:00
Aleksander cae2d7c7e2 clippy 2026-08-08 04:03:56 +09:00
hypevhs 6631c004c9 README: update Envision and SteamVR info 2026-08-06 11:16:44 +09:00
Aleksander 98f800c644 translator: Fix english not working at all, minor refactoring 2026-08-03 09:40:17 +02:00
Aleksander 3ae01f59d1 fix typo 2026-08-03 11:43:26 +09:00
Aleksander 6fa434af46 dash-frontend: fix stray '?' character, fix pl.json 2026-08-03 11:43:26 +09:00
Aleksander dcb01fdb6a translator: Update description.txt 2026-08-03 11:43:26 +09:00
galister 3940e8b4f2 dash-frontend translations 2026-08-03 11:43:26 +09:00
galister 97418111fb translations json → csv 2026-08-03 11:43:26 +09:00
Aleksander 38590d9cfb bugfix: whisper options do not show up in vr 2026-08-02 22:47:45 +02:00
galister 2e07818072 use xkb style for variants 2026-08-02 23:53:59 +09:00
galister 5a9133c497 translation keys 2026-08-02 23:41:43 +09:00
galister 84068ca710 typo 2026-08-02 23:39:25 +09:00
galister a7ff06f38a toast when no keymaps configured 2026-08-02 23:38:36 +09:00
galister 7b8fadfaf2 keymap cycling 2026-08-02 23:29:07 +09:00
galister eb2786311a wording for space_drag_affects_world 2026-08-02 17:15:35 +09:00
galister 8e0f27f690 fix auto_movement on Floating 2026-08-02 17:11:58 +09:00
galister e64fb789c7 persist window sizes for wvr & passthru 2026-08-02 17:11:58 +09:00
galister 05aac47716 fix persisting global & static overlays 2026-08-02 17:11:58 +09:00
galister ebb912db68 align_to_hmd for static & floating 2026-08-02 17:11:58 +09:00
galister 75154d8375 monado task switcher: use client id instead of name 2026-08-02 17:11:58 +09:00
galister 4c918b0aaf cleanup 2026-08-02 17:11:58 +09:00
galister 5ba7d1fdad defaults for positioning, opecity, curvature 2026-08-02 17:11:58 +09:00
galister 4eeb0afb0b align_to_hmd regardless of Positioning 2026-08-02 17:11:58 +09:00
galister f4523f3ab1 persistent passthrus 2026-08-02 17:11:58 +09:00
galister c594f6bda3 load state for global overlays 2026-08-02 17:11:58 +09:00
galister 6edf144aee passthru icon 2026-08-02 17:11:58 +09:00
Beyley Cardellio b85077b559 openxr: Add support for ContactGlove2+Magnetra2 2026-08-02 13:20:05 +09:00
Beyley Cardellio 29c5800a61 openxr: Correct check for other extensions 2026-08-02 13:20:05 +09:00
galister 3cfbafa577 focus mode: add keyboard toggle, num keys 2026-08-02 00:01:17 +09:00
galister 05708813be start blocking poses after keyboard was clicked once 2026-08-01 23:43:59 +09:00
galister 4ad6287efc refactor: InterfaceFeats in AppState 2026-08-01 23:30:06 +09:00
galister 98d8a3138d actually pass the params 2026-08-01 21:19:57 +09:00
galister 7261f7fa1f skip attrib woes 2026-08-01 21:19:57 +09:00
galister 7efc4bb0fc don't show options that are incompatible 2026-08-01 21:19:57 +09:00
galister 395e9d1919 passthru windows 2026-08-01 21:19:57 +09:00
galister deccbda473 add skip attribute 2026-08-01 21:19:57 +09:00
galister 7ff096c9ab update gitignore 2026-08-01 21:19:57 +09:00
Aleksander 6f6f9af983 move executor.try_tick() to AppState::tick()
[skip ci]
2026-07-30 08:21:31 +02:00
Aleksander 6b22e4aef1 dash-frontend: minor refactoring for Tasks 2026-07-30 12:58:49 +09:00
Aleksander 707e3a4927 dash-frontend: remove partially downloaded files, cancel download on Downloader view exit 2026-07-30 12:58:49 +09:00
Aleksander 0b4c59f1c7 dash-frontend: download in a separate thread 2026-07-30 12:58:49 +09:00
galister d1f2995846 dependency cleaning 2026-07-30 03:27:06 +09:00
galister 2574784ad3 remove smol-hyper 2026-07-30 03:26:59 +09:00
galister 239337ae76 toast when input capture fails 2026-07-30 03:26:47 +09:00
cubee 67877d6a5f make other `shift_world` obey `space_drag_affects_world`, and overlays follow `space-rotate` 2026-07-28 17:37:40 +09:00
cubee 44b7a2a6ab make space_reset obey space_drag_affects_world 2026-07-28 17:37:40 +09:00
Aleksander 5dffbb9fdb wayvr-ipc: bump to version 4, remove unused WayVR signal broadcast feature, fix broken `window-set-visible` command 2026-07-26 18:59:26 +09:00
Aleksander c92e27dcf9 get rid of handle.rs in favor of DenseSlotMap 2026-07-26 18:59:26 +09:00
oo8dev e40b953e5a
Dynamic color palettes without restart (#594)
* dash-frontend: dynamic color palette switching

* wayvr: add support for color dynamic color palette refresh
2026-07-25 18:40:07 +02:00
galister 9b336535f7
input: InputState: should_disable_lerp (#593)
Co-authored-by: Aleksander <aleksander@oo8.dev>
2026-07-25 18:39:45 +02:00
Aleksander 48da2ca416 dash-frontend: fix `pinned_apps` not saving 2026-07-25 18:34:51 +02:00
galister b4e2fd782c feat: Space drag moves overlays 2026-07-24 02:57:11 +09:00
galister 0613f94be6 overlays stay in place after reset/recenter/fix_floor 2026-07-23 18:58:28 +09:00
galister b82f781757 overlays stay while space moving 2026-07-23 18:26:54 +09:00
galister 4e4d552bb6 fix playspace center saving 2026-07-23 18:12:05 +09:00
galister 078055dc0f frame-time independent scrolling 2026-07-23 17:48:00 +09:00
galister d56c181e9d fix wl_virtual keyboard not respecting keymap 2026-07-23 17:46:24 +09:00
galister 6a6264347b mouse wheel handling & wl_virtual modifiers 2026-07-23 17:46:24 +09:00
galister 590980e560 input capture rework 2026-07-23 17:46:24 +09:00
galister ca550f356b refactor KeyCombo 2026-07-23 17:46:24 +09:00
galister cf6bfe855e fix ci 2026-07-23 17:46:24 +09:00
galister 43a435aa89 alt-tabbing and stuff 2026-07-23 17:46:24 +09:00
galister 2ab3605116 handsfree alt-tab 2026-07-23 17:46:24 +09:00
galister bc19afad34 wayvrctl input-capture 2026-07-23 17:46:24 +09:00
galister e3829fdebf better key combos 2026-07-23 17:46:24 +09:00
galister f711d9a464 relative mouse, dynamic decor, refactors 2026-07-23 17:46:24 +09:00
galister 302cd14a50 key combos 2026-07-23 17:46:24 +09:00
galister 58dbb1e1b2 input capture #4 - pointer accel config 2026-07-23 17:46:24 +09:00
galister 73ae2b7274 input capture #3 - use libinput instead of evdev 2026-07-23 17:46:24 +09:00
galister c295bf4f0d input capture #2 - mouse 2026-07-23 17:46:24 +09:00
galister 5c158e0353 input capture #1 - keyboard 2026-07-23 17:46:24 +09:00
Aleksander 7f6caca0f8 wgui: MouseCancel event couldn't propagate all the way down (Closes #588) 2026-07-23 11:02:35 +09:00
Aleksander e1fb392297 wgui: account for current scissoring state on widget hover check (Closes #587)
This prevents clicking widgets outside their scissor boundary.
2026-07-23 11:02:35 +09:00
Aleksander 8adff4ca6a wgui: bugfix: scrollable list could start swipe event out-of-bounds (Closes #586) 2026-07-23 11:02:35 +09:00
galister 629de4c8ff fix build without pipewire 2026-07-23 11:02:02 +09:00
galister beae8e82f5 save/reset playspace center 2026-07-22 14:56:13 +09:00
galister a12d1ff8f4 fix build again 2026-07-22 12:11:53 +09:00
galister 447d75acef fix build 2026-07-22 11:53:33 +09:00
galister 4652f708b0 meta → altgr 2026-07-20 16:34:12 +09:00
galister e1879ca891 playspace center? 2026-07-20 00:26:53 +09:00
galister 786660a4d5 fix mirrors only allowing screens 2026-07-19 09:29:17 +09:00
galister 9e43b9b3ad openvr: copy reset_offset logic from openxr 2026-07-19 09:22:35 +09:00
galister 7c16748f88 openvr: copy recenter logic from openxr 2026-07-19 09:22:35 +09:00
galister a29451ceaa build xwayland-satellite for release 2026-07-14 22:19:33 +09:00
194 changed files with 9941 additions and 5637 deletions

View File

@ -27,6 +27,9 @@ jobs:
- name: Cargo Build - name: Cargo Build
run: | run: |
../.github/workflows/scripts/appimage_build_wlx.sh ../.github/workflows/scripts/appimage_build_wlx.sh
- name: Build xwayland-satellite
run: |
../.github/workflows/scripts/appimage_build_satellite.sh
- name: Package AppImage - name: Package AppImage
run: | run: |
../.github/workflows/scripts/appimage_package.sh ../.github/workflows/scripts/appimage_package.sh

View File

@ -1,7 +1,11 @@
#!/bin/sh #!/bin/sh
sudo apt-get update sudo apt-get update
sudo apt-get install -y fuse cmake pkg-config fontconfig libasound2-dev libxkbcommon-dev libxkbcommon-x11-0 libxkbcommon-x11-dev libopenxr-dev libfontconfig-dev libdbus-1-dev libpipewire-0.3-0 libpipewire-0.3-dev libspa-0.2-dev libx11-6 libxext6 libxrandr2 libx11-dev libxext-dev libxrandr-dev libopenvr-dev libopenvr-api1 libwayland-dev libegl-dev libxcb-glx0 libxcb-glx0-dev dav1d libdav1d-dev libvulkan-dev glslc vulkan-tools sudo apt-get install -y fuse cmake pkg-config fontconfig libasound2-dev libxkbcommon-dev libxkbcommon-x11-0 libxkbcommon-x11-dev \
libopenxr-dev libfontconfig-dev libdbus-1-dev libpipewire-0.3-0 libpipewire-0.3-dev libspa-0.2-dev libx11-6 libxext6 libxrandr2 \
libx11-dev libxext-dev libxrandr-dev libopenvr-dev libopenvr-api1 libwayland-dev libegl-dev libxcb-glx0 libxcb-glx0-dev \
dav1d libdav1d-dev libvulkan-dev glslc vulkan-tools libudev-dev libudev1 libinput-dev libinput10
rustup update rustup update
if [ "$APPDIR" != "" ]; then if [ "$APPDIR" != "" ]; then

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.~lock.*
/target /target
.gdb_history .gdb_history
.vscode .vscode

647
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -62,13 +62,12 @@ In case screens were selected in the wrong order:
**WiVRn users**: Select WayVR from the `Application` drop-down. If there's no such entry, select `Custom` and browse to your WayVR executable or AppImage. **WiVRn users**: Select WayVR from the `Application` drop-down. If there's no such entry, select `Custom` and browse to your WayVR executable or AppImage.
**Envision users**: Go to the Plugins menu and select the WayVR plugin. This will download and run the AppImage version of the overlay. **Envision users**: Go to the Plugins menu and toggle on the WayVR plugin. If WayVR isn't in the Plugins list, or the list is empty, ensure you've installed WayVR fully, such that it appears in your Desktop Environment's application menu. If you've *downloaded* the WayVR AppImage, [Gear Lever](https://github.com/mijorus/gearlever) can *install* it, which creates the application menu entry.
To run a standalone installation (for instance, from the AUR), create a bash script containing `wayvr --openxr --show` and then set this bash script as a custom Envision plugin.
**SteamVR users**: WayVR no longer registers itself for auto-start, due to bugs in SteamVR. For now, you must start WayVR manually.
This will show a home environment with headset passthrough enabled by default or a [customizable background](https://wayvr.org/docs/various/openxr-skybox/)! This will show a home environment with headset passthrough enabled by default or a [customizable background](https://wayvr.org/docs/various/openxr-skybox/)!
**SteamVR users**: WayVR will register itself for auto-start, so there is no need to start it every time. Disclaimer: SteamVR will sometimes disregard this and not start WayVR anyway.
**Please continue reading the guide below.** **Please continue reading the guide below.**
## Getting Started ## Getting Started

View File

@ -24,15 +24,10 @@ strum.workspace = true
uuid.workspace = true uuid.workspace = true
xdg.workspace = true xdg.workspace = true
async-native-tls = "0.6.0" keyvalues-parser = "0.2.4"
http-body-util = "0.1.3"
keyvalues-parser = {
git = "https://codeberg.org/CosmicHarper/vdf-rs.git",
rev = "fc6dcbea9eb13cacb98dea40063f6f56cde6e145"
}
lz4_flex = { version = "0.13.1", features = ["frame"] } lz4_flex = { version = "0.13.1", features = ["frame"] }
smol-hyper = "0.1.1"
ureq = "3.3.0" ureq = "3.3.0"
rand = "0.10.2"
[features] [features]
default = ["monado"] default = ["monado"]

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Design Icons by Pictogrammers - https://github.com/Templarian/MaterialDesign/blob/master/LICENSE --><path fill="currentColor" d="M14.94 19.5L12 17.77L9.06 19.5l.78-3.34l-2.59-2.24l3.41-.29L12 10.5l1.34 3.13l3.41.29l-2.59 2.24M20 2H4v2l4.86 3.64a8 8 0 1 0 6.28 0L20 4m-2 11a6 6 0 1 1-7.18-5.88a5.9 5.9 0 0 1 2.36 0A6 6 0 0 1 18 15m-5.37-8h-1.26l-4-3h9.34Z"/></svg>

After

Width:  |  Height:  |  Size: 470 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="currentColor" d="M9.175 10.825Q8 9.65 8 8t1.175-2.825T12 4t2.825 1.175T16 8t-1.175 2.825T12 12t-2.825-1.175M4 20v-2.8q0-.85.438-1.562T5.6 14.55q1.55-.775 3.15-1.162T12 13t3.25.388t3.15 1.162q.725.375 1.163 1.088T20 17.2V20z"/></svg>

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,5 +1,5 @@
<layout> <layout>
<template name="Separator"> <template name="Separator">
<rectangle width="100%" min_height="2" color="#FFFFFF10" /> <rectangle width="100%" min_height="2" color="outline" />
</template> </template>
</layout> </layout>

View File

@ -1,47 +1,65 @@
<layout> <layout>
<include src="../t_group_box.xml" /> <include src="../t_separator.xml" />
<template name="TierCell">
<div gap="8" align_items="center">
<sprite width="28" height="28" src_builtin="dashboard/medal.svg" color="${color}"/>
<label text="${text}" weight="bold" size="18" color="${color}" shadow="shadow"/>
</div>
</template>
<template name="SupporterCell">
<rectangle padding="8" color="background(transparent)" round="8" border="2" border_color="outline" gap="8" align_items="center" flex_direction="row" >
<sprite width="24" height="24" src_builtin="dashboard/person.svg"/>
<label text="${username}" weight="bold"/>
</rectangle>
</template>
<!-- icon, nickname --> <!-- icon, nickname -->
<template name="Avatar"> <template name="Avatar">
<div flex_direction="column" gap="12" align_items="center"> <div flex_direction="column" gap="12" align_items="center">
<image src_builtin="${icon}" width="72" height="72" round="100%" position="relative"> <image src_builtin="${icon}" width="64" height="64" round="100%" position="relative">
<rectangle position="absolute" margin_left="-2" margin_top="-2" width="76" height="76" color="highlight" round="100%"/> <rectangle position="absolute" margin_left="-2" margin_top="-2" width="68" height="68" color="highlight" round="100%"/>
</image> </image>
<label size="14" text="${nickname}"/> <label size="14" text="${nickname}"/>
</div> </div>
</template> </template>
<macro name="half"
width="50%" gap="16" flex_direction="column" overflow_y="scroll"
align_items="center"/>
<elements> <elements>
<div position="absolute" width="100%" height="100%" padding="4"> <div flex_direction="row" width="100%" min_height="100%" gap="16">
<!-- <rectangle width="100%" height="100%" color="#000000" round="6"/> --> <div macro="half">
</div> <sprite color="#FFAAAA" src_builtin="dashboard/donate.svg" min_width="48" min_height="48"/>
<div margin="32" flex_direction="column" align_items="center" justify_content="center" gap="16" height="100%"> <div gap="16" align_items="center" width="100%">
<div gap="16" align_items="center" width="100%"> <label align="justified" wrap="1" size="15" translation="DONATE.DESCRIPTION" color="on_background"/>
<sprite color="#FFAAAA" src_builtin="dashboard/donate.svg" min_width="64" min_height="64"/> </div>
<label wrap="1" size="20" translation="DONATE.DESCRIPTION" color="on_background"/>
<div flex_direction="column" gap="8" align_items="center">
<Button id="btn_donate" tooltip="DONATE.BUTTON_TOOLTIP" align_self="baseline">
<image src_builtin="dashboard/opencollective_logo.svg" width="200" height="32" margin="8" margin_left="16" margin_right="16"/>
</Button>
<label text="opencollective.com/wayvr-org"/>
</div>
<label weight="bold" size="20" translation="DONATE.THANK_YOU_WAYVR" color="on_background"/>
<div gap="32">
<Avatar icon="dashboard/avatars/galister.png" nickname="galister"/>
<Avatar icon="dashboard/avatars/oo8dev.png" nickname="oo8dev"/>
</div>
</div> </div>
<!-- vertical separator -->
<div flex_direction="column" gap="8" align_items="center" margin_top="16"> <rectangle height="100%" min_width="2" color="outline"/>
<Button id="btn_donate" tooltip="DONATE.BUTTON_TOOLTIP" align_self="baseline"> <div macro="half">
<image src_builtin="dashboard/opencollective_logo.svg" width="252" height="42" margin="8" margin_left="16" margin_right="16"/> <div gap="8" align_items="center">
</Button> <label translation="DONATE.CURRENT_SUPPORTERS" size="18" weight="bold" />
<label text="opencollective.com/wayvr-org"/> <Button round="100%" text="?" tooltip_str="In last 30 days; the list is updated each day" width="24" height="24"/>
</div>
<div id="current_supporters" flex_direction="column" gap="8" width="100%"/>
</div> </div>
<label weight="bold" size="24" translation="DONATE.THANK_YOU_WAYVR" color="on_background"/>
<div gap="32" margin_top="16">
<Avatar icon="dashboard/avatars/galister.png" nickname="galister"/>
<Avatar icon="dashboard/avatars/oo8dev.png" nickname="oo8dev"/>
</div>
<!--
<rectangle color="#FFFFFF33" width="100%" height="2"/>
<rectangle macro="group_box" align_self="start" width="100%">
<label weight="bold" size="18" translation="DONATE.CURRENT_SUPPORTERS"/>
</rectangle>
-->
</div> </div>
</elements> </elements>
</layout> </layout>

View File

@ -7,12 +7,25 @@
justify_content="center" justify_content="center"
align_items="center" align_items="center"
flex_grow="1" flex_grow="1"
gap="24"> gap="8"
>
<image src_builtin="dashboard/splash.png" width="300" height="89" /> <image src_builtin="dashboard/splash.png" width="300" height="89" />
<label id="label_hello" size="32" weight="bold" color="on_background" />
<!-- supporters -->
<Button
id="btn_supporter"
width="fit_content"
height="24"
text=" "
border_color="tertiary(transparent)"
hover_border_color="tertiary"
color="background_variant(transparent)"
hover_color="tertiary(transparent)"/>
<label id="label_hello" margin_top="24" size="32" weight="bold" color="on_background" />
<!-- main button list --> <!-- main button list -->
<div flex_direction="row" gap="8"> <div flex_direction="row" gap="8" margin_top="32">
<MenuButton id="btn_apps" icon="dashboard/apps.svg" translation="APPLICATIONS" /> <MenuButton id="btn_apps" icon="dashboard/apps.svg" translation="APPLICATIONS" />
<MenuButton id="btn_games" icon="dashboard/games.svg" translation="GAMES" /> <MenuButton id="btn_games" icon="dashboard/games.svg" translation="GAMES" />
<MenuButton id="btn_monado" icon="dashboard/monado.svg" text="Monado" /> <MenuButton id="btn_monado" icon="dashboard/monado.svg" text="Monado" />

View File

@ -41,13 +41,6 @@
<RadioBox translation="APP_LAUNCHER.ASPECT.SEMI_TALL" value="SemiTall" tooltip_str="2:3" /> <RadioBox translation="APP_LAUNCHER.ASPECT.SEMI_TALL" value="SemiTall" tooltip_str="2:3" />
<RadioBox translation="APP_LAUNCHER.ASPECT.TALL" value="Tall" tooltip_str="9:16" /> <RadioBox translation="APP_LAUNCHER.ASPECT.TALL" value="Tall" tooltip_str="9:16" />
</RadioGroup> </RadioGroup>
<!-- Separator /> // saved settings override this, so let's hide it for now
<label translation="APP_LAUNCHER.POS_TITLE" />
<RadioGroup id="radio_pos" flex_direction="row" gap="16">
<RadioBox translation="APP_LAUNCHER.POS.FLOATING" value="Floating" tooltip_str="APP_LAUNCHER.POS.FLOATING_HELP" />
<RadioBox translation="APP_LAUNCHER.POS.ANCHORED" value="Anchored" tooltip_str="APP_LAUNCHER.POS.ANCHORED_HELP" checked="1" />
<RadioBox translation="APP_LAUNCHER.POS.STATIC" value="Static" tooltip_str="APP_LAUNCHER.POS.STATIC_HELP" />
</RadioGroup -->
<Separator /> <Separator />
<CheckBox id="cb_autostart" translation="APP_LAUNCHER.AUTOSTART" align_self="baseline"/> <CheckBox id="cb_autostart" translation="APP_LAUNCHER.AUTOSTART" align_self="baseline"/>
<div flex_direction="row" align_items="end" justify_content="center" gap="8" margin_top="8"> <div flex_direction="row" align_items="end" justify_content="center" gap="8" margin_top="8">

View File

@ -23,7 +23,7 @@
<div gap="16" align_items="center"> <div gap="16" align_items="center">
<!-- Back button --> <!-- Back button -->
<Button id="but_back" width="48" height="48" color="on_background_contrast(transparent)" border_color="on_background_contrast(transparent)"> <Button id="but_back" width="48" height="48" color="on_background_contrast(transparent)" border_color="on_background_contrast(transparent)">
<sprite src_builtin="dashboard/back.svg" width="24" height="24" /> <sprite src_builtin="dashboard/back.svg" width="24" height="24" color="on_background_contrast" />
</Button> </Button>
<!-- Title --> <!-- Title -->

View File

@ -1,114 +1,56 @@
{ {
"HOME_SCREEN": "Startbildschirm", "DEFINITIONS": {
"MONADO_RUNTIME": "Monado-Laufzeitumgebung", "ANCHORED": "Verankert",
"APPLICATIONS": "Anwendungen", "FLOATING": "Schwebend",
"GAMES": "Spiele", "STATIC": "Statisch",
"SETTINGS": "Einstellungen", "SET": "Set",
"HELLO_USER": "Hallo, {USER}!", "WATCH": "Handgelenk-Uhr",
"GENERAL_SETTINGS": "Allgemeine Einstellungen", "DASHBOARD": "Dashboard",
"APPLICATION_LAUNCHER": "Anwendung Launcher", "EDIT_MODE": "Bearbeitungsmodus",
"APP_SETTINGS": { "SETTINGS": "Einstellungen",
"HIDE_USERNAME": "Benutzernamen ausblenden", "KEYBOARD": "Tastatur",
"OPAQUE_BACKGROUND": "Undurchsichtiger Hintergrund", "TASKBAR": "Taskleiste",
"LOOK_AND_FEEL": "Aussehen und Verhalten", "FEATURES": "Features",
"HIDE_GRAB_HELP": "Greif-Hilfe ausblenden", "OVERLAY": "Overlay",
"ANIMATION_SPEED": "UI-Animationsgeschwindigkeit", "SKYMAP": "Skymap",
"ROUND_MULTIPLIER": "UI-Kantenrundung", "PLAYSPACE": "Playspace",
"USE_SKYBOX": "Skybox aktivieren", "D_PAD": "Steuerkreuz"
"USE_PASSTHROUGH": "Passthrough aktivieren", },
"CLOCK_12H": "12-Stunden-Uhr", "ACTIONS": {
"FEATURES": "Funktionen", "RECENTER_PLAYSPACE": "Playspace neu zentrieren"
"NOTIFICATIONS_ENABLED": "Benachrichtigungen aktivieren", },
"NOTIFICATIONS_SOUND_ENABLED": "Benachrichtigungstöne", "APP_LAUNCHER": {
"KEYBOARD_SOUND_ENABLED": "Tastengeräusche", "ASPECT": {
"SPACE_DRAG_MULTIPLIER": "Raum-Drag-Multiplikator", "SEMI_TALL": "Halbhoch",
"SPACE_DRAG_UNLOCKED": "Erlaube Space-Drag auf allen Achsen", "SEMI_WIDE": "Halbweit",
"SPACE_ROTATE_UNLOCKED": "Erlaube Drehungen in allen Achsen", "SQUARE": "Quadratisch",
"BLOCK_GAME_INPUT": "Spieleingabe blockieren", "TALL": "Hochkant",
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignoriere Watch beim Blockieren der Eingabe", "WIDE": "Breitbild"
"CONTROLS": "Steuerung",
"FOCUS_FOLLOWS_MOUSE_MODE": "Mausbewegung bei Triggerberührung",
"LEFT_HANDED_MOUSE": "Linkshändige Maus",
"ALLOW_SLIDING": "Stabinteraktion während des Greifens",
"INVERT_SCROLL_DIRECTION_X": "Horizontale Scrollrichtung umkehren",
"INVERT_SCROLL_DIRECTION_Y": "Vertikale Bildlaufrichtung umkehren",
"SCROLL_SPEED": "Scrollgeschwindigkeit",
"LONG_PRESS_DURATION": "Dauer für lange Drückvorgänge",
"POINTER_LERP_FACTOR": "Zeigerglättung",
"CLICK_FREEZE_TIME_MS": "Klick-Freeze-Zeit (ms)",
"MISC": "Verschiedenes",
"XWAYLAND_BY_DEFAULT": "Standardmäßig Apps im Kompatibilitätsmodus ausführen",
"UPRIGHT_SCREEN_FIX": "Bildschirm-Drehkorrektur",
"DOUBLE_CURSOR_FIX": "Doppelter Cursor Fix",
"SCREEN_RENDER_DOWN": "Bildschirm bei niedrigerer Auflösung rendern",
"UPRIGHT_SCREEN_FIX_HELP": "Behebt hochstehende Bildschirme auf einigen Desktops",
"DOUBLE_CURSOR_FIX_HELP": "Aktivieren Sie dies, wenn Sie 2 Cursor sehen",
"CLICK_FREEZE_TIME_MS_HELP": "Hilft bei der Präzision von Doppelklicks",
"LEFT_HANDED_MOUSE_HELP": "Verwenden Sie diese Option, wenn die Maustasten vertauscht sind",
"BLOCK_GAME_INPUT_HELP": "Blockiert alle Eingaben, wenn ein Overlay angefahren wird",
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Blockiere die Eingabe nicht, wenn die Überwachung aktiviert ist",
"USE_SKYBOX_HELP": "Zeige einen Skybox, wenn keine Szenen-App oder Passthrough vorhanden ist",
"USE_PASSTHROUGH_HELP": "Aktiviere Passthrough, falls die XR-Laufzeitumgebung dies unterstützt",
"SCREEN_RENDER_DOWN_HELP": "Hilft bei Aliasing auf hochauflösenden Bildschirmen",
"SETS_ON_WATCH": "Sets auf der Watch",
"TROUBLESHOOTING": "Fehlerbehebung",
"CLEAR_SAVED_STATE": "Gespeicherten Zustand löschen",
"CLEAR_PIPEWIRE_TOKENS": "PipeWire Tokens löschen",
"DELETE_ALL_CONFIGS": "Konfiguration löschen",
"RESTART_SOFTWARE": "Software neu starten",
"CLEAR_SAVED_STATE_HELP": "Sets und Overlay-Positionen zurücksetzen",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Bildschirmauswahl beim nächsten Start abfragen",
"DELETE_ALL_CONFIGS_HELP": "Entfernen Sie alle Konfigurationsdateien aus conf.d",
"RESTART_SOFTWARE_HELP": "Einstellungen anwenden, die einen Neustart erfordern",
"CAPTURE_METHOD": "Wayland-Bildschirmaufnahme",
"CAPTURE_METHOD_HELP": "Versuchen Sie, dies zu ändern, wenn Sie\nschwarze oder fehlerhafte Bildschirme erleben",
"KEYBOARD_MIDDLE_CLICK": "Keyboard-Mittelklick",
"KEYBOARD_MIDDLE_CLICK_HELP": "Modifikator bei Eingabe mit violettem Laser",
"OPTION": {
"AUTO": "Automatisch",
"AUTO_HELP": "Bildschirmkopie GPU falls unterstützt,\nansonsten PipeWire GPU.",
"PIPEWIRE_HELP": "Schnelle GPU-Erfassung,\nStandard auf allen Desktops.",
"PW_FALLBACK_HELP": "Langsame Methode mit hoher CPU-Auslastung.\nVersuchen Sie es, falls PipeWire GPU nicht funktioniert.",
"SCREENCOPY_GPU_HELP": "Schnell, keine Bildschirmfreigabe-Popups.\nFunktioniert mit: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Langsam, keine Bildschirmfreigabe-Popups.\nFunktioniert mit: Hyprland, Niri, River, Sway",
"NONE": "Keine",
"HMD_PINCH": "HMD + Kneifen",
"EYE_PINCH": "Auge + Kneifen",
"EYE_ONLY": "Nur Auge",
"HMD_ONLY": "Nur HMD",
"NONE_INPUT_HELP": "Maus und Tastatur nicht emulieren.\nEs wird nicht möglich sein, mit Displays zu interagieren.",
"UINPUT": "Gerätesimulation",
"UINPUT_HELP": "Verwendet das uinput-Modul, um ein Gerät zu emulieren.\nIhr Benutzer muss in der Gruppe „input“ sein.\nBekannt dafür, auf den meisten Desktops gut zu funktionieren.",
"WL_VIRTUAL": "Wayland-virtueller Input",
"WL_VIRTUAL_HELP": "Sendet Ereignisse an den Wayland-Compositor unter Verwendung von\nzwlr_virtual_pointer und zwp_virtual_keyboard.\nFunktioniert nur zuverlässig auf einigen Desktops.\nFunktioniert NICHT auf KDE, GNOME oder COSMIC."
}, },
"AUTOSTART_APPS": "Anwendungen, die beim Start ausgeführt werden sollen", "ASPECT_TITLE": "Seitenverhältnis",
"HANDSFREE_POINTER": "Freihändige Modus", "AUTOSTART": "Automatisch beim Start ausführen",
"HANDSFREE_POINTER_HELP": "Eingabe, die bei Bewegung\nder Controller verwendet wird, wenn diese nicht verfügbar sind.\nLinkes Kneifen greift, rechtes klickt.", "LAUNCH": "Starten",
"UI_GRADIENT_INTENSITY": "UI-Verlaufsintensität", "MODE": {
"RESET_PLAYSPACE": "Spielbereich zurücksetzen", "CAGE": "Kompatibilitätsmodus (Cage)",
"RESET_PLAYSPACE_HELP": "Den Abstand des Spielbereichs zurücksetzen.", "NATIVE": "Nativer Modus"
"BLOCK_POSES_ON_KBD_INTERACTION": "Posen beim Interagieren mit der Tastatur blockieren", },
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Verhindert, dass das Spiel Posen empfängt, wenn die Tastatur angefahren wird und „Spieleingabe blockieren“ aktiviert ist", "RES_TITLE": "Auflösung"
"LANGUAGE": "Sprache", },
"REQUIRES_RESTART": "Erfordert Neustart", "APP_SETTINGS": {
"GRID_OPACITY": "Bodenraster-Undurchsichtigkeit", "ALLOW_SLIDING": "Stick-Interaktion beim Greifen",
"GRID_OPACITY_HELP": "Undurchsichtigkeit des Bodenrasters, wenn der Skybox aktiviert ist", "ANIMATION_SPEED": "UI-Animationsgeschwindigkeit",
"BROWSE_ONLINE_CATALOG": "Online-Katalog durchsuchen...", "AUTOSTART_APPS": "Beim Start ausführen",
"BROWSE_SKYMAPS": "Skymaps durchsuchen", "BLOCK_GAME_INPUT": "Game-Input blockieren",
"COLOR_KEYING": "Farbschlüsselung", "BLOCK_GAME_INPUT_HELP": "Blockiert alle Eingaben, wenn ein Overlay fokussiert ist",
"NO_SKYMAPS_FOUND": "Keine Skymaps gefunden", "BLOCK_GAME_INPUT_IGNORE_WATCH": "Uhr beim Blockieren der Eingabe ignorieren",
"SELECT_VARIANT": "Variante auswählen", "BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Eingabe nicht blockieren, wenn die Handgelenk-Uhr fokussiert ist",
"SHOW_WELCOME_SCREEN": "Begrüßungsbildschirm anzeigen", "BLOCK_POSES_ON_KBD_INTERACTION": "Posen bei Tastaturinteraktion blockieren",
"SKYBOX": "Skybox", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Verhindert die Übertragung von Posen an das Spiel, wenn die Tastatur fokussiert ist und „Spielsteuerung blockieren“ aktiviert ist",
"SKYMAP_ALREADY_DOWNLOADED": "Diese Skymap wurde bereits heruntergeladen. Wählen Sie die gewünschte Aktion aus.",
"WATCH_VIEW_ANGLE": "Betrachtungswinkel der Watch",
"WATCH_VIEW_ANGLE_HELP": "Steuerung, wie die Watch ausgeblendet wird",
"BINDINGS": { "BINDINGS": {
"COMP": { "COMP": {
"CLICK": "Klicken", "CLICK": "Klicken",
"FORCE": "Kraft", "FORCE": "Druckkraft",
"TOUCH": "Berührung", "TOUCH": "Berühren",
"VALUE": "Wert", "VALUE": "Wert",
"PROXIMITY": "Nähe", "PROXIMITY": "Nähe",
"X_AXIS": "X-Achse", "X_AXIS": "X-Achse",
@ -116,203 +58,292 @@
}, },
"TYPE": { "TYPE": {
"BUMPER": "Bumper", "BUMPER": "Bumper",
"DPAD_UP": "D-Pad oben", "DPAD_UP": "Steuerkreuz oben",
"DPAD_DOWN": "D-Pad Runter", "DPAD_DOWN": "Steuerkreuz unten",
"DPAD_LEFT": "D-Pad Links", "DPAD_LEFT": "Steuerkreuz links",
"DPAD_RIGHT": "D-Pad Rechts", "DPAD_RIGHT": "Steuerkreuz rechts",
"JOYSTICK": "Joystick", "JOYSTICK": "Joystick",
"MENU": "Menü", "MENU": "Menü",
"SHOULDER": "Schulter", "SHOULDER": "Schulterknopftaste",
"SQUEEZE": "Greifen", "SQUEEZE": "Griff",
"SYSTEM": "System", "SYSTEM": "System",
"THUMBREST": "Daumenuflage", "THUMBREST": "Daumenauflage",
"THUMBSTICK": "Thumbstick", "THUMBSTICK": "Thumbstick",
"TRACKPAD": "Trackpad", "TRACKPAD": "Trackpad",
"TRIGGER": "Trigger", "TRIGGER": "Trigger",
"VIEW": "Ansehen" "VIEW": "View"
}, },
"CLICK": { "CLICK": {
"ANY": "Beliebig", "ANY": "Beliebig",
"DOUBLE": "Doppeltippen", "DOUBLE": "Doppeltippen",
"TRIPLE": "Dreifach-Tippen", "TRIPLE": "Dreifachklick",
"TYPE": "Anzahl der Taps" "TYPE": "Anzahl der Klicks"
}, },
"ACTION": { "ACTION": {
"CLICK": "Klick*", "CLICK": "Klick*",
"GRAB": "Greifen*", "GRAB": "Greifen*",
"ALT_CLICK": "Benutzerdefiniertes Shell-Exec (alt_click in Konfiguration festlegen)", "ALT_CLICK": "Benutzerdefinierter Shell-Befehl (alt_click in Config festlegen)",
"SHOW_HIDE": "Anzeigen, ausblenden, neuzentrieren*", "SHOW_HIDE": "Anzeigen, ausblenden, zentrieren*",
"TOGGLE_DASHBOARD": "Dashboard umschalten", "TOGGLE_DASHBOARD": "Dashboard umschalten",
"SPACE_DRAG": "Playspace-Drag", "SPACE_DRAG": "Playspace ziehen",
"SPACE_ROTATE": "Playspace rotieren", "SPACE_ROTATE": "Playspace rotieren",
"SPACE_RESET": "Playspace zurücksetzen", "SPACE_RESET": "Playspace zurücksetzen",
"CLICK_MODIFIER_RIGHT": "Rechtsklick-Modifikator", "CLICK_MODIFIER_RIGHT": "Rechtsklick-Modifikator",
"CLICK_MODIFIER_MIDDLE": "Mittlere Maustaste-Modifier", "CLICK_MODIFIER_MIDDLE": "Mittelklick-Modifier",
"MOVE_MOUSE": "Maus bewegen (falls standardmäßig deaktiviert)", "MOVE_MOUSE": "Maus bewegen (falls standardmäßig aus)",
"SCROLL": "Scrollen*" "SCROLL": "Scrollen*"
}, },
"LEFT": "Links", "LEFT": "Links",
"RIGHT": "Rechts", "RIGHT": "Rechts",
"COMPONENT": "Auslösetyp", "COMPONENT": "Aktivierungsart",
"SUBPATH": "Betätigungskontrolle", "SUBPATH": "Bedienelement",
"THRESHOLD": "Aktivieren, wenn oberer Wert überschritten\nDeaktivieren, wenn unterer Wert unterschritten" "THRESHOLD": "Aktivieren bei Überschreiten des oberen Wertes\nDeaktivieren bei Unterschreiten des unteren Wertes"
}, },
"BROWSE_ONLINE_CATALOG": "Online-Katalog durchsuchen...",
"BROWSE_SKYMAPS": "Skymaps durchsuchen",
"CAPTURE_METHOD": "Bildschirmaufnahme-Methode",
"CAPTURE_METHOD_HELP": "Ändere dies, wenn du schwarze oder\nfehlerhafte Bildschirme hast",
"COLOR_KEYING": "Farbschlüsselung",
"COLOR_PALETTE": "Farbpalette",
"COLOR_PALETTE_HELP": "Zum Durchsuchen der Farbpaletten klicken.\nFür eigene Paletten siehe Website!",
"COLOR_PALETTES": "Farbpaletten",
"COLOR_PALETTE_CURRENT": "Aktuelles Thema.",
"COLOR_PALETTE_CUSTOM_URL": "Eigenes Theme hinzufügen!",
"COLOR_PALETTE_CUSTOM_URL2": "Klicken zum Öffnen des Web-Handbuchs.",
"COLOR_PALETTE_ACTIVATE": "Zum Anwenden dieses Themes klicken.",
"CLEAR_PIPEWIRE_TOKENS": "PipeWire-Token löschen",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Bildschirmauswahl beim nächsten Start abfragen",
"CLEAR_SAVED_STATE": "Gespeicherten Zustand löschen",
"CLEAR_SAVED_STATE_HELP": "Sets & Overlay-Positionen zurücksetzen",
"CLICK_FREEZE_TIME_MS": "Klick-Freeze-Zeit (ms)",
"CLICK_FREEZE_TIME_MS_HELP": "Hilft bei der Doppelklick-Präzision",
"CLOCK_12H": "12-Stunden-Uhr",
"CONTROLS": "Steuerung",
"DELETE_ALL_CONFIGS": "Konfiguration zurücksetzen",
"DELETE_ALL_CONFIGS_HELP": "Alle Konfigurationsdateien aus conf.d entfernen",
"DOUBLE_CURSOR_FIX": "Doppelkursor-Fix",
"DOUBLE_CURSOR_FIX_HELP": "Aktivieren, wenn zwei Cursor sichtbar sind",
"DEFAULT_OVERLAY_SCALE": "Standardgröße der Overlays",
"DEFAULT_OVERLAY_SCALE_HELP": "Neue Overlays in dieser Größe spawnen.",
"DEFAULT_CURVATURE": "Standard-Overlay-Krümmung",
"DEFAULT_OPACITY": "Standard-Overlay-Undurchsichtigkeit",
"DEFAULT_POSITIONING": "Standard-Positionierung der Overlays",
"OVERLAY_DEFAULTS_HELP": "Gilt nur für neue Overlays",
"ENABLED": "Aktiviert", "ENABLED": "Aktiviert",
"INPUT_EMULATION_METHOD": "Methode zur Eingabeemulation", "FEATURES": "Features",
"INPUT_EMULATION_METHOD_HELP": "Versuchen Sie dies zu ändern, falls Maus- oder\nTastatureingaben nicht registriert werden.", "FOCUS_FOLLOWS_MOUSE_MODE": "Mausbewegung bei Trigger-Berührung",
"INPUT_PROFILES": "Eingabesteuerungen ändern", "HANDSFREE_POINTER": "Freisprechmodus",
"INPUT_PROFILES_HELP": "OpenXR-Controller-Eingabebindungen", "HANDSFREE_POINTER_HELP": "Eingabe, wenn keine Motion-Controller verfügbar sind.\nLinkes Zusammenkneifen zum Greifen, rechtes zum Klicken.",
"HANDSFREE_ALT_TAB": "Ausrichtung des App-Switchers",
"HANDSFREE_ALT_TAB_HELP": "Super+X halten, auf das gewünschte Fenster zielen und dann loslassen, um den Fokus zu wechseln.",
"HIDE_GRAB_HELP": "Greifhilfe ausblenden",
"HIDE_USERNAME": "Benutzernamen ausblenden",
"INPUT_EMULATION_METHOD": "Input-Emulationsmethode",
"INPUT_EMULATION_METHOD_HELP": "Hier ändern, falls Maus- oder\nTastatureingaben nicht registriert werden.",
"INPUT_CAPTURE_METHOD": "Eingabemethode",
"INPUT_CAPTURE_METHOD_HELP": "Ermöglicht die Nutzung physischer Peripheriegeräte in WayVR.\n Super+Z: Eingabe zwischen WayVR und echtem Desktop wechseln\n Super+X: Zwischen WayVR-Apps wechseln",
"INPUT_PROFILES": "Eingabebindungen ändern",
"INPUT_PROFILES_HELP": "OpenXR-Controller-Belegungen",
"INVERT_SCROLL_DIRECTION_X": "Horizontalen Scrollrichtung umkehren",
"INVERT_SCROLL_DIRECTION_Y": "Vertikale Scrollrichtung umkehren",
"KEYBOARD_MIDDLE_CLICK": "Tastatur-Mittelklick",
"KEYBOARD_MIDDLE_CLICK_HELP": "Modifier-Taste bei der Eingabe\nmit dem lila Laser",
"KEYBOARD_SOUND_ENABLED": "Tastatursounds",
"LANGUAGE": "Sprache",
"LEFT_HANDED_MOUSE": "Linkshänder-Maus",
"LEFT_HANDED_MOUSE_HELP": "Nutze dies, wenn die Maustasten vertauscht sind",
"LONG_PRESS_DURATION": "Langpress-Dauer",
"LOOK_AND_FEEL": "Aussehen & Gefühl",
"MISC": "Verschiedenes",
"NOTIFICATIONS_ENABLED": "Benachrichtigungen aktivieren",
"NOTIFICATIONS_SOUND_ENABLED": "Benachrichtigungstöne",
"NOT_SUPPORTED": "Nicht unterstützt", "NOT_SUPPORTED": "Nicht unterstützt",
"ENABLE_WATCH": "Watch aktivieren", "NO_SKYMAPS_FOUND": "Keine Skymaps gefunden",
"SPACE_DRAG": "Space-drag", "OPAQUE_BACKGROUND": "Undurchsichtiger Hintergrund",
"OPTION": {
"ANCHORED_HELP": "Bewegt sich mit dem Zentrumsmarker. Empfohlen.",
"FLOATING_HELP": "Bewegt sich unabhängig, zentriert sich neu.\nLeicht zu verlieren; nicht empfohlen.",
"STATIC_HELP": "Bleibt relativ zur Welt an Ort und Stelle.",
"AUTO": "Automatisch",
"AUTO_HELP": "ScreenCopy GPU, falls unterstützt, \nansonsten PipeWire GPU.",
"EYE_ONLY": "Augenlaser",
"EYE_PINCH": "Blick + Pinch",
"HMD_ONLY": "HMD-Laser",
"HMD_PINCH": "HMD + Greifen",
"NONE": "Keine",
"NONE_INPUT_HELP": "Keine Maus- und Tastatur-Emulation.\nInteraktion mit Bildschirmen nicht möglich.",
"NONE_INPUT_CAPTURE_HELP": "Keine Maus- und Tastaturerfassung.\nPhysische Maus oder Tastatur können in\nWayVR gestarteten Apps nicht genutzt werden.",
"PIPEWIRE_HELP": "Schnelle GPU-Erfassung,\nStandard auf allen Desktops.",
"PW_FALLBACK_HELP": "Langsame Methode mit hoher CPU-Auslastung.\nAusprobieren, falls PipeWire GPU nicht funktioniert",
"SCREENCOPY_GPU_HELP": "Schnell, ohne Popups beim Bildschirmausschnitt.\nFunktioniert bei: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Langsam, keine Pop-ups beim Bildschirmteilen.\nFunktioniert mit: Hyprland, Niri, River, Sway",
"UINPUT": "Geräteemulation",
"UINPUT_HELP": "Nutzt das uinput-Modul zur Geräteemulation.\nFunktioniert auf den meisten Desktops gut.",
"EVDEV_HELP": "Eingabegeräte für die exklusive Nutzung erfassen.\nDein Benutzer muss Mitglied der Gruppe \"input\" sein.",
"WL_VIRTUAL": "Wayland-virtueller Input",
"WL_VIRTUAL_HELP": "Sende Ereignisse an den Wayland-Compositor mittels\nzwlr_virtual_pointer und zwp_virtual_keyboard.\nFunktioniert nur auf einigen Desktops zuverlässig.\nFunktioniert NICHT unter KDE, GNOME oder COSMIC."
},
"POINTER_ACCELERATION": "Mausbeschleunigung",
"POINTER_ACCELERATION_HELP": "An: Adaptive Mausbeschleunigung\nAus: Konstante Geschwindigkeit",
"POINTER_LERP_FACTOR": "Zeiger-Glättung",
"POINTER_SPEED": "Mausgeschwindigkeit",
"REQUIRES_RESTART": "Neustart erforderlich",
"RESET_PLAYSPACE": "Playspace zurücksetzen",
"RESET_PLAYSPACE_HELP": "Playspace-Versatz zurücksetzen.",
"SAVE_PLAYSPACE_CENTER": "Playspace-Zentrum speichern",
"SAVE_PLAYSPACE_CENTER_HELP": "Nutze aktuellen Playspace für die Playspace-Reset-Belegung.",
"RESET_PLAYSPACE_CENTER": "Playspace-Zentrum zurücksetzen",
"RESET_PLAYSPACE_CENTER_HELP": "Vorheriges Playspace-Zentrum zurücksetzen.",
"RESTART_SOFTWARE": "Software neu starten",
"RESTART_SOFTWARE_HELP": "Einstellungen übernehmen, die einen Neustart erfordern",
"ROUND_MULTIPLIER": "Abrundung der UI-Kanten",
"SCREEN_RENDER_DOWN": "Bildschirm mit niedrigerer Auflösung rendern",
"SCREEN_RENDER_DOWN_HELP": "Hilft gegen Treppeneffekte bei hochauflösenden Bildschirmen",
"SCROLL_SPEED": "Scrollgeschwindigkeit",
"SELECT_VARIANT": "Variante wählen",
"SNAP_ANGLE_DEG": "Snap-Winkel für Fenster-Neigung & Rollen",
"SNAP_ANGLE_DEG_HELP": "Gegriffene Fenster rasten auf der Nick- und Rollachse in diesem Winkel ein.",
"ENABLE_WATCH": "Handgelenk-Uhr aktivieren",
"SETS_ON_WATCH": "Sets auf Handgelenk-Uhr",
"SHOW_WELCOME_SCREEN": "Willkommensbildschirm anzeigen",
"SKYBOX": "Skymap",
"SKYMAP_ALREADY_DOWNLOADED": "Diese Skymap ist bereits heruntergeladen. Wähle eine Aktion aus.",
"SPACE_DRAG": "Playspace",
"SPACE_DRAG_MULTIPLIER": "Space-Drag-Multiplikator",
"SPACE_DRAG_AFFECTS_WORLD": "Overlays bei Playspace-Verschiebung zurücklassen",
"SPACE_DRAG_UNLOCKED": "Space-drag auf allen Achsen erlauben",
"SPACE_GRAVITY_DAMPING": "Dämpfung", "SPACE_GRAVITY_DAMPING": "Dämpfung",
"SPACE_GRAVITY_DAMPING_HELP": "Künstlicher Widerstand, um die Bewegung zu verlangsamen. 0,1 - hoher Widerstand, 1,0 - kein Widerstand", "SPACE_GRAVITY_DAMPING_HELP": "Künstlicher Widerstand zur Verlangsamung der Bewegung. 0,1 hoher Widerstand, 1,0 kein Widerstand",
"SPACE_GRAVITY_FLING_STRENGTH": "Wurfstärke", "SPACE_GRAVITY_FLING_STRENGTH": "Schleuderstärke",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Intensitätsmultiplikator der Schwerkraft-Abstoßungskraft nach dem Space-drag.\n0.0 - gar keine Bewegung, 2.0 - doppelte Intensität", "SPACE_GRAVITY_FLING_STRENGTH_HELP": "Intensitätsmultiplikator der Gravitationskraft nach dem Space-drag.\n0.0 - gar keine Bewegung, 2.0 - doppelte Intensität",
"SPACE_GRAVITY_GRAVITY": "Gravitation", "SPACE_GRAVITY_GRAVITY": "Gravitation",
"SPACE_GRAVITY_GRAVITY_HELP": "Betrag der Abwärtskraft. 0.0 - keine Schwerkraft", "SPACE_GRAVITY_GRAVITY_HELP": "Stärke der Abwärtskraft. 0.0 - keine Schwerkraft",
"SPACE_GRAVITY_GROUND_FRICTION": "Bodenreibung", "SPACE_GRAVITY_GROUND_FRICTION": "Bodenreibung",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Das Ausmaß der Reibung, das Sie verlangsamt, wenn Sie den Boden berühren.\n0.0 - keine Reibung (wie auf Eis), 1.0 - raue Oberfläche", "SPACE_GRAVITY_GROUND_FRICTION_HELP": "Reibung beim Kontakt mit dem Boden.\n0,0 - keine Reibung (wie auf Eis), 1,0 - raue Oberfläche",
"SPACE_GRAVITY_FLOOR_HEIGHT": "Bodenhöhe", "SPACE_GRAVITY_FLOOR_HEIGHT": "Bodenhöhe",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "Die Y-Position, an der sich der Boden befindet. Die Schwerkraft wird gestoppt, wenn Sie diese Höhe erreichen.", "SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "Die Y-Position des Bodens. Hier endet die Wirkung der Gravitation.",
"SAVE": "Speichern", "SPACE_ROTATE_UNLOCKED": "Playspace-Rotation auf allen Achsen erlauben",
"CANCEL": "Abbrechen", "TROUBLESHOOTING": "Fehlerbehebung",
"UI_GRADIENT_INTENSITY": "UI-Gradientenintensität",
"UPRIGHT_SCREEN_FIX": "Bildschirm-Ausrichtung korrigieren",
"UPRIGHT_SCREEN_FIX_HELP": "Korrgiert aufrecht ausgerichtete Bildschirme bei einigen Desktops",
"USE_PASSTHROUGH": "Passthrough aktivieren",
"USE_PASSTHROUGH_HELP": "Passthrough zulassen, falls die XR-Runtime dies unterstützt",
"USE_SKYBOX": "Skymap anzeigen",
"USE_SKYBOX_HELP": "Skymap anzeigen, wenn keine Scene-App oder Passthrough aktiv ist",
"WATCH_VIEW_ANGLE": "Sichtwinkel der Handgelenk-Uhr",
"WATCH_VIEW_ANGLE_HELP": "Steuere, wie die Uhr ausblendet",
"WHISPER": { "WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "Das ausgewählte Modell muss heruntergeladen werden.\nJetzt herunterladen?", "NEED_TO_DOWNLOAD_MODEL": "Das ausgewählte Modell muss heruntergeladen werden.\nJetzt herunterladen?",
"REMOVE_UNUSED_MODELS": "Sie schalten die Sprache-zu-Text-Funktion aus.\nMöchten Sie die heruntergeladenen Whisper-Modelle entfernen, um Speicherplatz freizugeben?" "REMOVE_UNUSED_MODELS": "Du deaktivierst die Spracherkennungsfunktion.\nMöchtest du die heruntergeladenen Whisper-Modelle entfernen, um Speicherplatz freizugeben?"
}, },
"WHISPER_MODEL": "Sprach-zu-Text-Modell", "WHISPER_MODEL": "Sprache-zu-Text-Modell",
"WHISPER_MODEL_HELP": "Zu verwendendes Whisper-Modell.\nGrößere Modelle liefern genauere\nErgebnisse, verbrauchen jedoch mehr VRAM.", "WHISPER_MODEL_HELP": "Zu verwendendes Whisper-Modell.\nGrößere Modelle liefern präzisere\nErgebnisse, verbrauchen aber mehr VRAM.",
"DEFAULT_OVERLAY_SCALE": "Standardgröße des Overlays", "GRID_OPACITY": "Bodenraster-Deckkraft",
"DEFAULT_OVERLAY_SCALE_HELP": "Neue Overlays werden in dieser Skalierung erstellt.", "GRID_OPACITY_HELP": "Deckkraft des Bodengitters, wenn die Skymap aktiviert ist",
"COLOR_PALETTE": "Farbpalette", "XWAYLAND_BY_DEFAULT": "Apps standardmäßig im Kompatibilitätsmodus starten",
"COLOR_PALETTES": "Farbpaletten", "SAVE": "Speichern",
"COLOR_PALETTE_CURRENT": "Derzeit aktives Thema.", "CANCEL": "Abbrechen"
"COLOR_PALETTE_ACTIVATE": "Klicken Sie hier, um dieses Thema zu verwenden.",
"APPLY_CHANGES_RESTART": "WayVR neu starten, um die Änderungen zu übernehmen?",
"COLOR_PALETTE_HELP": "Klicken, um Farbpaletten zu durchsuchen.\nUm eigene zu erstellen, besuche die Webseite!",
"COLOR_PALETTE_CUSTOM_URL": "Füge dein eigenes benutzerdefiniertes Thema hinzu!",
"COLOR_PALETTE_CUSTOM_URL2": "Klicken Sie hier, um das Web-Handbuch zu öffnen.",
"SNAP_ANGLE_DEG": "Snap-Winkel für Fensterneigung und Rollwinkel",
"SNAP_ANGLE_DEG_HELP": "Gegriffene Fenster rasten in diesem Winkel auf der Nick- und Rollachse ein."
}, },
"HELLO": "Hallo!", "APPLICATION_LAUNCHER": "Programmstarter",
"AUDIO": {
"VOLUME": "Lautstärke",
"SETTINGS": "Audioeinstellungen",
"AUTO_SWITCH_TO_VR_AUDIO": "Automatisch auf VR-Audio umschalten",
"SPEAKERS": "Lautsprecher",
"MICROPHONES": "Mikrofone",
"CARDS": "Sound-Karten",
"SELECT_AUDIO_CARD_PROFILE": "Wählen Sie das Sound-Kartenprofil",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Keine VR-Lautsprecher gefunden. Schalten Sie diese manuell um.",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Kein VR-Mikrofon gefunden. Schalten Sie es manuell um.",
"FAILED_TO_SWITCH_MICROPHONE": "Fehler beim Wechseln des Mikrofons",
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofon erfolgreich umgeschaltet",
"SPEAKERS_SET_SUCCESSFULLY": "Lautsprecher erfolgreich umgeschaltet"
},
"ACTIONS": {
"RECENTER_PLAYSPACE": "Playspace neu zentrieren"
},
"POPUP_ADD_DISPLAY": {
"RESOLUTION": "Auflösung"
},
"WIDTH": "Breite",
"HEIGHT": "Höhe",
"HIDE": "Verbergen",
"REMOVE": "Entfernen",
"SHOW": "Anzeigen",
"FAILED_TO_LAUNCH_APPLICATION": "Fehler beim Starten der Anwendung:",
"APPLICATION_STARTED": "Anwendung gestartet", "APPLICATION_STARTED": "Anwendung gestartet",
"APPLICATIONS": "Anwendungen",
"AUDIO": {
"AUTO_SWITCH_TO_VR_AUDIO": "Automatisch auf VR-Audio umschalten",
"CARDS": "Soundkarten",
"FAILED_TO_SWITCH_MICROPHONE": "Mikrofonwechsel fehlgeschlagen",
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofon erfolgreich eingestellt",
"MICROPHONES": "Mikrofone",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Kein VR-Mikrofon gefunden. Manuell umschalten.",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Keine VR-Lautsprecher gefunden. Manuell umschalten.",
"SELECT_AUDIO_CARD_PROFILE": "Soundkartenprofil wählen",
"SETTINGS": "Audio-Einstellungen",
"SPEAKERS": "Lautsprecher",
"SPEAKERS_SET_SUCCESSFULLY": "Lautsprecher erfolgreich eingestellt",
"VOLUME": "Lautstärke"
},
"CLOSE_WINDOW": "Fenster schließen", "CLOSE_WINDOW": "Fenster schließen",
"CREATION_DATE": "Erstellungsdatum",
"DEBUG_INFO": "Debug-Infos",
"DISPLAY_BRIGHTNESS": "Displayhelligkeit",
"DONATE": {
"SUPPORT_US": "Unterstützt uns",
"DESCRIPTION": "Wir sind ein kleines Team aus 2 Entwicklern, die WayVR in ihrer Freizeit bauen. Wenn dir die Software gefällt, unterstütze uns bitte jede Spende hilft uns dabei, weiterzumachen.",
"THANK_YOU_WAYVR": "Danke vom WayVR-Team!",
"BUTTON_TOOLTIP": "Via Open Collective spenden",
"CURRENT_SUPPORTERS": "Aktuelle Unterstützer",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Unterstützt von {USER}|Besonderer Dank an {USER}|Gesponsert von {USER}|Ermöglicht durch {USER}|Getragen von Community-Mitgliedern wie {USER}|Mit Hilfe von {USER}|Aufrechterhalten durch {USER}|Ein Beitrag von {USER}|Finanziert durch {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Kaffee spendiert von {USER}|Angetrieben von {USER}|Ein großes Shoutout an {USER}!|{USER} hält uns am Laufen|Mit {USER} wachsen wir weiter|{USER} hält die Server stabil|In voller Dankbarkeit gegenüber {USER}|Power-up durch {USER}|Unterstützt von Freunden wie {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Unterstützt von Legenden wie {USER}|Koffein-Zufuhr gesichert durch {USER}|Eine echte Legende: {USER}|Unser Held des Tages: {USER}|Ein absoluter Superstar: {USER}|Bezahlt gerade die Stromrechnung: {USER}|Der Retter unserer Nerven: {USER}|Der Ruhepol im Chaos: {USER}|Kaffee-zu-Code-Konverter: {USER}|Hält die Production stabil: {USER}|Die eine und einzige(r): {USER}|Bezwinger des dmabuf-Buffers: {USER}"
},
"DOWNLOAD": "Herunterladen",
"DOWNLOADER": "Downloader",
"WELCOME": {
"ALL_SET": "Alles bereit!",
"BASICS": "Diese Grundlagen ermöglichen dir einen einfachen Start mit WayVR.",
"CENTER_MARKER": "Die Zentrierungsmarkierung erscheint beim Recentrieren vor dir. Platziere Overlays darum herum!",
"DOUBLE_PRESS_TO_TOGGLE": "Drücke B (beim Index) oder Y (bei Meta) doppelt, um dein Set anzuzeigen, neu zu zentrieren oder auszublenden. Probier es jetzt aus.",
"FEATURES_DOCUMENTATION": "Es gibt viele weitere anpassbare Funktionen. Weitere Informationen findest du in der Dokumentation unter",
"FINISH_TUTORIAL": "Tutorial beenden",
"GRAB_BOTH_HANDS": "Greif mit beiden Händen zu, wenn du ein bestimmtes Overlay in deinem Set verschieben willst.",
"GRAB_ONE_HAND": "Greife mit einer Hand zu, um dein Set zu bewegen.",
"GREETING": "Hallo!",
"GUIDE_INTRO": "Lass uns dich durch deine ersten Schritte führen.",
"LASER_COLORS": "Laserfarben",
"LASER_FUNCTIONALITY": "Vieles in WayVR hängt davon ab, welche Laserfarbe zur Interaktion mit einem UI-Element genutzt wird. Du musst die Schaltflächen nicht drücken, einfach nur berühren!",
"LAST_PAGE_INFO": "Dieses Tutorial wird nicht mehr angezeigt, sobald du die letzte Seite erreicht hast.",
"LOOK_AT_LEFT_WRIST": "Schau auf dein linkes Handgelenk. Das ist deine Handgelenk-Uhr.",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Mittelklick-Modus: Lilafarbener Laser",
"MOVING_YOUR_SET": "Set verschieben",
"NEXT_BUTTON": "Drücke unten auf „Weiter“, um zu starten.",
"REGULAR_MODE_BLUE_LASER": "Normalmodus: Blauer Laser",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Positioniere dieses Fenster neu, indem du die Grip-Taste deines Controllers benutzt.",
"RIGHT_CLICK_MODE_ORANGE_LASER": "Rechtsklick-Modus: Oranger Laser",
"THANKS_FOR_INSTALLING": "Vielen Dank für die Installation von WayVR!",
"WATCH": "Handgelenk-Uhr",
"WORKING_SET": "Aktives Set"
},
"DOWNLOAD_AGAIN": "Erneut herunterladen",
"DOWNLOADING_FILE": "Datei wird heruntergeladen...",
"FAILED_TO_LAUNCH_APPLICATION": "Starten der Anwendung fehlgeschlagen:",
"GAME_LAUNCHED": "Spiel gestartet",
"GAME_LIST": { "GAME_LIST": {
"NO_GAMES_FOUND": "Keine Spiele gefunden", "NO_GAMES_FOUND": "Keine Spiele gefunden",
"RUNNING_GAMES_LIST": "Liste der laufenden Spiele" "RUNNING_GAMES_LIST": "Liste der laufenden Spiele"
}, },
"TERMINATE_PROCESS": "Prozess beenden", "GAMES": "Spiele",
"GAME_LAUNCHED": "Spiel gestartet", "GENERAL_SETTINGS": "Allgemeine Einstellungen",
"APP_LAUNCHER": { "GETTING_STARTED": "Erste Schritte",
"MODE": { "HEIGHT": "Höhe",
"NATIVE": "Nativer Modus", "HELLO": "Hallo!",
"CAGE": "Kompatibilitätsmodus (Cage)" "HELLO_USER": "Hallo, {USER}!",
}, "HIDE": "Ausblenden",
"RES_TITLE": "Auflösung", "HOME_SCREEN": "Home",
"ASPECT_TITLE": "Seitenverhältnis", "MODIFICATION_DATE": "Änderungsdatum",
"ASPECT": { "MONADO_RUNTIME": "Monado Runtime",
"WIDE": "Breit", "LOADING": "Lädt...",
"SEMI_WIDE": "Halb-breit", "POPUP_ADD_DISPLAY": {
"SQUARE": "Quadratisch", "RESOLUTION": "Auflösung"
"SEMI_TALL": "Halbhoch", },
"TALL": "Hoch" "PROCESS": {
}, "FORCE_KILL": "Sofort beenden",
"POS_TITLE": "Positionierung", "STOP": "Beenden"
"POS": {
"FLOATING": "Schwebend",
"ANCHORED": "Verankert",
"STATIC": "Statisch",
"FLOATING_HELP": "Bewegt sich unabhängig, zentriert sich bei Anzeige neu.",
"ANCHORED_HELP": "Bleibt relativ zur Mittelmarkierung an Ort und Stelle.",
"STATIC_HELP": "Keine Set zugeordnet. Wird nicht zentriert."
},
"AUTOSTART": "Automatisch beim Start ausführen",
"LAUNCH": "Starten"
}, },
"DISPLAY_BRIGHTNESS": "Bildschirmhelligkeit",
"PROCESS_LIST": "Prozessliste", "PROCESS_LIST": "Prozessliste",
"REFRESH": "Aktualisieren", "REFRESH": "Aktualisieren",
"PROCESS": { "REMOVE": "Entfernen",
"STOP": "Stopp",
"FORCE_KILL": "Erzwinge Beenden"
},
"DEBUG_INFO": "Debug-Informationen",
"CREATION_DATE": "Erstellungsdatum",
"DOWNLOADER": "Downloader",
"DOWNLOAD_AGAIN": "Erneut herunterladen",
"DOWNLOADING_FILE": "Datei wird heruntergeladen...",
"GETTING_STARTED": "Erste Schritte",
"MODIFICATION_DATE": "Änderungsdatum",
"LOADING": "Laden...",
"APPLY": "Anwenden", "APPLY": "Anwenden",
"RELOAD_FROM_DISK": "Von Festplatte neu laden", "RELOAD_FROM_DISK": "Von Festplatte neu laden",
"SETTINGS": "Einstellungen",
"SHOW": "Anzeigen",
"TARGET_PATH": "Zielpfad", "TARGET_PATH": "Zielpfad",
"TERMINATE_PROCESS": "Prozess beenden",
"VERSION": "Version", "VERSION": "Version",
"DONATE": { "WIDTH": "Breite",
"SUPPORT_US": "Unterstütze uns", "PINNED_APPS": "Angeheftete Anwendungen",
"DESCRIPTION": "Wir sind ein kleines Team aus zwei Entwicklern, die WayVR in ihrer Freizeit bauen. Wenn Ihnen die Nutzung dieser Software Spaß macht, unterstützen Sie uns bitte jede Spende hilft uns, weiterzumachen.", "SAVED_TO_FAVOURITES": "Zu den angehefteten Anwendungen hinzugefügt",
"BUTTON_TOOLTIP": "Spenden über Open Collective", "ADD_TO_FAVOURITES": "Zu angehefteten Anwendungen hinzufügen",
"CURRENT_SUPPORTERS": "Aktuelle Unterstützer", "ADD_TO_FAVOURITES_HINT": "Voreinstellung speichern und an die App-Schublade anheften",
"THANK_YOU_WAYVR": "Vielen Dank vom WayVR-Team!" "REMOVE_FROM_FAVOURITES": "Aus angehefteten Anwendungen entfernen",
}, "EMPTY": "Leer"
"WELCOME": {
"ALL_SET": "Du bist startklar!",
"BASICS": "Diese Grundlagen ermöglichen Ihnen einen einfachen Einstieg in die Nutzung von WayVR.",
"FEATURES_DOCUMENTATION": "Es gibt viele weitere Funktionen, die es wert sind, angepasst zu werden. Weitere Informationen finden Sie in der Dokumentation unter",
"FINISH_TUTORIAL": "Tutorial beenden",
"GRAB_BOTH_HANDS": "Greifen Sie es mit beiden Händen, wenn Sie ein bestimmtes Overlay in Ihrem Set bewegen möchten.",
"GRAB_ONE_HAND": "Greife es mit einer Hand, um dein Set zu bewegen.",
"GREETING": "Hallo!",
"GUIDE_INTRO": "Lassen Sie sich durch Ihre ersten Schritte führen.",
"LASER_COLORS": "Laserfarben",
"LASER_FUNCTIONALITY": "Ein Großteil der Funktionalität in WayVR hängt davon ab, welche Laserfarbe verwendet wird, um mit einem UI-Element zu interagieren. Sie müssen diese Schaltflächen nicht drücken, berühren Sie sie einfach!",
"LAST_PAGE_INFO": "Dieses Tutorial wird nicht mehr angezeigt, sobald du die letzte Seite erreicht hast.",
"LOOK_AT_LEFT_WRIST": "Schau auf dein linkes Handgelenk. Das ist deine Watch.",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— Mittlere Maustaste-Modus: Lila Laser",
"MOVING_YOUR_SET": "Ihr Set wird verschoben",
"NEXT_BUTTON": "Drücke die Schaltfläche „Weiter“ unten, um zu beginnen.",
"REGULAR_MODE_BLUE_LASER": "— Regulärer Modus: Blauer Laser",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Positionieren Sie dieses Fenster neu, indem Sie die Greifaktion Ihres Controllers verwenden.",
"RIGHT_CLICK_MODE_ORANGE_LASER": "— Rechtsklick-Modus: Oranger Laser",
"THANKS_FOR_INSTALLING": "Vielen Dank für die Installation von WayVR!",
"WATCH": "Watch",
"WORKING_SET": "Arbeits-Set",
"DOUBLE_PRESS_TO_TOGGLE": "Drücke B (beim Index) oder Y (beim Meta) doppelt, um dein Set anzuzeigen, neu zu zentrieren oder auszublenden. Probier es jetzt aus.",
"CENTER_MARKER": "Der Zentrierungsmarker ist das, was bei der Neuzentrierung vor dir erscheint. Platziere Overlays darum herum!"
},
"DOWNLOAD": "Herunterladen",
"SAVED_TO_FAVOURITES": "Zu Favoriten hinzugefügt",
"ADD_TO_FAVOURITES": "Zu Favoriten hinzufügen",
"ADD_TO_FAVOURITES_HINT": "Voreinstellung speichern und an den App-Drawer anheften",
"REMOVE_FROM_FAVOURITES": "Aus Favoriten entfernen",
"EMPTY": "Leer",
"PINNED_APPS": "Angepinnte Anwendungen"
} }

View File

@ -0,0 +1,339 @@
DEFINITIONS.ANCHORED,Anchored,"A movement option that makes this window move together with the rest of the workspace. Emphasize the ""moving together"" part as opposed to ""not moving at all""."
DEFINITIONS.FLOATING,Floating,A movement option that lets this window float freely.
DEFINITIONS.STATIC,Static,"A movement option that keeps this window in place relative to the world origin. Emphasize the ""not moving at all"" part, as opposed to the ""moving together"" option which was previously translated as ${DEFINITIONS.ANCHORED}."
DEFINITIONS.SET,Set,A desktop workspace consisting of multiple windows.
DEFINITIONS.WATCH,Watch,Name of the small utility window that hovers around the user's wrist.
DEFINITIONS.DASHBOARD,Dashboard,Name of the window that acts as the main menu / control panel of the application.
DEFINITIONS.EDIT_MODE,Edit Mode,Name of the mode that allows the user to make various tweaks to the current workspace and its windows.
DEFINITIONS.SETTINGS,Settings,The title of the settings panel.
DEFINITIONS.KEYBOARD,Keyboard,Name of the virtual keyboard
DEFINITIONS.TASKBAR,Taskbar,"A long panel showing currently active programs & windows, workspaces and a clock."
DEFINITIONS.FEATURES,Features,The section title of the section panel that deals with software features.
DEFINITIONS.OVERLAY,Overlay,"An overlay window inside VR, similar to a ""desktop window"". Consider it a technical term."
DEFINITIONS.SKYMAP,Skymap,A 360 degree background image that surrounds the user.
DEFINITIONS.PLAYSPACE,Playspace,The VR play space that the user can adjust in different way. Technical term.
DEFINITIONS.D_PAD,D-pad ,Directional pad on a modern game controller. Technical term.
ACTIONS.RECENTER_PLAYSPACE,Re-center playspace,"Tooltip on a button (with recenter icon) in the bottom-left of the VR dashboard. The button resets the user's tracked playspace to the current physical location. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_LAUNCHER.ASPECT.SEMI_TALL,Semi-tall,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 2:3 vertical aspect ratio. Tooltip shows ""2:3""."
APP_LAUNCHER.ASPECT.SEMI_WIDE,Semi-wide,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 3:2 aspect ratio. Tooltip shows ""3:2""."
APP_LAUNCHER.ASPECT.SQUARE,Square,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 1:1 aspect ratio. Tooltip shows ""1:1""."
APP_LAUNCHER.ASPECT.TALL,Tall,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 9:16 vertical aspect ratio. Tooltip shows ""9:16""."
APP_LAUNCHER.ASPECT.WIDE,Wide,"Radio button in the App Launcher panel's Aspect section. Sets the window to a 16:9 aspect ratio (standard widescreen). Tooltip shows ""16:9""."
APP_LAUNCHER.ASPECT_TITLE,Aspect,"Section header label above a row of 5 radio buttons (Wide, Semi-wide, Square, Semi-tall, Tall) in the App Launcher panel. Controls the window aspect ratio for the selected app."
APP_LAUNCHER.AUTOSTART,Run automatically on startup,"Label on a checkbox in the App Launcher panel. When checked, the selected app will launch automatically when the Dash compositor starts."
APP_LAUNCHER.LAUNCH,Launch,Label on the primary (blue/primary color) button at the bottom of the App Launcher panel. Launches the selected app with the configured settings. Has a play icon next to it.
APP_LAUNCHER.MODE.CAGE,Compatibility mode (Cage),"Radio button option in the App Launcher panel's mode selector (next to ""Native mode""). Sets the app to run in Cage compatibility mode."
APP_LAUNCHER.MODE.NATIVE,Native mode,"Radio button option (default/checked) in the App Launcher panel's mode selector (next to ""Compatibility mode (Cage)""). Sets the app to run in native Wayland mode."
APP_LAUNCHER.RES_TITLE,Resolution,"Section header label in the App Launcher panel above a row of 4 radio buttons (1440p, 1080p, 720p, 480p). Controls the rendering resolution for the selected app."
APP_SETTINGS.ALLOW_SLIDING,Stick interaction during grab,Checkbox label in Settings > Features tab. Toggles whether analog stick input works while an overlay is grabbed/moved.
APP_SETTINGS.ANIMATION_SPEED,UI Animation speed,Slider label in Settings > Look & Feel tab. Controls the speed of UI transition animations (range 0.5-5.0).
APP_SETTINGS.AUTOSTART_APPS,Apps to run on startup,Category header in Settings. Label for the section listing apps configured to auto-launch on WayVR startup.
APP_SETTINGS.BLOCK_GAME_INPUT,Block game input,"Checkbox label in Settings > Features tab. When enabled, blocks all in-game input when an overlay is hovered."
APP_SETTINGS.BLOCK_GAME_INPUT_HELP,Blocks all input when an overlay is hovered,Tooltip text appearing next to the Block game input checkbox in Settings > Features.
APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH,Ignore watch when blocking input,"Checkbox label in Settings > Features tab. When enabled, hovering the wrist watch does not block game input. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH_HELP,Do not block input when watch is hovered,"Tooltip text next to the Ignore watch when blocking input checkbox. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION,Block poses when interacting with keyboard,Checkbox label in Settings > Features tab. Blocks game pose input when the on-screen keyboard is hovered (requires Block game input enabled).
APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION_HELP,Blocks the game from receiving poses when the keyboard is hovered and 'Block game input' is enabled,Tooltip explaining the Block poses when interacting with keyboard checkbox.
APP_SETTINGS.BINDINGS.COMP.CLICK,Click,Dropdown option in the controller bindings editor. Selects the Click component of a controller input.
APP_SETTINGS.BINDINGS.COMP.FORCE,Force,Dropdown option in the controller bindings editor. Selects the Force analog component (e.g. how hard a trigger is pressed).
APP_SETTINGS.BINDINGS.COMP.TOUCH,Touch,Dropdown option in the controller bindings editor. Selects the Touch component (whether a button is merely touched vs pressed).
APP_SETTINGS.BINDINGS.COMP.VALUE,Value,Dropdown option in the controller bindings editor. Selects the raw Value analog output of a component.
APP_SETTINGS.BINDINGS.COMP.PROXIMITY,Proximity,Dropdown option in the controller bindings editor. Selects the Proximity component (distance of controller from head/hand).
APP_SETTINGS.BINDINGS.COMP.X_AXIS,X axis,"Dropdown option in the controller bindings editor. Selects the X-axis analog value (e.g. thumbstick X, trackpad X)."
APP_SETTINGS.BINDINGS.COMP.Y_AXIS,Y axis,"Dropdown option in the controller bindings editor. Selects the Y-axis analog value (e.g. thumbstick Y, trackpad Y)."
APP_SETTINGS.BINDINGS.TYPE.BUMPER,Bumper,Dropdown option in the bindings editor. Maps to the Bumper controller subpath (upper shoulder button).
APP_SETTINGS.BINDINGS.TYPE.DPAD_UP,D-pad Up,"Dropdown option in the bindings editor. Maps to the D-pad up direction. ""D-pad"" was previously translated as ""${DEFINITIONS.D_PAD}""."
APP_SETTINGS.BINDINGS.TYPE.DPAD_DOWN,D-pad Down,"Dropdown option in the bindings editor. Maps to the D-pad down direction. ""D-pad"" was previously translated as ""${DEFINITIONS.D_PAD}"". ""D-pad Up"" was previously translated as ""${APP_SETTINGS.BINDINGS.TYPE.DPAD_UP}""."
APP_SETTINGS.BINDINGS.TYPE.DPAD_LEFT,D-pad Left,"Dropdown option in the bindings editor. Maps to the D-pad left direction. ""D-pad"" was previously translated as ""${DEFINITIONS.D_PAD}"". ""D-pad Up"" was previously translated as ""${APP_SETTINGS.BINDINGS.TYPE.DPAD_UP}""."
APP_SETTINGS.BINDINGS.TYPE.DPAD_RIGHT,D-pad Right,"Dropdown option in the bindings editor. Maps to the D-pad right direction. ""D-pad"" was previously translated as ""${DEFINITIONS.D_PAD}"". ""D-pad Up"" was previously translated as ""${APP_SETTINGS.BINDINGS.TYPE.DPAD_UP}""."
APP_SETTINGS.BINDINGS.TYPE.JOYSTICK,Joystick,Dropdown option in the bindings editor. Maps to the joystick subpath.
APP_SETTINGS.BINDINGS.TYPE.MENU,Menu,Dropdown option in the bindings editor. Maps to the Menu controller button.
APP_SETTINGS.BINDINGS.TYPE.SHOULDER,Shoulder,Dropdown option in the bindings editor. Maps to the Shoulder subpath (shoulder strap button).
APP_SETTINGS.BINDINGS.TYPE.SQUEEZE,Grip,Dropdown option in the bindings editor. Maps to the Squeeze component (controller grip action).
APP_SETTINGS.BINDINGS.TYPE.SYSTEM,System,Dropdown option in the bindings editor. Maps to the System controller subpath.
APP_SETTINGS.BINDINGS.TYPE.THUMBREST,Thumbrest,Dropdown option in the bindings editor. Maps to the thumbrest touch sensor.
APP_SETTINGS.BINDINGS.TYPE.THUMBSTICK,Thumbstick,"Dropdown option in the bindings editor. Maps to the thumbstick subpath. Different from ""Joystick"" which was previously translated as ""${APP_SETTINGS.BINDINGS.TYPE.JOYSTICK}""."
APP_SETTINGS.BINDINGS.TYPE.TRACKPAD,Trackpad,Dropdown option in the bindings editor. Maps to the trackpad subpath.
APP_SETTINGS.BINDINGS.TYPE.TRIGGER,Trigger,Dropdown option in the bindings editor. Maps to the trigger subpath.
APP_SETTINGS.BINDINGS.TYPE.VIEW,View,Dropdown option in the bindings editor. Maps to the View controller button.
APP_SETTINGS.BINDINGS.CLICK.ANY,Any,Dropdown option in the bindings editor. Selects any press click type (no double/triple tap requirement).
APP_SETTINGS.BINDINGS.CLICK.DOUBLE,Double-tap,Dropdown option in the bindings editor. Requires a double-tap on the selected button/component.
APP_SETTINGS.BINDINGS.CLICK.TRIPLE,Triple-tap,Dropdown option in the bindings editor. Requires a triple-tap on the selected button/component.
APP_SETTINGS.BINDINGS.CLICK.TYPE,Tap count,Tooltip for the click-type dropdown in the bindings editor. Indicates this dropdown controls how many taps are required.
APP_SETTINGS.BINDINGS.ACTION.CLICK,Click*,Label for the click action row in the controller bindings editor. The asterisk indicates it may have modifiers. Leave the '*' at the end.
APP_SETTINGS.BINDINGS.ACTION.GRAB,Grab*,Label for the grab action row in the bindings editor. Maps to the controller grab/grip action. Leave the '*' at the end.
APP_SETTINGS.BINDINGS.ACTION.ALT_CLICK,Custom shell exec (set alt_click in config),Label for the alt_click action row in the bindings editor. Triggers a custom shell command defined in config.
APP_SETTINGS.BINDINGS.ACTION.SHOW_HIDE,"Show, hide, recenter*",Label for the show_hide action row. Toggles overlay visibility and recenters the set. Leave the '*' at the end.
APP_SETTINGS.BINDINGS.ACTION.TOGGLE_DASHBOARD,Toggle dashboard,Label for the toggle_dashboard action row. Opens or closes the WayVR dashboard.
APP_SETTINGS.BINDINGS.ACTION.SPACE_DRAG,Playspace drag,"Label for the space_drag action row. Allows dragging the entire playspace/set of overlays. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.BINDINGS.ACTION.SPACE_ROTATE,Playspace rotate,"Label for the space_rotate action row. Allows rotating the entire playspace/set. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.BINDINGS.ACTION.SPACE_RESET,Playspace reset,"Label for the space_reset action row. Resets playspace to the original state. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.BINDINGS.ACTION.CLICK_MODIFIER_RIGHT,Right-click modifier,Label for the click_modifier_right action row. Maps a controller input to act as a right-click modifier.
APP_SETTINGS.BINDINGS.ACTION.CLICK_MODIFIER_MIDDLE,Middle-click modifier,Label for the click_modifier_middle action row. Maps a controller input to act as a middle-click modifier.
APP_SETTINGS.BINDINGS.ACTION.MOVE_MOUSE,Move mouse (if off by default),Label for the move_mouse action row. Maps controller input to mouse movement.
APP_SETTINGS.BINDINGS.ACTION.SCROLL,Scroll*,Label for the scroll action row. Maps controller input to scrolling. Leave the '*' at the end.
APP_SETTINGS.BINDINGS.LEFT,Left,Label in the bindings editor. Refers to the left controller/hand configuration.
APP_SETTINGS.BINDINGS.RIGHT,Right,Label in the bindings editor. Refers to the right controller/hand configuration.
APP_SETTINGS.BINDINGS.COMPONENT,Actuation type,"Tooltip for the component dropdown in the bindings editor. Asks user to select what type of actuation (click, touch, axis, etc.)."
APP_SETTINGS.BINDINGS.SUBPATH,Actuating control,Tooltip for the subpath dropdown in the bindings editor. Asks user to select which controller button/stick/trackpad to bind.
APP_SETTINGS.BINDINGS.THRESHOLD,"Activate when above upper value
Deactivate when below lower value",Tooltip for the threshold slider in the bindings editor. Explains the two-value threshold range for analog inputs.
APP_SETTINGS.BROWSE_ONLINE_CATALOG,Browse online catalog...,Button label in the color palettes popup. Opens a web browser to the WayVR online catalog.
APP_SETTINGS.BROWSE_SKYMAPS,Browse skymaps,"Button label in Settings > Skybox tab. Opens the skymap browser/list. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
APP_SETTINGS.CAPTURE_METHOD,Screen capture method,"Dropdown label in Settings > Miscellaneous tab. Selects the method for capturing the desktop screen (PipeWire, ScreenCopy, etc.)."
APP_SETTINGS.CAPTURE_METHOD_HELP,"Try changing this if you are
experiencing black or glitchy screens",Tooltip for the Wayland screen capture dropdown in Miscellaneous settings.
APP_SETTINGS.COLOR_KEYING,Color keying,Setting in the look-and-feel / color palette section. Enables or configures chroma-key style color filtering.
APP_SETTINGS.COLOR_PALETTE,Color palette,Button label in Settings > Look & Feel tab. Opens the color palette selection popup.
APP_SETTINGS.COLOR_PALETTE_HELP,"Click to browse color palettes.
To create custom ones, see website!",Tooltip for the Color palette button.
APP_SETTINGS.COLOR_PALETTES,Color palettes,Category/header label in the color palette popup.
APP_SETTINGS.COLOR_PALETTE_CURRENT,Currently active theme.,Label or tooltip showing which color palette is currently applied.
APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL,Add your own custom theme!,Button/label in the color palette popup for adding a custom theme via URL.
APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL2,Click to open web manual.,"Secondary label/button next to the custom URL input, linking to the web manual."
APP_SETTINGS.COLOR_PALETTE_ACTIVATE,Click to use this theme.,Tooltip or button label on a palette card to apply/activate that theme.
APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS,Clear PipeWire tokens,Button label in Settings > Troubleshooting tab. Clears stored PipeWire screen-selection tokens so the user is prompted again on next start.
APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS_HELP,Prompt for screen selection on next start,Tooltip explaining what clearing PipeWire tokens does.
APP_SETTINGS.CLEAR_SAVED_STATE,Clear saved state,Button label in Settings > Troubleshooting tab. Resets overlay positions and set placements to defaults.
APP_SETTINGS.CLEAR_SAVED_STATE_HELP,Reset sets & overlay positions,"Tooltip explaining what clearing saved state does. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
APP_SETTINGS.CLICK_FREEZE_TIME_MS,Click freeze time (ms),Slider/numeric input in Settings > Features tab. Sets a time window (in milliseconds) to help with double-click precision.
APP_SETTINGS.CLICK_FREEZE_TIME_MS_HELP,Helps with double-click precision,Tooltip for the click freeze time setting.
APP_SETTINGS.CLOCK_12H,12-hour clock,Checkbox label in Settings > Look & Feel tab. Toggles between 12-hour and 24-hour time display.
APP_SETTINGS.CONTROLS,Controls,Category header in Settings. Groups input/controller-related settings.
APP_SETTINGS.DELETE_ALL_CONFIGS,Wipe configuration,Button label in Settings > Troubleshooting tab. Removes all configuration files from conf.d.
APP_SETTINGS.DELETE_ALL_CONFIGS_HELP,Remove all configuration files from conf.d,Tooltip explaining the Wipe configuration button.
APP_SETTINGS.DOUBLE_CURSOR_FIX,Double cursor fix,Checkbox label in Settings > Miscellaneous tab. Enables a workaround for systems that show two cursors.
APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP,Enable this if you see 2 cursors,Tooltip for the double cursor fix checkbox.
APP_SETTINGS.DEFAULT_OVERLAY_SCALE,Default overlay size,Slider label in Settings > Look & Feel tab. Sets the default scale for newly created overlays.
APP_SETTINGS.DEFAULT_OVERLAY_SCALE_HELP,Spawn new overlays at this scale.,"Tooltip for the default overlay size slider. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
APP_SETTINGS.DEFAULT_CURVATURE,Default overlay curvature,"Slider label in Settings > Look & Feel tab. Sets the default curvature for new overlays. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
APP_SETTINGS.DEFAULT_OPACITY,Default overlay opacity,"Slider label in Settings > Look & Feel tab. Sets the default opacity for new overlays. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
APP_SETTINGS.DEFAULT_POSITIONING,Default overlay positioning,"Dropdown label in Settings > Look & Feel tab. Sets the default positioning mode (anchored/floating/static) for new overlays. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
APP_SETTINGS.OVERLAY_DEFAULTS_HELP,Only applies to new overlays,"Tooltip shared by default overlay settings (curvature, opacity, positioning). Notes these don't affect existing overlays. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
APP_SETTINGS.ENABLED,Enabled,Label used for enabling space gravity and related physics features in the space drag settings.
APP_SETTINGS.FEATURES,Features,Category header in Settings. Previously translated as ${DEFINITIONS.FEATURES}
APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE,Mouse move on trigger touch,"Setting in Settings > Features tab. When enabled, moving the trigger touch moves the mouse cursor."
APP_SETTINGS.HANDSFREE_POINTER,Handsfree mode,Dropdown label in Settings > Features tab. Selects the input method used when motion controllers are unavailable.
APP_SETTINGS.HANDSFREE_POINTER_HELP,"Input to use when motion
controllers are unavailable.
Left pinch is grab, right is click.",Tooltip for the handsfree mode dropdown.
APP_SETTINGS.HANDSFREE_ALT_TAB,App switcher aim,Dropdown/setting in Settings > Features tab. Controls how the alt-tab app switcher is aimed.
APP_SETTINGS.HANDSFREE_ALT_TAB_HELP,"Hold Super+X, aim at the desired window, then release to switch focus.",Tooltip explaining the handsfree alt-tab behavior.
APP_SETTINGS.HIDE_GRAB_HELP,Hide grab help,Checkbox label in Settings > Look & Feel tab. Hides the grab help overlay/text.
APP_SETTINGS.HIDE_USERNAME,Hide username,Checkbox label in Settings > Look & Feel tab. Hides the user's username from the UI.
APP_SETTINGS.INPUT_EMULATION_METHOD,Input emulation method,"Dropdown label in Settings > Miscellaneous tab. Selects how WayVR emulates mouse/keyboard input (uinput, Wayland virtual, none)."
APP_SETTINGS.INPUT_EMULATION_METHOD_HELP,"Try change this in case mouse or
keyboard input does not register.",Tooltip for the input emulation method dropdown.
APP_SETTINGS.INPUT_CAPTURE_METHOD,Input capture method,Dropdown label in Settings > Miscellaneous tab. Selects how physical input devices are captured for use inside WayVR.
APP_SETTINGS.INPUT_CAPTURE_METHOD_HELP,"Allows using physical peripherial inside WayVR.
Super+Z: Switch input between WayVR and real desktop
Super+X: Switch between WayVR apps",Tooltip explaining the input capture method setting.
APP_SETTINGS.INPUT_PROFILES,Change Input Bindings,Button label in Settings > Controls tab. Opens the controller bindings editor popup.
APP_SETTINGS.INPUT_PROFILES_HELP,OpenXR controller input bindings,Tooltip for the Change Input Bindings button.
APP_SETTINGS.INVERT_SCROLL_DIRECTION_X,Invert horizontal scroll direction,Checkbox label in Settings > Features tab. Inverts the horizontal scroll direction.
APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y,Invert vertical scroll direction,Checkbox label in Settings > Features tab. Inverts the vertical scroll direction.
APP_SETTINGS.KEYBOARD_MIDDLE_CLICK,Keyboard middle click,Dropdown label in Settings > Features tab. Selects the modifier key used for middle-click when typing with the laser pointer.
APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP,"Modifier to use when typing
with purple laser",Tooltip for the keyboard middle-click setting.
APP_SETTINGS.KEYBOARD_SOUND_ENABLED,Keyboard sounds,Checkbox label in Settings > Features tab. Enables or disables typing sounds when using the on-screen keyboard.
APP_SETTINGS.LANGUAGE,Language,Dropdown label in Settings > Look & Feel tab. Selects the UI language.
APP_SETTINGS.LEFT_HANDED_MOUSE,Left-handed mouse,Checkbox label in Settings > Features tab. Swaps mouse buttons for left-handed users.
APP_SETTINGS.LEFT_HANDED_MOUSE_HELP,Use this if mouse buttons are swapped,Tooltip for the left-handed mouse checkbox.
APP_SETTINGS.LONG_PRESS_DURATION,Long press duration,Setting in Settings > Features tab. Controls how long a press must be held to register as a long press.
APP_SETTINGS.LOOK_AND_FEEL,Look & Feel,"Category header in Settings. Groups visual/customization settings like language, opacity, animation speed, color palettes."
APP_SETTINGS.MISC,Miscellaneous,"Category header in Settings. Groups troubleshooting and system-level settings like capture method, input emulation, xwayland."
APP_SETTINGS.NOTIFICATIONS_ENABLED,Enable notifications,Checkbox label in Settings > Features tab. Enables or disables system notifications within WayVR.
APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED,Notification sounds,Checkbox label in Settings > Features tab. Enables or disables sound effects for notifications.
APP_SETTINGS.NOT_SUPPORTED,Not supported,Label shown in the space drag/physics settings when a feature (like gravity) is not supported by the current backend.
APP_SETTINGS.NO_SKYMAPS_FOUND,No skymaps found,"Label shown in the skymap browser when no skymaps are available locally. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
APP_SETTINGS.OPAQUE_BACKGROUND,Opaque background,Checkbox label in Settings > Look & Feel tab. Makes overlay backgrounds fully opaque (no transparency).
APP_SETTINGS.OPTION.ANCHORED_HELP,Moves with center marker. Recommended.,Tooltip for the Anchored positioning option.
APP_SETTINGS.OPTION.FLOATING_HELP,"Moves independently, recenters.
Easy to misplace; not recommended.",Tooltip for the Floating positioning option.
APP_SETTINGS.OPTION.STATIC_HELP,Stays in place relative to world.,Tooltip for the Static positioning option.
APP_SETTINGS.OPTION.AUTO,Automatic,"Dropdown option for screen capture method. Uses ScreenCopy GPU if supported, otherwise PipeWire GPU."
APP_SETTINGS.OPTION.AUTO_HELP,"ScreenCopy GPU if supported,
otherwise PipeWire GPU.",Tooltip for the Automatic capture method option.
APP_SETTINGS.OPTION.EYE_ONLY,Eye laser,Dropdown option for handsfree pointer mode. Uses only eye-tracking laser (no pinch).
APP_SETTINGS.OPTION.EYE_PINCH,Eye + pinch,Dropdown option for handsfree pointer mode. Uses eye-tracking for aiming and pinch for click.
APP_SETTINGS.OPTION.HMD_ONLY,HMD laser,Dropdown option for handsfree pointer/alt-tab mode. Uses only the HMD forward laser.
APP_SETTINGS.OPTION.HMD_PINCH,HMD + pinch,Dropdown option for handsfree pointer mode. Uses HMD laser for aiming and pinch for click.
APP_SETTINGS.OPTION.NONE,None,"Dropdown option used as the no binding or disabled choice in various settings (input emulation, input capture, handsfree pointer, alt modifier, whisper model)."
APP_SETTINGS.OPTION.NONE_INPUT_HELP,"Do not emulate mouse and keyboard.
Will not be able to interact with screens.",Tooltip for the None input emulation option.
APP_SETTINGS.OPTION.NONE_INPUT_CAPTURE_HELP,"Do not capture mouse and keyboard.
Will not be able to use physical mouse or
keyboard in apps launched inside WayVR.",Tooltip for the None input capture option.
APP_SETTINGS.OPTION.PIPEWIRE_HELP,"Fast GPU capture,
standard on all desktops.",Tooltip for the PipeWire GPU capture method option.
APP_SETTINGS.OPTION.PW_FALLBACK_HELP,"Slow method with high CPU usage.
Try in case PipeWire GPU doesn't work",Tooltip for the PipeWire CPU (fallback) capture method option.
APP_SETTINGS.OPTION.SCREENCOPY_GPU_HELP,"Fast, no screen share popups.
Works on: Hyprland, Niri, River, Sway",Tooltip for the ScreenCopy GPU capture method option.
APP_SETTINGS.OPTION.SCREENCOPY_HELP,"Slow, no screen share popups.
Works on: Hyprland, Niri, River, Sway",Tooltip for the ScreenCopy CPU capture method option.
APP_SETTINGS.OPTION.UINPUT,Device emulation,Dropdown option for input emulation method. Uses the uinput kernel module to emulate input devices.
APP_SETTINGS.OPTION.UINPUT_HELP,"Uses the uinput module to emulate a device.
Known to work well on most desktops.",Tooltip for the Device emulation (uinput) option.
APP_SETTINGS.OPTION.EVDEV_HELP,"Grab input devices for exclusive use.
Your user must be in the input group.",Tooltip for the evdev input capture method option.
APP_SETTINGS.OPTION.WL_VIRTUAL,Wayland virtual input,Dropdown option for input emulation method. Uses Wayland virtual pointer/keyboard protocols.
APP_SETTINGS.OPTION.WL_VIRTUAL_HELP,"Send events to the Wayland compositor using
zwlr_virtual_pointer and zwp_virtual_keyboard.
Only works reliably on some desktops.
Does NOT work on KDE, GNOME or COSMIC.",Tooltip for the Wayland virtual input option.
APP_SETTINGS.POINTER_ACCELERATION,Mouse acceleration,Checkbox/dropdown in Settings > Features tab. Toggles adaptive mouse acceleration (on) or constant speed (off).
APP_SETTINGS.POINTER_ACCELERATION_HELP,"On: Adaptive mouse acceleration
Off: Constant speed",Tooltip for the mouse acceleration setting.
APP_SETTINGS.POINTER_LERP_FACTOR,Pointer smoothing,Slider in Settings > Features tab. Controls the linear interpolation (smoothing) factor for pointer movement.
APP_SETTINGS.POINTER_SPEED,Mouse speed,Slider in Settings > Features tab. Controls the base mouse pointer speed.
APP_SETTINGS.REQUIRES_RESTART,Requires restart,Label shown below settings that require a software restart to take effect.
APP_SETTINGS.RESET_PLAYSPACE,Reset playspace,"Button in Settings > Space Drag tab. Clears the stage space offset, resetting playspace position. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.RESET_PLAYSPACE_HELP,Clear the stage space offset.,"Tooltip for the Reset playspace button. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.SAVE_PLAYSPACE_CENTER,Save playspace center,"Button in Settings > Space Drag tab. Saves the current playspace center as the reset target. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.SAVE_PLAYSPACE_CENTER_HELP,Use current playspace for reset playspace binding.,"Tooltip for the Save playspace center button. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.RESET_PLAYSPACE_CENTER,Reset playspace center,"Button in Settings > Space Drag tab. Clears the previously saved playspace center. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.RESET_PLAYSPACE_CENTER_HELP,Clear previously set playspace center.,"Tooltip for the Reset playspace center button. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.RESTART_SOFTWARE,Restart software,Button in Settings > Troubleshooting tab. Restarts the WayVR software to apply settings that require a restart.
APP_SETTINGS.RESTART_SOFTWARE_HELP,Apply settings that require a restart,Tooltip for the Restart software button.
APP_SETTINGS.ROUND_MULTIPLIER,UI Edge roundness,Slider in Settings > Look & Feel tab. Controls how rounded the corners of UI elements appear (range 0.1-5.0).
APP_SETTINGS.SCREEN_RENDER_DOWN,Render screen at lower resolution,Checkbox in Settings > Miscellaneous tab. Renders the captured desktop screen at a lower resolution to improve performance or reduce aliasing.
APP_SETTINGS.SCREEN_RENDER_DOWN_HELP,Helps with aliasing on high-res screens,Tooltip for the lower-resolution screen render setting.
APP_SETTINGS.SCROLL_SPEED,Scroll speed,Slider in Settings > Features tab. Controls how fast scrolling occurs.
APP_SETTINGS.SELECT_VARIANT,Select variant,Label/button in the color palette or variant selection UI. Allows choosing between different theme variants.
APP_SETTINGS.SNAP_ANGLE_DEG,Window pitch & roll snap angle,Slider in Settings > Features tab. Sets the angle (in degrees) at which grabbed windows snap on pitch and roll axes.
APP_SETTINGS.SNAP_ANGLE_DEG_HELP,Grabbed windows snap to this angle on pitch and roll axis.,Tooltip for the snap angle setting.
APP_SETTINGS.ENABLE_WATCH,Enable watch,"Checkbox in Settings > Look & Feel tab. Enables the wrist watch UI element. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
APP_SETTINGS.SETS_ON_WATCH,Sets on watch,"Checkbox in Settings > Look & Feel tab. Shows overlay sets on the wrist watch display. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}"". ""Set"" was previously translated as ""${DEFINITIONS.SET}""."
APP_SETTINGS.SHOW_WELCOME_SCREEN,Show welcome screen,Checkbox in Settings > Features tab. Controls whether the welcome/tutorial screen is shown on first launch.
APP_SETTINGS.SKYBOX,Skymap,"Category header in Settings > Skymap tab. Groups skymap-related settings. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
APP_SETTINGS.SKYMAP_ALREADY_DOWNLOADED,This skymap is already downloaded. Select desired action.,"Message shown in a dialog when attempting to download a skymap that is already present locally. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
APP_SETTINGS.SPACE_DRAG,Playspace,"Category header in Settings. Groups playspace drag/physics settings including reset buttons and gravity. ""Playspace"" was previously translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.SPACE_DRAG_MULTIPLIER,Space drag multiplier,"Setting in the space drag physics panel. Multiplies the force applied during space drag. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.SPACE_DRAG_AFFECTS_WORLD,Leave overlays behind during space move,"Checkbox in Settings > Space Drag tab. When enabled, moving the playspace leaves overlays behind instead of moving them with the set. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}"". ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.SPACE_DRAG_UNLOCKED,Allow space drag on all axes,"Checkbox in Settings > Space Drag tab. Unlocks space drag to work on all axes instead of a constrained axis. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.SPACE_GRAVITY_DAMPING,Damping,"Setting in the space gravity physics panel. Artificial drag to slow movement (0.1 = high drag, 1.0 = no drag)."
APP_SETTINGS.SPACE_GRAVITY_DAMPING_HELP,"Artificial drag to slow down movement. 0.1 - high drag, 1.0 - no drag",Tooltip for the inertial damping setting.
APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH,Fling strength,Setting in the space gravity physics panel. Intensity multiplier for the gravitational launch force after space-drag.
APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH_HELP,"Intensity multiplier of gravitational launch force after space-drag.
0.0 - no movement at all, 2.0 - double intensity","Tooltip for the fling strength setting. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.SPACE_GRAVITY_GRAVITY,Gravity,Setting in the space gravity physics panel. Amount of downward force (0.0 = no gravity).
APP_SETTINGS.SPACE_GRAVITY_GRAVITY_HELP,Amount of downwards force. 0.0 - no gravity,Tooltip for the gravity setting.
APP_SETTINGS.SPACE_GRAVITY_GROUND_FRICTION,Ground friction,"Setting in the space gravity physics panel. Friction when touching the ground (0.0 = ice-like, 1.0 = rough)."
APP_SETTINGS.SPACE_GRAVITY_GROUND_FRICTION_HELP,"Amount of friction slowing you down if you're touching the ground.
0.0 - no friction (just like on ice), 1.0 - rough surface",Tooltip for the ground friction setting.
APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT,Floor height,Setting in the space gravity physics panel. The Y position where the virtual floor is.
APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT_HELP,The Y position where the floor is. Gravity stops when you reach this height.,Tooltip for the floor height setting.
APP_SETTINGS.SPACE_ROTATE_UNLOCKED,Allow space rotate on all axes,"Checkbox in Settings > Space Drag tab. Unlocks space rotate to work on all axes. ""Space"" in this context refers to ""Playspace"" which was translated as ""${DEFINITIONS.PLAYSPACE}""."
APP_SETTINGS.TROUBLESHOOTING,Troubleshooting,"Category header in Settings. Groups diagnostic/reset actions like clearing tokens, wiping config, and restarting."
APP_SETTINGS.UI_GRADIENT_INTENSITY,UI Gradient intensity,Slider in Settings > Look & Feel tab. Controls the intensity of gradient effects on the UI (range 0.0-1.0).
APP_SETTINGS.UPRIGHT_SCREEN_FIX,Upright screen fix,Checkbox in Settings > Miscellaneous tab. Fixes upright screen orientation on some desktop environments.
APP_SETTINGS.UPRIGHT_SCREEN_FIX_HELP,Fixes upright screens on some desktops,Tooltip for the upright screen fix checkbox.
APP_SETTINGS.USE_PASSTHROUGH,Enable passthrough,Checkbox in Settings > Skybox tab. Allows camera passthrough mode if the XR runtime supports it.
APP_SETTINGS.USE_PASSTHROUGH_HELP,Allow passthrough if the XR runtime supports it,Tooltip for the passthrough checkbox.
APP_SETTINGS.USE_SKYBOX,Show skymap,"Checkbox in Settings > Skybox tab. Shows a skybox when there's no scene app or passthrough active. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
APP_SETTINGS.USE_SKYBOX_HELP,Show a skymap if there's no scene app or passthrough,"Tooltip for the enable skybox checkbox. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
APP_SETTINGS.WATCH_VIEW_ANGLE,Watch view angles,"Setting in Settings > Look & Feel tab. Controls the view angles at which the wrist watch fades in/out. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
APP_SETTINGS.WATCH_VIEW_ANGLE_HELP,Control how the watch fades away,"Tooltip for the watch view angles setting. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
APP_SETTINGS.WHISPER.NEED_TO_DOWNLOAD_MODEL,"The selected model needs to be downloaded.
Download it right now?",Message shown in a dialog box when the user selects a Whisper model that hasn't been downloaded yet.
APP_SETTINGS.WHISPER.REMOVE_UNUSED_MODELS,"You are turning off the speech-to-text feature.
Would you like to remove downloaded Whisper models to free up space?",Message shown in a dialog box when the user disables the whisper feature.
APP_SETTINGS.WHISPER_MODEL,Speech-to-text model,Dropdown label in Settings > Features tab. Selects which Whisper model to use for speech-to-text.
APP_SETTINGS.WHISPER_MODEL_HELP,"Whisper model to use.
Larger models produce more accurate
results, but consume more VRAM.",Tooltip for the speech-to-text model dropdown.
APP_SETTINGS.GRID_OPACITY,Floor grid opacity,Slider in Settings > Skybox tab. Controls the opacity of the floor grid when skybox is enabled.
APP_SETTINGS.GRID_OPACITY_HELP,Opacity of the floor grid when the skymap is enabled,"Tooltip for the floor grid opacity slider. ""Skymap"" was previously translated as ""${DEFINITIONS.SKYMAP}""."
APP_SETTINGS.XWAYLAND_BY_DEFAULT,Run apps in Compatibility mode by default,Checkbox in Settings > Miscellaneous tab. Launches apps in Cage/compatibility mode by default.
APP_SETTINGS.SAVE,Save,Button label in the controller bindings editor popup. Saves the current bindings configuration.
APP_SETTINGS.CANCEL,Cancel,Button label in the controller bindings editor popup and in whisper model dialogs. Cancels/dismisses the dialog without saving.
APPLICATION_LAUNCHER,Application launcher,App launcher configuration popup title - appears as the label for the app launch/options dialog.
APPLICATION_STARTED,Application started,Toast notification shown after a successful app launch.
APPLICATIONS,Applications,Tab label in the dashboard sidebar for the Apps tab.
AUDIO.AUTO_SWITCH_TO_VR_AUDIO,Auto-switch to VR audio,Tooltip on the auto-switch audio button in the audio settings popup.
AUDIO.CARDS,Cards,Button label in the audio settings popup for selecting audio card profiles.
AUDIO.FAILED_TO_SWITCH_MICROPHONE,Failed to switch microphone,Error toast shown when switching to a VR microphone fails.
AUDIO.MICROPHONE_SET_SUCCESSFULLY,Microphone set successfully,Toast notification after successfully switching the microphone.
AUDIO.MICROPHONES,Microphones,Button label in the audio settings popup for selecting microphone sources.
AUDIO.NO_VR_MICROPHONE_SWITCH_MANUALLY,No VR microphone found. Switch it manually.,Toast shown when no VR microphone is detected and manual switching is needed.
AUDIO.NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY,No VR speakers found. Switch them manually.,Toast shown when no VR speakers are detected after auto-switch.
AUDIO.SELECT_AUDIO_CARD_PROFILE,Select audio card profile,Bold label in the audio settings popup for choosing an audio card profile.
AUDIO.SETTINGS,Audio settings,Window title for the audio settings popup opened from the dashboard.
AUDIO.SPEAKERS,Speakers,Button label in the audio settings popup for selecting speaker sinks.
AUDIO.SPEAKERS_SET_SUCCESSFULLY,Speakers set successfully,Toast notification after successfully switching speakers.
AUDIO.VOLUME,Volume,Tooltip on the audio volume button in the dashboard.
CLOSE_WINDOW,Close window,"Close button label used in dialog boxes, download file popup, and window options."
CREATION_DATE,Creation date,Column label in the remote skymap downloader showing file metadata.
DEBUG_INFO,Debug info,Tab name in the Monado runtime section of the dashboard.
DISPLAY_BRIGHTNESS,Display brightness,Label for the display brightness setting in the Monado general settings tab.
DONATE.SUPPORT_US,Support us,Button tooltip on the home screen donate button.
DONATE.DESCRIPTION,"We're a small team of 2 developers building WayVR in our free time. If you enjoy using this software, please consider supporting us - every donation helps us keep going.",Description text on the donate tab explaining the project.
DONATE.THANK_YOU_WAYVR,Thank you from the WayVR Team!,Thank you message displayed on the donate tab.
DONATE.BUTTON_TOOLTIP,Donate via Open Collective,Tooltip on the donate button on the donate tab.
DONATE.CURRENT_SUPPORTERS,Current Supporters,Section header on the donate tab listing supporters.
DONATE.BROUGHT_TO_YOU_VARIANTS_OFTEN,Supported by {USER}|Special thanks to {USER}|Sponsored by {USER}|Backed by {USER}|Driven by community members like {USER}|Made possible by {USER}|Sustained by {USER}|Contributed by {USER}|Funded by {USER},This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it.
DONATE.BROUGHT_TO_YOU_VARIANTS_RARE,Coffee provided by {USER}|Fuelled by {USER}|Shoutout to {USER}!|Keeping us going: {USER}|Helping us grow: {USER}|Keeping the servers running: {USER}|With gratitude to {USER}|Powered by {USER}|Supported by friends like {USER},This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it (rare versions).
DONATE.BROUGHT_TO_YOU_VARIANTS_VERY_RARE,Supported by legends like {USER}|Caffeine supplied by {USER}|A true legend: {USER}|Our hero of the day: {USER}|An absolute superstar: {USER}|Paying for the electricity bill: {USER}|The savior of our sanity: {USER}|Leading the way: {USER}|Caffeine-to-code converter provided by {USER}|Keeping the production stable: {USER}|The one and only: {USER}|Passing dmabuf buffers: {USER},This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it (rare versions).
DOWNLOAD,Download,Button in the Whisper model download dialog to confirm downloading a model.
DOWNLOADER,Downloader,Window title for the file download popup.
WELCOME.ALL_SET,You're all set!,Main heading on the final welcome/tutorial page.
WELCOME.BASICS,These basics will allow you to start using WayVR with ease.,Description text on the final welcome page under the You are all set heading.
WELCOME.CENTER_MARKER,Center marker is what will appear in front of you when recentering. Place overlays around it!,"Description of the center marker on the moving your set tutorial page. ""Overlay"" was previously translated as ""${DEFINITIONS.OVERLAY}""."
WELCOME.DOUBLE_PRESS_TO_TOGGLE,"Double-press B (on Index) or Y (on Meta) to show, recenter or hide your set. Try it now.","Instruction text on the working set tutorial page explaining the double-press gesture. ""Set"" was previously translated as ""${DEFINITIONS.SET}""."
WELCOME.FEATURES_DOCUMENTATION,"There are many other features worth customizing. For more information, check the documentation at",Text on the final welcome page linking to documentation.
WELCOME.FINISH_TUTORIAL,Finish tutorial,Button text on the final welcome page to complete the tutorial.
WELCOME.GRAB_BOTH_HANDS,Grab it with both hands if you want to move a specific overlay in your set.,Instruction text on the moving your set tutorial page for two-hand grab.
WELCOME.GRAB_ONE_HAND,Grab it with one hand to move your set.,Instruction text on the moving your set tutorial page for one-hand grab.
WELCOME.GREETING,Hi there!,Greeting label on the first welcome page.
WELCOME.GUIDE_INTRO,Let us guide you through your first steps.,Intro text on the first welcome page below the greeting.
WELCOME.LASER_COLORS,Laser Colors,Page title on the laser colors tutorial page.
WELCOME.LASER_FUNCTIONALITY,"Much of the functionality in WayVR depends on what color of laser is used to interact with a UI element. You don't need to press these buttons, just touch them!",Description text on the laser colors tutorial page.
WELCOME.LAST_PAGE_INFO,This tutorial will stop showing up once you get to the last page.,Info text on the first welcome page noting the tutorial is near the end.
WELCOME.LOOK_AT_LEFT_WRIST,Look at your left wrist. That's your watch.,"Instruction text on the watch tutorial page. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
WELCOME.MIDDLE_CLICK_MODE_PURPLE_LASER, Middle-click Mode: Purple laser,Laser mode label on the laser colors tutorial page.
WELCOME.MOVING_YOUR_SET,Moving your set,Page title on the moving your set tutorial page.
WELCOME.NEXT_BUTTON,"Press ""Next"" button below to get started.",Label on the first welcome page pointing to the next button.
WELCOME.REGULAR_MODE_BLUE_LASER,Regular Mode: Blue laser,Laser mode label on the laser colors tutorial page.
WELCOME.REPOSITION_THIS_WINDOW_BY_GRABBING,Reposition this window using your controller's grip action.,Instruction text on the first welcome page about window repositioning.
WELCOME.RIGHT_CLICK_MODE_ORANGE_LASER,Right-click Mode: Orange laser,Laser mode label on the laser colors tutorial page.
WELCOME.THANKS_FOR_INSTALLING,Thank you for installing WayVR!,Thanks text on the first welcome page below the greeting.
WELCOME.WATCH,Watch,"Page title on the watch/tutorial page. ""Watch"" was previously translated as ""${DEFINITIONS.WATCH}""."
WELCOME.WORKING_SET,Working Set,"Page title on the working set tutorial page. ""Set"" was previously translated as ""${DEFINITIONS.SET}"". Working as in ""Current""."
DOWNLOAD_AGAIN,Download again,Button in the skymap already downloaded dialog to re-download a skymap.
DOWNLOADING_FILE,Downloading file...,Status label in the download file popup showing download progress.
FAILED_TO_LAUNCH_APPLICATION,Failed to launch a application:,Error prefix in the toast shown when app launch fails.
GAME_LAUNCHED,Game launched,Toast notification shown after successfully launching a game via Steam.
GAME_LIST.NO_GAMES_FOUND,No games found,Empty state text shown in the game list when no games are installed.
GAME_LIST.RUNNING_GAMES_LIST,List of running games,Section label in the running games list view.
GAMES,Games,Tab label in the dashboard sidebar for the Games tab.
GENERAL_SETTINGS,General settings,Tab name and group box title in the Monado runtime settings.
GETTING_STARTED,Getting started,Tab label in the dashboard sidebar for the Welcome/tutorial tab.
HEIGHT,Height,Label for the height dimension field in the add display popup.
HELLO,Hello!,Fallback greeting on the home screen when username is hidden.
HELLO_USER,"Hello, {USER}!",Greeting on the home screen with the user name substituted in.
HIDE,Hide,Used in the double-press tutorial context for hiding the set.
HOME_SCREEN,Home,Tab label in the dashboard sidebar for the Home tab.
MODIFICATION_DATE,Modification date,Column label in the remote skymap downloader showing file metadata.
MONADO_RUNTIME,Monado runtime,Tab label in the dashboard sidebar for the Monado runtime tab.
LOADING,Loading...,Label in the loading spinner template used across the UI.
POPUP_ADD_DISPLAY.RESOLUTION,Resolution,Label for the resolution field in the add display popup.
PROCESS.FORCE_KILL,Force-kill,Tooltip on the kill button in the running games list.
PROCESS.STOP,Stop,Tooltip on the stop button in the running games list.
PROCESS_LIST,Process list,Tab name and group box title in the Monado runtime process list section.
REFRESH,Refresh,Tooltip on the refresh button in the running games list.
REMOVE,Remove,Button label in the skymap already downloaded dialog and Whisper cleanup dialog to remove files.
APPLY,Apply,Button label in the skymap already downloaded dialog to apply the selected skymap.
RELOAD_FROM_DISK,Reload from disk,Tooltip on the reload button in the skymap list view.
SETTINGS,Settings,Tab label in the dashboard sidebar for the Settings tab. Previously translated as ${DEFINITIONS.SETT}
SHOW,Show,Used in the double-press tutorial context for showing the set.
TARGET_PATH,Target path,Label for the target path display in the download file popup.
TERMINATE_PROCESS,Terminate process,Button label in the window options bar to kill a process.
VERSION,Version,Label for the version display in the remote skymap downloader.
WIDTH,Width,Label for the width dimension field in the add display popup.
PINNED_APPS,Pinned applications,"Section header label for the pinned apps list on the Apps tab, a.k.a. ""Favourites"""
SAVED_TO_FAVOURITES,Saved to pinned apps,"Toast notification shown after pinning an app to favourites. ""Pinned apps"" was previously translated as ""${PINNED_APPS}""."
ADD_TO_FAVOURITES,Add to pinned apps,"Label on the pin button in the app launcher popup that is used to add to favourites.. ""Pinned apps"" was previously translated as ""${PINNED_APPS}""."
ADD_TO_FAVOURITES_HINT,Save preset and pin it to the app drawer,"Tooltip on the add to favourites button in the app launcher popup. ""Pinned apps"" was previously translated as ""${PINNED_APPS}""."
REMOVE_FROM_FAVOURITES,Remove from pinned apps,"Label on the unpin section in the app launcher popup. ""Pinned apps"" was previously translated as ""${PINNED_APPS}""."
EMPTY,Empty,Label shown in the pinned apps section when there are no pinned apps.
1 DEFINITIONS.ANCHORED Anchored A movement option that makes this window move together with the rest of the workspace. Emphasize the "moving together" part as opposed to "not moving at all".
2 DEFINITIONS.FLOATING Floating A movement option that lets this window float freely.
3 DEFINITIONS.STATIC Static A movement option that keeps this window in place relative to the world origin. Emphasize the "not moving at all" part, as opposed to the "moving together" option which was previously translated as ${DEFINITIONS.ANCHORED}.
4 DEFINITIONS.SET Set A desktop workspace consisting of multiple windows.
5 DEFINITIONS.WATCH Watch Name of the small utility window that hovers around the user's wrist.
6 DEFINITIONS.DASHBOARD Dashboard Name of the window that acts as the main menu / control panel of the application.
7 DEFINITIONS.EDIT_MODE Edit Mode Name of the mode that allows the user to make various tweaks to the current workspace and its windows.
8 DEFINITIONS.SETTINGS Settings The title of the settings panel.
9 DEFINITIONS.KEYBOARD Keyboard Name of the virtual keyboard
10 DEFINITIONS.TASKBAR Taskbar A long panel showing currently active programs & windows, workspaces and a clock.
11 DEFINITIONS.FEATURES Features The section title of the section panel that deals with software features.
12 DEFINITIONS.OVERLAY Overlay An overlay window inside VR, similar to a "desktop window". Consider it a technical term.
13 DEFINITIONS.SKYMAP Skymap A 360 degree background image that surrounds the user.
14 DEFINITIONS.PLAYSPACE Playspace The VR play space that the user can adjust in different way. Technical term.
15 DEFINITIONS.D_PAD D-pad Directional pad on a modern game controller. Technical term.
16 ACTIONS.RECENTER_PLAYSPACE Re-center playspace Tooltip on a button (with recenter icon) in the bottom-left of the VR dashboard. The button resets the user's tracked playspace to the current physical location. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
17 APP_LAUNCHER.ASPECT.SEMI_TALL Semi-tall Radio button in the App Launcher panel's Aspect section. Sets the window to a 2:3 vertical aspect ratio. Tooltip shows "2:3".
18 APP_LAUNCHER.ASPECT.SEMI_WIDE Semi-wide Radio button in the App Launcher panel's Aspect section. Sets the window to a 3:2 aspect ratio. Tooltip shows "3:2".
19 APP_LAUNCHER.ASPECT.SQUARE Square Radio button in the App Launcher panel's Aspect section. Sets the window to a 1:1 aspect ratio. Tooltip shows "1:1".
20 APP_LAUNCHER.ASPECT.TALL Tall Radio button in the App Launcher panel's Aspect section. Sets the window to a 9:16 vertical aspect ratio. Tooltip shows "9:16".
21 APP_LAUNCHER.ASPECT.WIDE Wide Radio button in the App Launcher panel's Aspect section. Sets the window to a 16:9 aspect ratio (standard widescreen). Tooltip shows "16:9".
22 APP_LAUNCHER.ASPECT_TITLE Aspect Section header label above a row of 5 radio buttons (Wide, Semi-wide, Square, Semi-tall, Tall) in the App Launcher panel. Controls the window aspect ratio for the selected app.
23 APP_LAUNCHER.AUTOSTART Run automatically on startup Label on a checkbox in the App Launcher panel. When checked, the selected app will launch automatically when the Dash compositor starts.
24 APP_LAUNCHER.LAUNCH Launch Label on the primary (blue/primary color) button at the bottom of the App Launcher panel. Launches the selected app with the configured settings. Has a play icon next to it.
25 APP_LAUNCHER.MODE.CAGE Compatibility mode (Cage) Radio button option in the App Launcher panel's mode selector (next to "Native mode"). Sets the app to run in Cage compatibility mode.
26 APP_LAUNCHER.MODE.NATIVE Native mode Radio button option (default/checked) in the App Launcher panel's mode selector (next to "Compatibility mode (Cage)"). Sets the app to run in native Wayland mode.
27 APP_LAUNCHER.RES_TITLE Resolution Section header label in the App Launcher panel above a row of 4 radio buttons (1440p, 1080p, 720p, 480p). Controls the rendering resolution for the selected app.
28 APP_SETTINGS.ALLOW_SLIDING Stick interaction during grab Checkbox label in Settings > Features tab. Toggles whether analog stick input works while an overlay is grabbed/moved.
29 APP_SETTINGS.ANIMATION_SPEED UI Animation speed Slider label in Settings > Look & Feel tab. Controls the speed of UI transition animations (range 0.5-5.0).
30 APP_SETTINGS.AUTOSTART_APPS Apps to run on startup Category header in Settings. Label for the section listing apps configured to auto-launch on WayVR startup.
31 APP_SETTINGS.BLOCK_GAME_INPUT Block game input Checkbox label in Settings > Features tab. When enabled, blocks all in-game input when an overlay is hovered.
32 APP_SETTINGS.BLOCK_GAME_INPUT_HELP Blocks all input when an overlay is hovered Tooltip text appearing next to the Block game input checkbox in Settings > Features.
33 APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH Ignore watch when blocking input Checkbox label in Settings > Features tab. When enabled, hovering the wrist watch does not block game input. "Watch" was previously translated as "${DEFINITIONS.WATCH}".
34 APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH_HELP Do not block input when watch is hovered Tooltip text next to the Ignore watch when blocking input checkbox. "Watch" was previously translated as "${DEFINITIONS.WATCH}".
35 APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION Block poses when interacting with keyboard Checkbox label in Settings > Features tab. Blocks game pose input when the on-screen keyboard is hovered (requires Block game input enabled).
36 APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION_HELP Blocks the game from receiving poses when the keyboard is hovered and 'Block game input' is enabled Tooltip explaining the Block poses when interacting with keyboard checkbox.
37 APP_SETTINGS.BINDINGS.COMP.CLICK Click Dropdown option in the controller bindings editor. Selects the Click component of a controller input.
38 APP_SETTINGS.BINDINGS.COMP.FORCE Force Dropdown option in the controller bindings editor. Selects the Force analog component (e.g. how hard a trigger is pressed).
39 APP_SETTINGS.BINDINGS.COMP.TOUCH Touch Dropdown option in the controller bindings editor. Selects the Touch component (whether a button is merely touched vs pressed).
40 APP_SETTINGS.BINDINGS.COMP.VALUE Value Dropdown option in the controller bindings editor. Selects the raw Value analog output of a component.
41 APP_SETTINGS.BINDINGS.COMP.PROXIMITY Proximity Dropdown option in the controller bindings editor. Selects the Proximity component (distance of controller from head/hand).
42 APP_SETTINGS.BINDINGS.COMP.X_AXIS X axis Dropdown option in the controller bindings editor. Selects the X-axis analog value (e.g. thumbstick X, trackpad X).
43 APP_SETTINGS.BINDINGS.COMP.Y_AXIS Y axis Dropdown option in the controller bindings editor. Selects the Y-axis analog value (e.g. thumbstick Y, trackpad Y).
44 APP_SETTINGS.BINDINGS.TYPE.BUMPER Bumper Dropdown option in the bindings editor. Maps to the Bumper controller subpath (upper shoulder button).
45 APP_SETTINGS.BINDINGS.TYPE.DPAD_UP D-pad Up Dropdown option in the bindings editor. Maps to the D-pad up direction. "D-pad" was previously translated as "${DEFINITIONS.D_PAD}".
46 APP_SETTINGS.BINDINGS.TYPE.DPAD_DOWN D-pad Down Dropdown option in the bindings editor. Maps to the D-pad down direction. "D-pad" was previously translated as "${DEFINITIONS.D_PAD}". "D-pad Up" was previously translated as "${APP_SETTINGS.BINDINGS.TYPE.DPAD_UP}".
47 APP_SETTINGS.BINDINGS.TYPE.DPAD_LEFT D-pad Left Dropdown option in the bindings editor. Maps to the D-pad left direction. "D-pad" was previously translated as "${DEFINITIONS.D_PAD}". "D-pad Up" was previously translated as "${APP_SETTINGS.BINDINGS.TYPE.DPAD_UP}".
48 APP_SETTINGS.BINDINGS.TYPE.DPAD_RIGHT D-pad Right Dropdown option in the bindings editor. Maps to the D-pad right direction. "D-pad" was previously translated as "${DEFINITIONS.D_PAD}". "D-pad Up" was previously translated as "${APP_SETTINGS.BINDINGS.TYPE.DPAD_UP}".
49 APP_SETTINGS.BINDINGS.TYPE.JOYSTICK Joystick Dropdown option in the bindings editor. Maps to the joystick subpath.
50 APP_SETTINGS.BINDINGS.TYPE.MENU Menu Dropdown option in the bindings editor. Maps to the Menu controller button.
51 APP_SETTINGS.BINDINGS.TYPE.SHOULDER Shoulder Dropdown option in the bindings editor. Maps to the Shoulder subpath (shoulder strap button).
52 APP_SETTINGS.BINDINGS.TYPE.SQUEEZE Grip Dropdown option in the bindings editor. Maps to the Squeeze component (controller grip action).
53 APP_SETTINGS.BINDINGS.TYPE.SYSTEM System Dropdown option in the bindings editor. Maps to the System controller subpath.
54 APP_SETTINGS.BINDINGS.TYPE.THUMBREST Thumbrest Dropdown option in the bindings editor. Maps to the thumbrest touch sensor.
55 APP_SETTINGS.BINDINGS.TYPE.THUMBSTICK Thumbstick Dropdown option in the bindings editor. Maps to the thumbstick subpath. Different from "Joystick" which was previously translated as "${APP_SETTINGS.BINDINGS.TYPE.JOYSTICK}".
56 APP_SETTINGS.BINDINGS.TYPE.TRACKPAD Trackpad Dropdown option in the bindings editor. Maps to the trackpad subpath.
57 APP_SETTINGS.BINDINGS.TYPE.TRIGGER Trigger Dropdown option in the bindings editor. Maps to the trigger subpath.
58 APP_SETTINGS.BINDINGS.TYPE.VIEW View Dropdown option in the bindings editor. Maps to the View controller button.
59 APP_SETTINGS.BINDINGS.CLICK.ANY Any Dropdown option in the bindings editor. Selects any press click type (no double/triple tap requirement).
60 APP_SETTINGS.BINDINGS.CLICK.DOUBLE Double-tap Dropdown option in the bindings editor. Requires a double-tap on the selected button/component.
61 APP_SETTINGS.BINDINGS.CLICK.TRIPLE Triple-tap Dropdown option in the bindings editor. Requires a triple-tap on the selected button/component.
62 APP_SETTINGS.BINDINGS.CLICK.TYPE Tap count Tooltip for the click-type dropdown in the bindings editor. Indicates this dropdown controls how many taps are required.
63 APP_SETTINGS.BINDINGS.ACTION.CLICK Click* Label for the click action row in the controller bindings editor. The asterisk indicates it may have modifiers. Leave the '*' at the end.
64 APP_SETTINGS.BINDINGS.ACTION.GRAB Grab* Label for the grab action row in the bindings editor. Maps to the controller grab/grip action. Leave the '*' at the end.
65 APP_SETTINGS.BINDINGS.ACTION.ALT_CLICK Custom shell exec (set alt_click in config) Label for the alt_click action row in the bindings editor. Triggers a custom shell command defined in config.
66 APP_SETTINGS.BINDINGS.ACTION.SHOW_HIDE Show, hide, recenter* Label for the show_hide action row. Toggles overlay visibility and recenters the set. Leave the '*' at the end.
67 APP_SETTINGS.BINDINGS.ACTION.TOGGLE_DASHBOARD Toggle dashboard Label for the toggle_dashboard action row. Opens or closes the WayVR dashboard.
68 APP_SETTINGS.BINDINGS.ACTION.SPACE_DRAG Playspace drag Label for the space_drag action row. Allows dragging the entire playspace/set of overlays. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
69 APP_SETTINGS.BINDINGS.ACTION.SPACE_ROTATE Playspace rotate Label for the space_rotate action row. Allows rotating the entire playspace/set. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
70 APP_SETTINGS.BINDINGS.ACTION.SPACE_RESET Playspace reset Label for the space_reset action row. Resets playspace to the original state. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
71 APP_SETTINGS.BINDINGS.ACTION.CLICK_MODIFIER_RIGHT Right-click modifier Label for the click_modifier_right action row. Maps a controller input to act as a right-click modifier.
72 APP_SETTINGS.BINDINGS.ACTION.CLICK_MODIFIER_MIDDLE Middle-click modifier Label for the click_modifier_middle action row. Maps a controller input to act as a middle-click modifier.
73 APP_SETTINGS.BINDINGS.ACTION.MOVE_MOUSE Move mouse (if off by default) Label for the move_mouse action row. Maps controller input to mouse movement.
74 APP_SETTINGS.BINDINGS.ACTION.SCROLL Scroll* Label for the scroll action row. Maps controller input to scrolling. Leave the '*' at the end.
75 APP_SETTINGS.BINDINGS.LEFT Left Label in the bindings editor. Refers to the left controller/hand configuration.
76 APP_SETTINGS.BINDINGS.RIGHT Right Label in the bindings editor. Refers to the right controller/hand configuration.
77 APP_SETTINGS.BINDINGS.COMPONENT Actuation type Tooltip for the component dropdown in the bindings editor. Asks user to select what type of actuation (click, touch, axis, etc.).
78 APP_SETTINGS.BINDINGS.SUBPATH Actuating control Tooltip for the subpath dropdown in the bindings editor. Asks user to select which controller button/stick/trackpad to bind.
79 APP_SETTINGS.BINDINGS.THRESHOLD Activate when above upper value Deactivate when below lower value Tooltip for the threshold slider in the bindings editor. Explains the two-value threshold range for analog inputs.
80 APP_SETTINGS.BROWSE_ONLINE_CATALOG Browse online catalog... Button label in the color palettes popup. Opens a web browser to the WayVR online catalog.
81 APP_SETTINGS.BROWSE_SKYMAPS Browse skymaps Button label in Settings > Skybox tab. Opens the skymap browser/list. "Skymap" was previously translated as "${DEFINITIONS.SKYMAP}".
82 APP_SETTINGS.CAPTURE_METHOD Screen capture method Dropdown label in Settings > Miscellaneous tab. Selects the method for capturing the desktop screen (PipeWire, ScreenCopy, etc.).
83 APP_SETTINGS.CAPTURE_METHOD_HELP Try changing this if you are experiencing black or glitchy screens Tooltip for the Wayland screen capture dropdown in Miscellaneous settings.
84 APP_SETTINGS.COLOR_KEYING Color keying Setting in the look-and-feel / color palette section. Enables or configures chroma-key style color filtering.
85 APP_SETTINGS.COLOR_PALETTE Color palette Button label in Settings > Look & Feel tab. Opens the color palette selection popup.
86 APP_SETTINGS.COLOR_PALETTE_HELP Click to browse color palettes. To create custom ones, see website! Tooltip for the Color palette button.
87 APP_SETTINGS.COLOR_PALETTES Color palettes Category/header label in the color palette popup.
88 APP_SETTINGS.COLOR_PALETTE_CURRENT Currently active theme. Label or tooltip showing which color palette is currently applied.
89 APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL Add your own custom theme! Button/label in the color palette popup for adding a custom theme via URL.
90 APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL2 Click to open web manual. Secondary label/button next to the custom URL input, linking to the web manual.
91 APP_SETTINGS.COLOR_PALETTE_ACTIVATE Click to use this theme. Tooltip or button label on a palette card to apply/activate that theme.
92 APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS Clear PipeWire tokens Button label in Settings > Troubleshooting tab. Clears stored PipeWire screen-selection tokens so the user is prompted again on next start.
93 APP_SETTINGS.CLEAR_PIPEWIRE_TOKENS_HELP Prompt for screen selection on next start Tooltip explaining what clearing PipeWire tokens does.
94 APP_SETTINGS.CLEAR_SAVED_STATE Clear saved state Button label in Settings > Troubleshooting tab. Resets overlay positions and set placements to defaults.
95 APP_SETTINGS.CLEAR_SAVED_STATE_HELP Reset sets & overlay positions Tooltip explaining what clearing saved state does. "Overlay" was previously translated as "${DEFINITIONS.OVERLAY}".
96 APP_SETTINGS.CLICK_FREEZE_TIME_MS Click freeze time (ms) Slider/numeric input in Settings > Features tab. Sets a time window (in milliseconds) to help with double-click precision.
97 APP_SETTINGS.CLICK_FREEZE_TIME_MS_HELP Helps with double-click precision Tooltip for the click freeze time setting.
98 APP_SETTINGS.CLOCK_12H 12-hour clock Checkbox label in Settings > Look & Feel tab. Toggles between 12-hour and 24-hour time display.
99 APP_SETTINGS.CONTROLS Controls Category header in Settings. Groups input/controller-related settings.
100 APP_SETTINGS.DELETE_ALL_CONFIGS Wipe configuration Button label in Settings > Troubleshooting tab. Removes all configuration files from conf.d.
101 APP_SETTINGS.DELETE_ALL_CONFIGS_HELP Remove all configuration files from conf.d Tooltip explaining the Wipe configuration button.
102 APP_SETTINGS.DOUBLE_CURSOR_FIX Double cursor fix Checkbox label in Settings > Miscellaneous tab. Enables a workaround for systems that show two cursors.
103 APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP Enable this if you see 2 cursors Tooltip for the double cursor fix checkbox.
104 APP_SETTINGS.DEFAULT_OVERLAY_SCALE Default overlay size Slider label in Settings > Look & Feel tab. Sets the default scale for newly created overlays.
105 APP_SETTINGS.DEFAULT_OVERLAY_SCALE_HELP Spawn new overlays at this scale. Tooltip for the default overlay size slider. "Overlay" was previously translated as "${DEFINITIONS.OVERLAY}".
106 APP_SETTINGS.DEFAULT_CURVATURE Default overlay curvature Slider label in Settings > Look & Feel tab. Sets the default curvature for new overlays. "Overlay" was previously translated as "${DEFINITIONS.OVERLAY}".
107 APP_SETTINGS.DEFAULT_OPACITY Default overlay opacity Slider label in Settings > Look & Feel tab. Sets the default opacity for new overlays. "Overlay" was previously translated as "${DEFINITIONS.OVERLAY}".
108 APP_SETTINGS.DEFAULT_POSITIONING Default overlay positioning Dropdown label in Settings > Look & Feel tab. Sets the default positioning mode (anchored/floating/static) for new overlays. "Overlay" was previously translated as "${DEFINITIONS.OVERLAY}".
109 APP_SETTINGS.OVERLAY_DEFAULTS_HELP Only applies to new overlays Tooltip shared by default overlay settings (curvature, opacity, positioning). Notes these don't affect existing overlays. "Overlay" was previously translated as "${DEFINITIONS.OVERLAY}".
110 APP_SETTINGS.ENABLED Enabled Label used for enabling space gravity and related physics features in the space drag settings.
111 APP_SETTINGS.FEATURES Features Category header in Settings. Previously translated as ${DEFINITIONS.FEATURES}
112 APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE Mouse move on trigger touch Setting in Settings > Features tab. When enabled, moving the trigger touch moves the mouse cursor.
113 APP_SETTINGS.HANDSFREE_POINTER Handsfree mode Dropdown label in Settings > Features tab. Selects the input method used when motion controllers are unavailable.
114 APP_SETTINGS.HANDSFREE_POINTER_HELP Input to use when motion controllers are unavailable. Left pinch is grab, right is click. Tooltip for the handsfree mode dropdown.
115 APP_SETTINGS.HANDSFREE_ALT_TAB App switcher aim Dropdown/setting in Settings > Features tab. Controls how the alt-tab app switcher is aimed.
116 APP_SETTINGS.HANDSFREE_ALT_TAB_HELP Hold Super+X, aim at the desired window, then release to switch focus. Tooltip explaining the handsfree alt-tab behavior.
117 APP_SETTINGS.HIDE_GRAB_HELP Hide grab help Checkbox label in Settings > Look & Feel tab. Hides the grab help overlay/text.
118 APP_SETTINGS.HIDE_USERNAME Hide username Checkbox label in Settings > Look & Feel tab. Hides the user's username from the UI.
119 APP_SETTINGS.INPUT_EMULATION_METHOD Input emulation method Dropdown label in Settings > Miscellaneous tab. Selects how WayVR emulates mouse/keyboard input (uinput, Wayland virtual, none).
120 APP_SETTINGS.INPUT_EMULATION_METHOD_HELP Try change this in case mouse or keyboard input does not register. Tooltip for the input emulation method dropdown.
121 APP_SETTINGS.INPUT_CAPTURE_METHOD Input capture method Dropdown label in Settings > Miscellaneous tab. Selects how physical input devices are captured for use inside WayVR.
122 APP_SETTINGS.INPUT_CAPTURE_METHOD_HELP Allows using physical peripherial inside WayVR. Super+Z: Switch input between WayVR and real desktop Super+X: Switch between WayVR apps Tooltip explaining the input capture method setting.
123 APP_SETTINGS.INPUT_PROFILES Change Input Bindings Button label in Settings > Controls tab. Opens the controller bindings editor popup.
124 APP_SETTINGS.INPUT_PROFILES_HELP OpenXR controller input bindings Tooltip for the Change Input Bindings button.
125 APP_SETTINGS.INVERT_SCROLL_DIRECTION_X Invert horizontal scroll direction Checkbox label in Settings > Features tab. Inverts the horizontal scroll direction.
126 APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y Invert vertical scroll direction Checkbox label in Settings > Features tab. Inverts the vertical scroll direction.
127 APP_SETTINGS.KEYBOARD_MIDDLE_CLICK Keyboard middle click Dropdown label in Settings > Features tab. Selects the modifier key used for middle-click when typing with the laser pointer.
128 APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP Modifier to use when typing with purple laser Tooltip for the keyboard middle-click setting.
129 APP_SETTINGS.KEYBOARD_SOUND_ENABLED Keyboard sounds Checkbox label in Settings > Features tab. Enables or disables typing sounds when using the on-screen keyboard.
130 APP_SETTINGS.LANGUAGE Language Dropdown label in Settings > Look & Feel tab. Selects the UI language.
131 APP_SETTINGS.LEFT_HANDED_MOUSE Left-handed mouse Checkbox label in Settings > Features tab. Swaps mouse buttons for left-handed users.
132 APP_SETTINGS.LEFT_HANDED_MOUSE_HELP Use this if mouse buttons are swapped Tooltip for the left-handed mouse checkbox.
133 APP_SETTINGS.LONG_PRESS_DURATION Long press duration Setting in Settings > Features tab. Controls how long a press must be held to register as a long press.
134 APP_SETTINGS.LOOK_AND_FEEL Look & Feel Category header in Settings. Groups visual/customization settings like language, opacity, animation speed, color palettes.
135 APP_SETTINGS.MISC Miscellaneous Category header in Settings. Groups troubleshooting and system-level settings like capture method, input emulation, xwayland.
136 APP_SETTINGS.NOTIFICATIONS_ENABLED Enable notifications Checkbox label in Settings > Features tab. Enables or disables system notifications within WayVR.
137 APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED Notification sounds Checkbox label in Settings > Features tab. Enables or disables sound effects for notifications.
138 APP_SETTINGS.NOT_SUPPORTED Not supported Label shown in the space drag/physics settings when a feature (like gravity) is not supported by the current backend.
139 APP_SETTINGS.NO_SKYMAPS_FOUND No skymaps found Label shown in the skymap browser when no skymaps are available locally. "Skymap" was previously translated as "${DEFINITIONS.SKYMAP}".
140 APP_SETTINGS.OPAQUE_BACKGROUND Opaque background Checkbox label in Settings > Look & Feel tab. Makes overlay backgrounds fully opaque (no transparency).
141 APP_SETTINGS.OPTION.ANCHORED_HELP Moves with center marker. Recommended. Tooltip for the Anchored positioning option.
142 APP_SETTINGS.OPTION.FLOATING_HELP Moves independently, recenters. Easy to misplace; not recommended. Tooltip for the Floating positioning option.
143 APP_SETTINGS.OPTION.STATIC_HELP Stays in place relative to world. Tooltip for the Static positioning option.
144 APP_SETTINGS.OPTION.AUTO Automatic Dropdown option for screen capture method. Uses ScreenCopy GPU if supported, otherwise PipeWire GPU.
145 APP_SETTINGS.OPTION.AUTO_HELP ScreenCopy GPU if supported, otherwise PipeWire GPU. Tooltip for the Automatic capture method option.
146 APP_SETTINGS.OPTION.EYE_ONLY Eye laser Dropdown option for handsfree pointer mode. Uses only eye-tracking laser (no pinch).
147 APP_SETTINGS.OPTION.EYE_PINCH Eye + pinch Dropdown option for handsfree pointer mode. Uses eye-tracking for aiming and pinch for click.
148 APP_SETTINGS.OPTION.HMD_ONLY HMD laser Dropdown option for handsfree pointer/alt-tab mode. Uses only the HMD forward laser.
149 APP_SETTINGS.OPTION.HMD_PINCH HMD + pinch Dropdown option for handsfree pointer mode. Uses HMD laser for aiming and pinch for click.
150 APP_SETTINGS.OPTION.NONE None Dropdown option used as the no binding or disabled choice in various settings (input emulation, input capture, handsfree pointer, alt modifier, whisper model).
151 APP_SETTINGS.OPTION.NONE_INPUT_HELP Do not emulate mouse and keyboard. Will not be able to interact with screens. Tooltip for the None input emulation option.
152 APP_SETTINGS.OPTION.NONE_INPUT_CAPTURE_HELP Do not capture mouse and keyboard. Will not be able to use physical mouse or keyboard in apps launched inside WayVR. Tooltip for the None input capture option.
153 APP_SETTINGS.OPTION.PIPEWIRE_HELP Fast GPU capture, standard on all desktops. Tooltip for the PipeWire GPU capture method option.
154 APP_SETTINGS.OPTION.PW_FALLBACK_HELP Slow method with high CPU usage. Try in case PipeWire GPU doesn't work Tooltip for the PipeWire CPU (fallback) capture method option.
155 APP_SETTINGS.OPTION.SCREENCOPY_GPU_HELP Fast, no screen share popups. Works on: Hyprland, Niri, River, Sway Tooltip for the ScreenCopy GPU capture method option.
156 APP_SETTINGS.OPTION.SCREENCOPY_HELP Slow, no screen share popups. Works on: Hyprland, Niri, River, Sway Tooltip for the ScreenCopy CPU capture method option.
157 APP_SETTINGS.OPTION.UINPUT Device emulation Dropdown option for input emulation method. Uses the uinput kernel module to emulate input devices.
158 APP_SETTINGS.OPTION.UINPUT_HELP Uses the uinput module to emulate a device. Known to work well on most desktops. Tooltip for the Device emulation (uinput) option.
159 APP_SETTINGS.OPTION.EVDEV_HELP Grab input devices for exclusive use. Your user must be in the input group. Tooltip for the evdev input capture method option.
160 APP_SETTINGS.OPTION.WL_VIRTUAL Wayland virtual input Dropdown option for input emulation method. Uses Wayland virtual pointer/keyboard protocols.
161 APP_SETTINGS.OPTION.WL_VIRTUAL_HELP Send events to the Wayland compositor using zwlr_virtual_pointer and zwp_virtual_keyboard. Only works reliably on some desktops. Does NOT work on KDE, GNOME or COSMIC. Tooltip for the Wayland virtual input option.
162 APP_SETTINGS.POINTER_ACCELERATION Mouse acceleration Checkbox/dropdown in Settings > Features tab. Toggles adaptive mouse acceleration (on) or constant speed (off).
163 APP_SETTINGS.POINTER_ACCELERATION_HELP On: Adaptive mouse acceleration Off: Constant speed Tooltip for the mouse acceleration setting.
164 APP_SETTINGS.POINTER_LERP_FACTOR Pointer smoothing Slider in Settings > Features tab. Controls the linear interpolation (smoothing) factor for pointer movement.
165 APP_SETTINGS.POINTER_SPEED Mouse speed Slider in Settings > Features tab. Controls the base mouse pointer speed.
166 APP_SETTINGS.REQUIRES_RESTART Requires restart Label shown below settings that require a software restart to take effect.
167 APP_SETTINGS.RESET_PLAYSPACE Reset playspace Button in Settings > Space Drag tab. Clears the stage space offset, resetting playspace position. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
168 APP_SETTINGS.RESET_PLAYSPACE_HELP Clear the stage space offset. Tooltip for the Reset playspace button. "Space" in this context refers to "Playspace" which was translated as "${DEFINITIONS.PLAYSPACE}".
169 APP_SETTINGS.SAVE_PLAYSPACE_CENTER Save playspace center Button in Settings > Space Drag tab. Saves the current playspace center as the reset target. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
170 APP_SETTINGS.SAVE_PLAYSPACE_CENTER_HELP Use current playspace for reset playspace binding. Tooltip for the Save playspace center button. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
171 APP_SETTINGS.RESET_PLAYSPACE_CENTER Reset playspace center Button in Settings > Space Drag tab. Clears the previously saved playspace center. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
172 APP_SETTINGS.RESET_PLAYSPACE_CENTER_HELP Clear previously set playspace center. Tooltip for the Reset playspace center button. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
173 APP_SETTINGS.RESTART_SOFTWARE Restart software Button in Settings > Troubleshooting tab. Restarts the WayVR software to apply settings that require a restart.
174 APP_SETTINGS.RESTART_SOFTWARE_HELP Apply settings that require a restart Tooltip for the Restart software button.
175 APP_SETTINGS.ROUND_MULTIPLIER UI Edge roundness Slider in Settings > Look & Feel tab. Controls how rounded the corners of UI elements appear (range 0.1-5.0).
176 APP_SETTINGS.SCREEN_RENDER_DOWN Render screen at lower resolution Checkbox in Settings > Miscellaneous tab. Renders the captured desktop screen at a lower resolution to improve performance or reduce aliasing.
177 APP_SETTINGS.SCREEN_RENDER_DOWN_HELP Helps with aliasing on high-res screens Tooltip for the lower-resolution screen render setting.
178 APP_SETTINGS.SCROLL_SPEED Scroll speed Slider in Settings > Features tab. Controls how fast scrolling occurs.
179 APP_SETTINGS.SELECT_VARIANT Select variant Label/button in the color palette or variant selection UI. Allows choosing between different theme variants.
180 APP_SETTINGS.SNAP_ANGLE_DEG Window pitch & roll snap angle Slider in Settings > Features tab. Sets the angle (in degrees) at which grabbed windows snap on pitch and roll axes.
181 APP_SETTINGS.SNAP_ANGLE_DEG_HELP Grabbed windows snap to this angle on pitch and roll axis. Tooltip for the snap angle setting.
182 APP_SETTINGS.ENABLE_WATCH Enable watch Checkbox in Settings > Look & Feel tab. Enables the wrist watch UI element. "Watch" was previously translated as "${DEFINITIONS.WATCH}".
183 APP_SETTINGS.SETS_ON_WATCH Sets on watch Checkbox in Settings > Look & Feel tab. Shows overlay sets on the wrist watch display. "Watch" was previously translated as "${DEFINITIONS.WATCH}". "Set" was previously translated as "${DEFINITIONS.SET}".
184 APP_SETTINGS.SHOW_WELCOME_SCREEN Show welcome screen Checkbox in Settings > Features tab. Controls whether the welcome/tutorial screen is shown on first launch.
185 APP_SETTINGS.SKYBOX Skymap Category header in Settings > Skymap tab. Groups skymap-related settings. "Skymap" was previously translated as "${DEFINITIONS.SKYMAP}".
186 APP_SETTINGS.SKYMAP_ALREADY_DOWNLOADED This skymap is already downloaded. Select desired action. Message shown in a dialog when attempting to download a skymap that is already present locally. "Skymap" was previously translated as "${DEFINITIONS.SKYMAP}".
187 APP_SETTINGS.SPACE_DRAG Playspace Category header in Settings. Groups playspace drag/physics settings including reset buttons and gravity. "Playspace" was previously translated as "${DEFINITIONS.PLAYSPACE}".
188 APP_SETTINGS.SPACE_DRAG_MULTIPLIER Space drag multiplier Setting in the space drag physics panel. Multiplies the force applied during space drag. "Space" in this context refers to "Playspace" which was translated as "${DEFINITIONS.PLAYSPACE}".
189 APP_SETTINGS.SPACE_DRAG_AFFECTS_WORLD Leave overlays behind during space move Checkbox in Settings > Space Drag tab. When enabled, moving the playspace leaves overlays behind instead of moving them with the set. "Overlay" was previously translated as "${DEFINITIONS.OVERLAY}". "Space" in this context refers to "Playspace" which was translated as "${DEFINITIONS.PLAYSPACE}".
190 APP_SETTINGS.SPACE_DRAG_UNLOCKED Allow space drag on all axes Checkbox in Settings > Space Drag tab. Unlocks space drag to work on all axes instead of a constrained axis. "Space" in this context refers to "Playspace" which was translated as "${DEFINITIONS.PLAYSPACE}".
191 APP_SETTINGS.SPACE_GRAVITY_DAMPING Damping Setting in the space gravity physics panel. Artificial drag to slow movement (0.1 = high drag, 1.0 = no drag).
192 APP_SETTINGS.SPACE_GRAVITY_DAMPING_HELP Artificial drag to slow down movement. 0.1 - high drag, 1.0 - no drag Tooltip for the inertial damping setting.
193 APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH Fling strength Setting in the space gravity physics panel. Intensity multiplier for the gravitational launch force after space-drag.
194 APP_SETTINGS.SPACE_GRAVITY_FLING_STRENGTH_HELP Intensity multiplier of gravitational launch force after space-drag. 0.0 - no movement at all, 2.0 - double intensity Tooltip for the fling strength setting. "Space" in this context refers to "Playspace" which was translated as "${DEFINITIONS.PLAYSPACE}".
195 APP_SETTINGS.SPACE_GRAVITY_GRAVITY Gravity Setting in the space gravity physics panel. Amount of downward force (0.0 = no gravity).
196 APP_SETTINGS.SPACE_GRAVITY_GRAVITY_HELP Amount of downwards force. 0.0 - no gravity Tooltip for the gravity setting.
197 APP_SETTINGS.SPACE_GRAVITY_GROUND_FRICTION Ground friction Setting in the space gravity physics panel. Friction when touching the ground (0.0 = ice-like, 1.0 = rough).
198 APP_SETTINGS.SPACE_GRAVITY_GROUND_FRICTION_HELP Amount of friction slowing you down if you're touching the ground. 0.0 - no friction (just like on ice), 1.0 - rough surface Tooltip for the ground friction setting.
199 APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT Floor height Setting in the space gravity physics panel. The Y position where the virtual floor is.
200 APP_SETTINGS.SPACE_GRAVITY_FLOOR_HEIGHT_HELP The Y position where the floor is. Gravity stops when you reach this height. Tooltip for the floor height setting.
201 APP_SETTINGS.SPACE_ROTATE_UNLOCKED Allow space rotate on all axes Checkbox in Settings > Space Drag tab. Unlocks space rotate to work on all axes. "Space" in this context refers to "Playspace" which was translated as "${DEFINITIONS.PLAYSPACE}".
202 APP_SETTINGS.TROUBLESHOOTING Troubleshooting Category header in Settings. Groups diagnostic/reset actions like clearing tokens, wiping config, and restarting.
203 APP_SETTINGS.UI_GRADIENT_INTENSITY UI Gradient intensity Slider in Settings > Look & Feel tab. Controls the intensity of gradient effects on the UI (range 0.0-1.0).
204 APP_SETTINGS.UPRIGHT_SCREEN_FIX Upright screen fix Checkbox in Settings > Miscellaneous tab. Fixes upright screen orientation on some desktop environments.
205 APP_SETTINGS.UPRIGHT_SCREEN_FIX_HELP Fixes upright screens on some desktops Tooltip for the upright screen fix checkbox.
206 APP_SETTINGS.USE_PASSTHROUGH Enable passthrough Checkbox in Settings > Skybox tab. Allows camera passthrough mode if the XR runtime supports it.
207 APP_SETTINGS.USE_PASSTHROUGH_HELP Allow passthrough if the XR runtime supports it Tooltip for the passthrough checkbox.
208 APP_SETTINGS.USE_SKYBOX Show skymap Checkbox in Settings > Skybox tab. Shows a skybox when there's no scene app or passthrough active. "Skymap" was previously translated as "${DEFINITIONS.SKYMAP}".
209 APP_SETTINGS.USE_SKYBOX_HELP Show a skymap if there's no scene app or passthrough Tooltip for the enable skybox checkbox. "Skymap" was previously translated as "${DEFINITIONS.SKYMAP}".
210 APP_SETTINGS.WATCH_VIEW_ANGLE Watch view angles Setting in Settings > Look & Feel tab. Controls the view angles at which the wrist watch fades in/out. "Watch" was previously translated as "${DEFINITIONS.WATCH}".
211 APP_SETTINGS.WATCH_VIEW_ANGLE_HELP Control how the watch fades away Tooltip for the watch view angles setting. "Watch" was previously translated as "${DEFINITIONS.WATCH}".
212 APP_SETTINGS.WHISPER.NEED_TO_DOWNLOAD_MODEL The selected model needs to be downloaded. Download it right now? Message shown in a dialog box when the user selects a Whisper model that hasn't been downloaded yet.
213 APP_SETTINGS.WHISPER.REMOVE_UNUSED_MODELS You are turning off the speech-to-text feature. Would you like to remove downloaded Whisper models to free up space? Message shown in a dialog box when the user disables the whisper feature.
214 APP_SETTINGS.WHISPER_MODEL Speech-to-text model Dropdown label in Settings > Features tab. Selects which Whisper model to use for speech-to-text.
215 APP_SETTINGS.WHISPER_MODEL_HELP Whisper model to use. Larger models produce more accurate results, but consume more VRAM. Tooltip for the speech-to-text model dropdown.
216 APP_SETTINGS.GRID_OPACITY Floor grid opacity Slider in Settings > Skybox tab. Controls the opacity of the floor grid when skybox is enabled.
217 APP_SETTINGS.GRID_OPACITY_HELP Opacity of the floor grid when the skymap is enabled Tooltip for the floor grid opacity slider. "Skymap" was previously translated as "${DEFINITIONS.SKYMAP}".
218 APP_SETTINGS.XWAYLAND_BY_DEFAULT Run apps in Compatibility mode by default Checkbox in Settings > Miscellaneous tab. Launches apps in Cage/compatibility mode by default.
219 APP_SETTINGS.SAVE Save Button label in the controller bindings editor popup. Saves the current bindings configuration.
220 APP_SETTINGS.CANCEL Cancel Button label in the controller bindings editor popup and in whisper model dialogs. Cancels/dismisses the dialog without saving.
221 APPLICATION_LAUNCHER Application launcher App launcher configuration popup title - appears as the label for the app launch/options dialog.
222 APPLICATION_STARTED Application started Toast notification shown after a successful app launch.
223 APPLICATIONS Applications Tab label in the dashboard sidebar for the Apps tab.
224 AUDIO.AUTO_SWITCH_TO_VR_AUDIO Auto-switch to VR audio Tooltip on the auto-switch audio button in the audio settings popup.
225 AUDIO.CARDS Cards Button label in the audio settings popup for selecting audio card profiles.
226 AUDIO.FAILED_TO_SWITCH_MICROPHONE Failed to switch microphone Error toast shown when switching to a VR microphone fails.
227 AUDIO.MICROPHONE_SET_SUCCESSFULLY Microphone set successfully Toast notification after successfully switching the microphone.
228 AUDIO.MICROPHONES Microphones Button label in the audio settings popup for selecting microphone sources.
229 AUDIO.NO_VR_MICROPHONE_SWITCH_MANUALLY No VR microphone found. Switch it manually. Toast shown when no VR microphone is detected and manual switching is needed.
230 AUDIO.NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY No VR speakers found. Switch them manually. Toast shown when no VR speakers are detected after auto-switch.
231 AUDIO.SELECT_AUDIO_CARD_PROFILE Select audio card profile Bold label in the audio settings popup for choosing an audio card profile.
232 AUDIO.SETTINGS Audio settings Window title for the audio settings popup opened from the dashboard.
233 AUDIO.SPEAKERS Speakers Button label in the audio settings popup for selecting speaker sinks.
234 AUDIO.SPEAKERS_SET_SUCCESSFULLY Speakers set successfully Toast notification after successfully switching speakers.
235 AUDIO.VOLUME Volume Tooltip on the audio volume button in the dashboard.
236 CLOSE_WINDOW Close window Close button label used in dialog boxes, download file popup, and window options.
237 CREATION_DATE Creation date Column label in the remote skymap downloader showing file metadata.
238 DEBUG_INFO Debug info Tab name in the Monado runtime section of the dashboard.
239 DISPLAY_BRIGHTNESS Display brightness Label for the display brightness setting in the Monado general settings tab.
240 DONATE.SUPPORT_US Support us Button tooltip on the home screen donate button.
241 DONATE.DESCRIPTION We're a small team of 2 developers building WayVR in our free time. If you enjoy using this software, please consider supporting us - every donation helps us keep going. Description text on the donate tab explaining the project.
242 DONATE.THANK_YOU_WAYVR Thank you from the WayVR Team! Thank you message displayed on the donate tab.
243 DONATE.BUTTON_TOOLTIP Donate via Open Collective Tooltip on the donate button on the donate tab.
244 DONATE.CURRENT_SUPPORTERS Current Supporters Section header on the donate tab listing supporters.
245 DONATE.BROUGHT_TO_YOU_VARIANTS_OFTEN Supported by {USER}|Special thanks to {USER}|Sponsored by {USER}|Backed by {USER}|Driven by community members like {USER}|Made possible by {USER}|Sustained by {USER}|Contributed by {USER}|Funded by {USER} This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it.
246 DONATE.BROUGHT_TO_YOU_VARIANTS_RARE Coffee provided by {USER}|Fuelled by {USER}|Shoutout to {USER}!|Keeping us going: {USER}|Helping us grow: {USER}|Keeping the servers running: {USER}|With gratitude to {USER}|Powered by {USER}|Supported by friends like {USER} This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it (rare versions).
247 DONATE.BROUGHT_TO_YOU_VARIANTS_VERY_RARE Supported by legends like {USER}|Caffeine supplied by {USER}|A true legend: {USER}|Our hero of the day: {USER}|An absolute superstar: {USER}|Paying for the electricity bill: {USER}|The savior of our sanity: {USER}|Leading the way: {USER}|Caffeine-to-code converter provided by {USER}|Keeping the production stable: {USER}|The one and only: {USER}|Passing dmabuf buffers: {USER} This text will show up a random person from donations page - line below this string will display the supporter user. There are many variants of it (rare versions).
248 DOWNLOAD Download Button in the Whisper model download dialog to confirm downloading a model.
249 DOWNLOADER Downloader Window title for the file download popup.
250 WELCOME.ALL_SET You're all set! Main heading on the final welcome/tutorial page.
251 WELCOME.BASICS These basics will allow you to start using WayVR with ease. Description text on the final welcome page under the You are all set heading.
252 WELCOME.CENTER_MARKER Center marker is what will appear in front of you when recentering. Place overlays around it! Description of the center marker on the moving your set tutorial page. "Overlay" was previously translated as "${DEFINITIONS.OVERLAY}".
253 WELCOME.DOUBLE_PRESS_TO_TOGGLE Double-press B (on Index) or Y (on Meta) to show, recenter or hide your set. Try it now. Instruction text on the working set tutorial page explaining the double-press gesture. "Set" was previously translated as "${DEFINITIONS.SET}".
254 WELCOME.FEATURES_DOCUMENTATION There are many other features worth customizing. For more information, check the documentation at Text on the final welcome page linking to documentation.
255 WELCOME.FINISH_TUTORIAL Finish tutorial Button text on the final welcome page to complete the tutorial.
256 WELCOME.GRAB_BOTH_HANDS Grab it with both hands if you want to move a specific overlay in your set. Instruction text on the moving your set tutorial page for two-hand grab.
257 WELCOME.GRAB_ONE_HAND Grab it with one hand to move your set. Instruction text on the moving your set tutorial page for one-hand grab.
258 WELCOME.GREETING Hi there! Greeting label on the first welcome page.
259 WELCOME.GUIDE_INTRO Let us guide you through your first steps. Intro text on the first welcome page below the greeting.
260 WELCOME.LASER_COLORS Laser Colors Page title on the laser colors tutorial page.
261 WELCOME.LASER_FUNCTIONALITY Much of the functionality in WayVR depends on what color of laser is used to interact with a UI element. You don't need to press these buttons, just touch them! Description text on the laser colors tutorial page.
262 WELCOME.LAST_PAGE_INFO This tutorial will stop showing up once you get to the last page. Info text on the first welcome page noting the tutorial is near the end.
263 WELCOME.LOOK_AT_LEFT_WRIST Look at your left wrist. That's your watch. Instruction text on the watch tutorial page. "Watch" was previously translated as "${DEFINITIONS.WATCH}".
264 WELCOME.MIDDLE_CLICK_MODE_PURPLE_LASER Middle-click Mode: Purple laser Laser mode label on the laser colors tutorial page.
265 WELCOME.MOVING_YOUR_SET Moving your set Page title on the moving your set tutorial page.
266 WELCOME.NEXT_BUTTON Press "Next" button below to get started. Label on the first welcome page pointing to the next button.
267 WELCOME.REGULAR_MODE_BLUE_LASER Regular Mode: Blue laser Laser mode label on the laser colors tutorial page.
268 WELCOME.REPOSITION_THIS_WINDOW_BY_GRABBING Reposition this window using your controller's grip action. Instruction text on the first welcome page about window repositioning.
269 WELCOME.RIGHT_CLICK_MODE_ORANGE_LASER Right-click Mode: Orange laser Laser mode label on the laser colors tutorial page.
270 WELCOME.THANKS_FOR_INSTALLING Thank you for installing WayVR! Thanks text on the first welcome page below the greeting.
271 WELCOME.WATCH Watch Page title on the watch/tutorial page. "Watch" was previously translated as "${DEFINITIONS.WATCH}".
272 WELCOME.WORKING_SET Working Set Page title on the working set tutorial page. "Set" was previously translated as "${DEFINITIONS.SET}". Working as in "Current".
273 DOWNLOAD_AGAIN Download again Button in the skymap already downloaded dialog to re-download a skymap.
274 DOWNLOADING_FILE Downloading file... Status label in the download file popup showing download progress.
275 FAILED_TO_LAUNCH_APPLICATION Failed to launch a application: Error prefix in the toast shown when app launch fails.
276 GAME_LAUNCHED Game launched Toast notification shown after successfully launching a game via Steam.
277 GAME_LIST.NO_GAMES_FOUND No games found Empty state text shown in the game list when no games are installed.
278 GAME_LIST.RUNNING_GAMES_LIST List of running games Section label in the running games list view.
279 GAMES Games Tab label in the dashboard sidebar for the Games tab.
280 GENERAL_SETTINGS General settings Tab name and group box title in the Monado runtime settings.
281 GETTING_STARTED Getting started Tab label in the dashboard sidebar for the Welcome/tutorial tab.
282 HEIGHT Height Label for the height dimension field in the add display popup.
283 HELLO Hello! Fallback greeting on the home screen when username is hidden.
284 HELLO_USER Hello, {USER}! Greeting on the home screen with the user name substituted in.
285 HIDE Hide Used in the double-press tutorial context for hiding the set.
286 HOME_SCREEN Home Tab label in the dashboard sidebar for the Home tab.
287 MODIFICATION_DATE Modification date Column label in the remote skymap downloader showing file metadata.
288 MONADO_RUNTIME Monado runtime Tab label in the dashboard sidebar for the Monado runtime tab.
289 LOADING Loading... Label in the loading spinner template used across the UI.
290 POPUP_ADD_DISPLAY.RESOLUTION Resolution Label for the resolution field in the add display popup.
291 PROCESS.FORCE_KILL Force-kill Tooltip on the kill button in the running games list.
292 PROCESS.STOP Stop Tooltip on the stop button in the running games list.
293 PROCESS_LIST Process list Tab name and group box title in the Monado runtime process list section.
294 REFRESH Refresh Tooltip on the refresh button in the running games list.
295 REMOVE Remove Button label in the skymap already downloaded dialog and Whisper cleanup dialog to remove files.
296 APPLY Apply Button label in the skymap already downloaded dialog to apply the selected skymap.
297 RELOAD_FROM_DISK Reload from disk Tooltip on the reload button in the skymap list view.
298 SETTINGS Settings Tab label in the dashboard sidebar for the Settings tab. Previously translated as ${DEFINITIONS.SETT}
299 SHOW Show Used in the double-press tutorial context for showing the set.
300 TARGET_PATH Target path Label for the target path display in the download file popup.
301 TERMINATE_PROCESS Terminate process Button label in the window options bar to kill a process.
302 VERSION Version Label for the version display in the remote skymap downloader.
303 WIDTH Width Label for the width dimension field in the add display popup.
304 PINNED_APPS Pinned applications Section header label for the pinned apps list on the Apps tab, a.k.a. "Favourites"
305 SAVED_TO_FAVOURITES Saved to pinned apps Toast notification shown after pinning an app to favourites. "Pinned apps" was previously translated as "${PINNED_APPS}".
306 ADD_TO_FAVOURITES Add to pinned apps Label on the pin button in the app launcher popup that is used to add to favourites.. "Pinned apps" was previously translated as "${PINNED_APPS}".
307 ADD_TO_FAVOURITES_HINT Save preset and pin it to the app drawer Tooltip on the add to favourites button in the app launcher popup. "Pinned apps" was previously translated as "${PINNED_APPS}".
308 REMOVE_FROM_FAVOURITES Remove from pinned apps Label on the unpin section in the app launcher popup. "Pinned apps" was previously translated as "${PINNED_APPS}".
309 EMPTY Empty Label shown in the pinned apps section when there are no pinned apps.

View File

@ -1,4 +1,21 @@
{ {
"DEFINITIONS": {
"ANCHORED": "Anchored",
"FLOATING": "Floating",
"STATIC": "Static",
"SET": "Set",
"WATCH": "Watch",
"DASHBOARD": "Dashboard",
"EDIT_MODE": "Edit Mode",
"SETTINGS": "Settings",
"KEYBOARD": "Keyboard",
"TASKBAR": "Taskbar",
"FEATURES": "Features",
"OVERLAY": "Overlay",
"SKYMAP": "Skymap",
"PLAYSPACE": "Playspace",
"D_PAD": "D-pad"
},
"ACTIONS": { "ACTIONS": {
"RECENTER_PLAYSPACE": "Re-center playspace" "RECENTER_PLAYSPACE": "Re-center playspace"
}, },
@ -17,15 +34,6 @@
"CAGE": "Compatibility mode (Cage)", "CAGE": "Compatibility mode (Cage)",
"NATIVE": "Native mode" "NATIVE": "Native mode"
}, },
"POS": {
"ANCHORED": "Anchored",
"ANCHORED_HELP": "Stays in place relative to center marker.",
"FLOATING": "Floating",
"FLOATING_HELP": "Moves independently, recenters on show.",
"STATIC": "Static",
"STATIC_HELP": "Not part of any set. Does not recenter."
},
"POS_TITLE": "Positioning",
"RES_TITLE": "Resolution" "RES_TITLE": "Resolution"
}, },
"APP_SETTINGS": { "APP_SETTINGS": {
@ -93,7 +101,7 @@
}, },
"BROWSE_ONLINE_CATALOG": "Browse online catalog...", "BROWSE_ONLINE_CATALOG": "Browse online catalog...",
"BROWSE_SKYMAPS": "Browse skymaps", "BROWSE_SKYMAPS": "Browse skymaps",
"CAPTURE_METHOD": "Wayland screen capture", "CAPTURE_METHOD": "Screen capture method",
"CAPTURE_METHOD_HELP": "Try changing this if you are\nexperiencing black or glitchy screens", "CAPTURE_METHOD_HELP": "Try changing this if you are\nexperiencing black or glitchy screens",
"COLOR_KEYING": "Color keying", "COLOR_KEYING": "Color keying",
"COLOR_PALETTE": "Color palette", "COLOR_PALETTE": "Color palette",
@ -103,7 +111,6 @@
"COLOR_PALETTE_CUSTOM_URL": "Add your own custom theme!", "COLOR_PALETTE_CUSTOM_URL": "Add your own custom theme!",
"COLOR_PALETTE_CUSTOM_URL2": "Click to open web manual.", "COLOR_PALETTE_CUSTOM_URL2": "Click to open web manual.",
"COLOR_PALETTE_ACTIVATE": "Click to use this theme.", "COLOR_PALETTE_ACTIVATE": "Click to use this theme.",
"APPLY_CHANGES_RESTART": "Restart WayVR to apply changes?",
"CLEAR_PIPEWIRE_TOKENS": "Clear PipeWire tokens", "CLEAR_PIPEWIRE_TOKENS": "Clear PipeWire tokens",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Prompt for screen selection on next start", "CLEAR_PIPEWIRE_TOKENS_HELP": "Prompt for screen selection on next start",
"CLEAR_SAVED_STATE": "Clear saved state", "CLEAR_SAVED_STATE": "Clear saved state",
@ -118,15 +125,23 @@
"DOUBLE_CURSOR_FIX_HELP": "Enable this if you see 2 cursors", "DOUBLE_CURSOR_FIX_HELP": "Enable this if you see 2 cursors",
"DEFAULT_OVERLAY_SCALE": "Default overlay size", "DEFAULT_OVERLAY_SCALE": "Default overlay size",
"DEFAULT_OVERLAY_SCALE_HELP": "Spawn new overlays at this scale.", "DEFAULT_OVERLAY_SCALE_HELP": "Spawn new overlays at this scale.",
"DEFAULT_CURVATURE": "Default overlay curvature",
"DEFAULT_OPACITY": "Default overlay opacity",
"DEFAULT_POSITIONING": "Default overlay positioning",
"OVERLAY_DEFAULTS_HELP": "Only applies to new overlays",
"ENABLED": "Enabled", "ENABLED": "Enabled",
"FEATURES": "Features", "FEATURES": "Features",
"FOCUS_FOLLOWS_MOUSE_MODE": "Mouse move on trigger touch", "FOCUS_FOLLOWS_MOUSE_MODE": "Mouse move on trigger touch",
"HANDSFREE_POINTER": "Handsfree mode", "HANDSFREE_POINTER": "Handsfree mode",
"HANDSFREE_POINTER_HELP": "Input to use when motion\ncontrollers are unavailable.\nLeft pinch is grab, right is click.", "HANDSFREE_POINTER_HELP": "Input to use when motion\ncontrollers are unavailable.\nLeft pinch is grab, right is click.",
"HANDSFREE_ALT_TAB": "App switcher aim",
"HANDSFREE_ALT_TAB_HELP": "Hold Super+X, aim at the desired window, then release to switch focus.",
"HIDE_GRAB_HELP": "Hide grab help", "HIDE_GRAB_HELP": "Hide grab help",
"HIDE_USERNAME": "Hide username", "HIDE_USERNAME": "Hide username",
"INPUT_EMULATION_METHOD": "Input emulation method", "INPUT_EMULATION_METHOD": "Input emulation method",
"INPUT_EMULATION_METHOD_HELP": "Try change this in case mouse or\nkeyboard input does not register.", "INPUT_EMULATION_METHOD_HELP": "Try change this in case mouse or\nkeyboard input does not register.",
"INPUT_CAPTURE_METHOD": "Input capture method",
"INPUT_CAPTURE_METHOD_HELP": "Allows using physical peripherial inside WayVR.\n Super+Z: Switch input between WayVR and real desktop\n Super+X: Switch between WayVR apps",
"INPUT_PROFILES": "Change Input Bindings", "INPUT_PROFILES": "Change Input Bindings",
"INPUT_PROFILES_HELP": "OpenXR controller input bindings", "INPUT_PROFILES_HELP": "OpenXR controller input bindings",
"INVERT_SCROLL_DIRECTION_X": "Invert horizontal scroll direction", "INVERT_SCROLL_DIRECTION_X": "Invert horizontal scroll direction",
@ -146,27 +161,39 @@
"NO_SKYMAPS_FOUND": "No skymaps found", "NO_SKYMAPS_FOUND": "No skymaps found",
"OPAQUE_BACKGROUND": "Opaque background", "OPAQUE_BACKGROUND": "Opaque background",
"OPTION": { "OPTION": {
"ANCHORED_HELP": "Moves with center marker. Recommended.",
"FLOATING_HELP": "Moves independently, recenters.\nEasy to misplace; not recommended.",
"STATIC_HELP": "Stays in place relative to world.",
"AUTO": "Automatic", "AUTO": "Automatic",
"AUTO_HELP": "ScreenCopy GPU if supported,\notherwise PipeWire GPU.", "AUTO_HELP": "ScreenCopy GPU if supported,\notherwise PipeWire GPU.",
"EYE_ONLY": "Eye only", "EYE_ONLY": "Eye laser",
"EYE_PINCH": "Eye + pinch", "EYE_PINCH": "Eye + pinch",
"HMD_ONLY": "HMD only", "HMD_ONLY": "HMD laser",
"HMD_PINCH": "HMD + pinch", "HMD_PINCH": "HMD + pinch",
"NONE": "None", "NONE": "None",
"NONE_INPUT_HELP": "Do not emulate mouse and keyboard.\nWill not be able to interact with screens.", "NONE_INPUT_HELP": "Do not emulate mouse and keyboard.\nWill not be able to interact with screens.",
"NONE_INPUT_CAPTURE_HELP": "Do not capture mouse and keyboard.\nWill not be able to use physical mouse or\nkeyboard in apps launched inside WayVR.",
"PIPEWIRE_HELP": "Fast GPU capture,\nstandard on all desktops.", "PIPEWIRE_HELP": "Fast GPU capture,\nstandard on all desktops.",
"PW_FALLBACK_HELP": "Slow method with high CPU usage.\nTry in case PipeWire GPU doesn't work", "PW_FALLBACK_HELP": "Slow method with high CPU usage.\nTry in case PipeWire GPU doesn't work",
"SCREENCOPY_GPU_HELP": "Fast, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway", "SCREENCOPY_GPU_HELP": "Fast, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Slow, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway", "SCREENCOPY_HELP": "Slow, no screen share popups.\nWorks on: Hyprland, Niri, River, Sway",
"UINPUT": "Device emulation", "UINPUT": "Device emulation",
"UINPUT_HELP": "Uses the uinput module to emulate a device.\nYour user must be in the input group.\nKnown to work well on most desktops.", "UINPUT_HELP": "Uses the uinput module to emulate a device.\nKnown to work well on most desktops.",
"EVDEV_HELP": "Grab input devices for exclusive use.\nYour user must be in the input group.",
"WL_VIRTUAL": "Wayland virtual input", "WL_VIRTUAL": "Wayland virtual input",
"WL_VIRTUAL_HELP": "Send events to the Wayland compositor using\nzwlr_virtual_pointer and zwp_virtual_keyboard.\nOnly works reliably on some desktops.\nDoes NOT work on KDE, GNOME or COSMIC." "WL_VIRTUAL_HELP": "Send events to the Wayland compositor using\nzwlr_virtual_pointer and zwp_virtual_keyboard.\nOnly works reliably on some desktops.\nDoes NOT work on KDE, GNOME or COSMIC."
}, },
"POINTER_ACCELERATION": "Mouse acceleration",
"POINTER_ACCELERATION_HELP": "On: Adaptive mouse acceleration\nOff: Constant speed",
"POINTER_LERP_FACTOR": "Pointer smoothing", "POINTER_LERP_FACTOR": "Pointer smoothing",
"POINTER_SPEED": "Mouse speed",
"REQUIRES_RESTART": "Requires restart", "REQUIRES_RESTART": "Requires restart",
"RESET_PLAYSPACE": "Reset playspace", "RESET_PLAYSPACE": "Reset playspace",
"RESET_PLAYSPACE_HELP": "Clear the stage space offset.", "RESET_PLAYSPACE_HELP": "Clear the stage space offset.",
"SAVE_PLAYSPACE_CENTER": "Save playspace center",
"SAVE_PLAYSPACE_CENTER_HELP": "Use current playspace for reset playspace binding.",
"RESET_PLAYSPACE_CENTER": "Reset playspace center",
"RESET_PLAYSPACE_CENTER_HELP": "Clear previously set playspace center.",
"RESTART_SOFTWARE": "Restart software", "RESTART_SOFTWARE": "Restart software",
"RESTART_SOFTWARE_HELP": "Apply settings that require a restart", "RESTART_SOFTWARE_HELP": "Apply settings that require a restart",
"ROUND_MULTIPLIER": "UI Edge roundness", "ROUND_MULTIPLIER": "UI Edge roundness",
@ -179,10 +206,11 @@
"ENABLE_WATCH": "Enable watch", "ENABLE_WATCH": "Enable watch",
"SETS_ON_WATCH": "Sets on watch", "SETS_ON_WATCH": "Sets on watch",
"SHOW_WELCOME_SCREEN": "Show welcome screen", "SHOW_WELCOME_SCREEN": "Show welcome screen",
"SKYBOX": "Skybox", "SKYBOX": "Skymap",
"SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.", "SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.",
"SPACE_DRAG": "Space drag", "SPACE_DRAG": "Playspace",
"SPACE_DRAG_MULTIPLIER": "Space drag multiplier", "SPACE_DRAG_MULTIPLIER": "Space drag multiplier",
"SPACE_DRAG_AFFECTS_WORLD": "Leave overlays behind during space move",
"SPACE_DRAG_UNLOCKED": "Allow space drag on all axes", "SPACE_DRAG_UNLOCKED": "Allow space drag on all axes",
"SPACE_GRAVITY_DAMPING": "Damping", "SPACE_GRAVITY_DAMPING": "Damping",
"SPACE_GRAVITY_DAMPING_HELP": "Artificial drag to slow down movement. 0.1 - high drag, 1.0 - no drag", "SPACE_GRAVITY_DAMPING_HELP": "Artificial drag to slow down movement. 0.1 - high drag, 1.0 - no drag",
@ -201,8 +229,8 @@
"UPRIGHT_SCREEN_FIX_HELP": "Fixes upright screens on some desktops", "UPRIGHT_SCREEN_FIX_HELP": "Fixes upright screens on some desktops",
"USE_PASSTHROUGH": "Enable passthrough", "USE_PASSTHROUGH": "Enable passthrough",
"USE_PASSTHROUGH_HELP": "Allow passthrough if the XR runtime supports it", "USE_PASSTHROUGH_HELP": "Allow passthrough if the XR runtime supports it",
"USE_SKYBOX": "Enable skybox", "USE_SKYBOX": "Show skymap",
"USE_SKYBOX_HELP": "Show a skybox if there's no scene app or passthrough", "USE_SKYBOX_HELP": "Show a skymap if there's no scene app or passthrough",
"WATCH_VIEW_ANGLE": "Watch view angles", "WATCH_VIEW_ANGLE": "Watch view angles",
"WATCH_VIEW_ANGLE_HELP": "Control how the watch fades away", "WATCH_VIEW_ANGLE_HELP": "Control how the watch fades away",
"WHISPER": { "WHISPER": {
@ -212,7 +240,7 @@
"WHISPER_MODEL": "Speech-to-text model", "WHISPER_MODEL": "Speech-to-text model",
"WHISPER_MODEL_HELP": "Whisper model to use.\nLarger models produce more accurate\nresults, but consume more VRAM.", "WHISPER_MODEL_HELP": "Whisper model to use.\nLarger models produce more accurate\nresults, but consume more VRAM.",
"GRID_OPACITY": "Floor grid opacity", "GRID_OPACITY": "Floor grid opacity",
"GRID_OPACITY_HELP": "Opacity of the floor grid when the skybox is enabled", "GRID_OPACITY_HELP": "Opacity of the floor grid when the skymap is enabled",
"XWAYLAND_BY_DEFAULT": "Run apps in Compatibility mode by default", "XWAYLAND_BY_DEFAULT": "Run apps in Compatibility mode by default",
"SAVE": "Save", "SAVE": "Save",
"CANCEL": "Cancel" "CANCEL": "Cancel"
@ -243,7 +271,10 @@
"DESCRIPTION": "We're a small team of 2 developers building WayVR in our free time. If you enjoy using this software, please consider supporting us - every donation helps us keep going.", "DESCRIPTION": "We're a small team of 2 developers building WayVR in our free time. If you enjoy using this software, please consider supporting us - every donation helps us keep going.",
"THANK_YOU_WAYVR": "Thank you from the WayVR Team!", "THANK_YOU_WAYVR": "Thank you from the WayVR Team!",
"BUTTON_TOOLTIP": "Donate via Open Collective", "BUTTON_TOOLTIP": "Donate via Open Collective",
"CURRENT_SUPPORTERS": "Current Supporters" "CURRENT_SUPPORTERS": "Current Supporters",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Supported by {USER}|Special thanks to {USER}|Sponsored by {USER}|Backed by {USER}|Driven by community members like {USER}|Made possible by {USER}|Sustained by {USER}|Contributed by {USER}|Funded by {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Coffee provided by {USER}|Fuelled by {USER}|Shoutout to {USER}!|Keeping us going: {USER}|Helping us grow: {USER}|Keeping the servers running: {USER}|With gratitude to {USER}|Powered by {USER}|Supported by friends like {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Supported by legends like {USER}|Caffeine supplied by {USER}|A true legend: {USER}|Our hero of the day: {USER}|An absolute superstar: {USER}|Paying for the electricity bill: {USER}|Leading the way: {USER}|Caffeine-to-code converter provided by {USER}|Keeping the production stable: {USER}|The one and only: {USER}|Passing dmabuf buffers: {USER}"
}, },
"DOWNLOAD": "Download", "DOWNLOAD": "Download",
"DOWNLOADER": "Downloader", "DOWNLOADER": "Downloader",
@ -262,12 +293,12 @@
"LASER_FUNCTIONALITY": "Much of the functionality in WayVR depends on what color of laser is used to interact with a UI element. You don't need to press these buttons, just touch them!", "LASER_FUNCTIONALITY": "Much of the functionality in WayVR depends on what color of laser is used to interact with a UI element. You don't need to press these buttons, just touch them!",
"LAST_PAGE_INFO": "This tutorial will stop showing up once you get to the last page.", "LAST_PAGE_INFO": "This tutorial will stop showing up once you get to the last page.",
"LOOK_AT_LEFT_WRIST": "Look at your left wrist. That's your watch.", "LOOK_AT_LEFT_WRIST": "Look at your left wrist. That's your watch.",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Middle-click Mode: Purple laser", "MIDDLE_CLICK_MODE_PURPLE_LASER": "Middle-click Mode: Purple laser",
"MOVING_YOUR_SET": "Moving your set", "MOVING_YOUR_SET": "Moving your set",
"NEXT_BUTTON": "Press \"Next\" button below to get started.", "NEXT_BUTTON": "Press Next button below to get started.",
"REGULAR_MODE_BLUE_LASER": "Regular Mode: Blue laser", "REGULAR_MODE_BLUE_LASER": "Regular Mode: Blue laser",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Reposition this window using your controller's grip action.", "REPOSITION_THIS_WINDOW_BY_GRABBING": "Reposition this window using your controller's grip action.",
"RIGHT_CLICK_MODE_ORANGE_LASER": "Right-click Mode: Orange laser", "RIGHT_CLICK_MODE_ORANGE_LASER": "Right-click Mode: Orange laser",
"THANKS_FOR_INSTALLING": "Thank you for installing WayVR!", "THANKS_FOR_INSTALLING": "Thank you for installing WayVR!",
"WATCH": "Watch", "WATCH": "Watch",
"WORKING_SET": "Working Set" "WORKING_SET": "Working Set"
@ -309,10 +340,10 @@
"TERMINATE_PROCESS": "Terminate process", "TERMINATE_PROCESS": "Terminate process",
"VERSION": "Version", "VERSION": "Version",
"WIDTH": "Width", "WIDTH": "Width",
"SAVED_TO_FAVOURITES": "Saved to favourites", "PINNED_APPS": "Pinned applications",
"ADD_TO_FAVOURITES": "Add to favourites", "SAVED_TO_FAVOURITES": "Saved to pinned apps",
"ADD_TO_FAVOURITES": "Add to pinned apps",
"ADD_TO_FAVOURITES_HINT": "Save preset and pin it to the app drawer", "ADD_TO_FAVOURITES_HINT": "Save preset and pin it to the app drawer",
"REMOVE_FROM_FAVOURITES": "Remove from favourites", "REMOVE_FROM_FAVOURITES": "Remove from pinned apps",
"EMPTY": "Empty", "EMPTY": "Empty"
"PINNED_APPS": "Pinned applications"
} }

View File

@ -1,114 +1,56 @@
{ {
"HOME_SCREEN": "Inicio", "DEFINITIONS": {
"MONADO_RUNTIME": "Monado tiempo de ejecución", "ANCHORED": "Anclado",
"APPLICATIONS": "Aplicaciones", "FLOATING": "Flotante",
"GAMES": "Juegos", "STATIC": "Estático",
"SETTINGS": "Ajustes", "SET": "Set",
"HELLO_USER": "¡Hola, {USER}!", "WATCH": "Reloj",
"GENERAL_SETTINGS": "Ajustes generales", "DASHBOARD": "Panel de control",
"APPLICATION_LAUNCHER": "Lanzador de aplicaciones", "EDIT_MODE": "Modo edición",
"APP_SETTINGS": { "SETTINGS": "Ajustes",
"HIDE_USERNAME": "Ocultar nombre de usuario", "KEYBOARD": "Teclado",
"OPAQUE_BACKGROUND": "Fondo opaco", "TASKBAR": "Barra de tareas",
"LOOK_AND_FEEL": "Apariencia y estilo",
"HIDE_GRAB_HELP": "Ocultar ayuda para agarrar",
"ANIMATION_SPEED": "Velocidad de animación de la IU",
"ROUND_MULTIPLIER": "Redondeo de bordes de la IU",
"USE_SKYBOX": "Activar skybox",
"USE_PASSTHROUGH": "Activar passthrough",
"CLOCK_12H": "Reloj de 12 horas",
"FEATURES": "Funciones", "FEATURES": "Funciones",
"NOTIFICATIONS_ENABLED": "Habilitar notificaciones", "OVERLAY": "Overlay",
"NOTIFICATIONS_SOUND_ENABLED": "Sonidos de notificación", "SKYMAP": "Skymap",
"KEYBOARD_SOUND_ENABLED": "Sonidos del teclado", "PLAYSPACE": "Espacio de juego",
"SPACE_DRAG_MULTIPLIER": "Multiplicador de arrastre espacial", "D_PAD": "Cruceta"
"SPACE_DRAG_UNLOCKED": "Permitir arrastre del espacio en todos los ejes", },
"SPACE_ROTATE_UNLOCKED": "Permitir rotación espacial en todos los ejes", "ACTIONS": {
"BLOCK_GAME_INPUT": "Bloquear entrada del juego", "RECENTER_PLAYSPACE": "Recentrar espacio de juego"
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignorar watch al bloquear la entrada", },
"CONTROLS": "Controles", "APP_LAUNCHER": {
"FOCUS_FOLLOWS_MOUSE_MODE": "El movimiento del ratón en el disparador", "ASPECT": {
"LEFT_HANDED_MOUSE": "Ratón para zurdos", "SEMI_TALL": "Semicomprimido vertical",
"ALLOW_SLIDING": "Interacción con el stick durante el agarre", "SEMI_WIDE": "Semicomprimido",
"INVERT_SCROLL_DIRECTION_X": "Invertir dirección de desplazamiento horizontal", "SQUARE": "Cuadrado",
"INVERT_SCROLL_DIRECTION_Y": "Invertir la dirección del desplazamiento vertical", "TALL": "Vertical",
"SCROLL_SPEED": "Velocidad de desplazamiento", "WIDE": "Ancho"
"LONG_PRESS_DURATION": "Duración de la pulsación larga",
"POINTER_LERP_FACTOR": "Suavizado del puntero",
"CLICK_FREEZE_TIME_MS": "Tiempo de congelación al hacer clic (ms)",
"MISC": "Miscelánea",
"XWAYLAND_BY_DEFAULT": "Ejecutar aplicaciones en modo de compatibilidad por defecto",
"UPRIGHT_SCREEN_FIX": "Corrección de pantalla vertical",
"DOUBLE_CURSOR_FIX": "Solución de doble cursor",
"SCREEN_RENDER_DOWN": "Renderizar pantalla a menor resolución",
"UPRIGHT_SCREEN_FIX_HELP": "Corrige pantallas en posición vertical en algunos escritorios",
"DOUBLE_CURSOR_FIX_HELP": "Habilita esto si ves 2 cursores",
"CLICK_FREEZE_TIME_MS_HELP": "Ayuda con la precisión de los dobles clics",
"LEFT_HANDED_MOUSE_HELP": "Utilice esto si los botones del ratón están intercambiados",
"BLOCK_GAME_INPUT_HELP": "Bloquea toda la entrada cuando se pasa el cursor sobre un overlay",
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "No bloquear la entrada cuando el cursor está sobre la ventana",
"USE_SKYBOX_HELP": "Mostrar una skybox si no hay una aplicación de escena o passthrough",
"USE_PASSTHROUGH_HELP": "Permitir passthrough si el entorno de ejecución XR lo admite",
"SCREEN_RENDER_DOWN_HELP": "Ayuda a reducir el aliasing en pantallas de alta resolución",
"SETS_ON_WATCH": "Conjuntos en el reloj",
"TROUBLESHOOTING": "Solución de problemas",
"CLEAR_SAVED_STATE": "Borrar estado guardado",
"CLEAR_PIPEWIRE_TOKENS": "Limpiar tokens de PipeWire",
"DELETE_ALL_CONFIGS": "Borrar configuración",
"RESTART_SOFTWARE": "Reiniciar software",
"CLEAR_SAVED_STATE_HELP": "Restablecer sets y posiciones de superposición",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Solicitar la selección de pantalla al iniciar la próxima vez",
"DELETE_ALL_CONFIGS_HELP": "Eliminar todos los archivos de configuración de conf.d",
"RESTART_SOFTWARE_HELP": "Aplicar la configuración que requiere un reinicio",
"CAPTURE_METHOD": "Captura de pantalla de Wayland",
"CAPTURE_METHOD_HELP": "Intente cambiar esta opción si\nexperimenta pantallas negras o con fallos",
"KEYBOARD_MIDDLE_CLICK": "Clic del botón central del teclado",
"KEYBOARD_MIDDLE_CLICK_HELP": "Modificador para usar al escribir\ncon láser púrpura",
"OPTION": {
"AUTO": "Automático",
"AUTO_HELP": "Copiar pantalla usando la GPU si es compatible,\nde lo contrario, GPU de PipeWire.",
"PIPEWIRE_HELP": "Captura de GPU rápida,\nestándar en todos los escritorios.",
"PW_FALLBACK_HELP": "Método lento con alto uso de CPU.\nPruébalo si PipeWire GPU no funciona",
"SCREENCOPY_GPU_HELP": "Rápido, sin ventanas emergentes de uso compartido de pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Lento, sin ventanas emergentes de uso compartido de pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
"NONE": "Ninguno",
"HMD_PINCH": "HMD + pellizco",
"EYE_PINCH": "Ojo + pellizco",
"EYE_ONLY": "Solo ojo",
"HMD_ONLY": "Solo HMD",
"NONE_INPUT_HELP": "No emular ratón y teclado.\nNo podrá interactuar con las pantallas.",
"UINPUT": "Emulación de dispositivo",
"UINPUT_HELP": "Utiliza el módulo uinput para emular un dispositivo.\nSu usuario debe estar en el grupo input.\nSe sabe que funciona bien en la mayoría de los escritorios.",
"WL_VIRTUAL": "Entrada virtual de Wayland",
"WL_VIRTUAL_HELP": "Enviar eventos al compositor de Wayland usando\nzwlr_virtual_pointer y zwp_virtual_keyboard.\nSolo funciona de forma fiable en algunos escritorios.\nNO funciona en KDE, GNOME o COSMIC."
}, },
"AUTOSTART_APPS": "Aplicaciones a ejecutar al inicio", "ASPECT_TITLE": "Relación de aspecto",
"HANDSFREE_POINTER": "Modo manos libres", "AUTOSTART": "Iniciar automáticamente al arrancar",
"HANDSFREE_POINTER_HELP": "Entrada a utilizar cuando no\nestén disponibles los mandos de movimiento.\nPellizco con la izquierda para agarrar, con la derecha para hacer clic.", "LAUNCH": "Lanzar",
"UI_GRADIENT_INTENSITY": "Intensidad del degradado de la IU", "MODE": {
"RESET_PLAYSPACE": "Restablecer espacio de juego", "CAGE": "Modo de compatibilidad (Cage)",
"RESET_PLAYSPACE_HELP": "Borrar el desplazamiento del espacio de juego.", "NATIVE": "Modo nativo"
},
"RES_TITLE": "Resolución"
},
"APP_SETTINGS": {
"ALLOW_SLIDING": "Interacción del stick al agarrar",
"ANIMATION_SPEED": "Velocidad de animación de la interfaz",
"AUTOSTART_APPS": "Aplicaciones al iniciar",
"BLOCK_GAME_INPUT": "Bloquear entrada del juego",
"BLOCK_GAME_INPUT_HELP": "Bloquea toda entrada cuando el cursor está sobre una superposición",
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignorar el reloj al bloquear la entrada",
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "No bloquear la entrada al pasar el cursor sobre el reloj",
"BLOCK_POSES_ON_KBD_INTERACTION": "Bloquear poses al interactuar con el teclado", "BLOCK_POSES_ON_KBD_INTERACTION": "Bloquear poses al interactuar con el teclado",
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Bloquea que el juego reciba poses cuando el teclado está sobre él y 'Bloquear entrada del juego' está habilitado", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Bloquea la recepción de poses del juego cuando el cursor está sobre el teclado y 'Bloquear entrada del juego' está activado",
"LANGUAGE": "Idioma",
"REQUIRES_RESTART": "Requiere reinicio",
"GRID_OPACITY": "Opacidad de la cuadrícula del suelo",
"GRID_OPACITY_HELP": "Opacidad de la cuadrícula del suelo cuando el skybox está habilitado",
"BROWSE_ONLINE_CATALOG": "Explorar catálogo en línea...",
"BROWSE_SKYMAPS": "Explorar skymaps",
"COLOR_KEYING": "Clave de color",
"NO_SKYMAPS_FOUND": "No se encontraron skymaps",
"SELECT_VARIANT": "Seleccionar variante",
"SHOW_WELCOME_SCREEN": "Mostrar pantalla de bienvenida",
"SKYBOX": "Skybox",
"SKYMAP_ALREADY_DOWNLOADED": "Esta skymap ya ha sido descargada. Selecciona la acción deseada.",
"WATCH_VIEW_ANGLE": "Ángulos de visión del Watch",
"WATCH_VIEW_ANGLE_HELP": "Controla cómo se desvanece el Watch",
"BINDINGS": { "BINDINGS": {
"COMP": { "COMP": {
"CLICK": "Click", "CLICK": "Clic",
"FORCE": "Fuerza", "FORCE": "Fuerza",
"TOUCH": "Tocar", "TOUCH": "Toque",
"VALUE": "Valor", "VALUE": "Valor",
"PROXIMITY": "Proximidad", "PROXIMITY": "Proximidad",
"X_AXIS": "Eje X", "X_AXIS": "Eje X",
@ -116,203 +58,292 @@
}, },
"TYPE": { "TYPE": {
"BUMPER": "Bumper", "BUMPER": "Bumper",
"DPAD_UP": "D-pad arriba", "DPAD_UP": "Cruceta Arriba",
"DPAD_DOWN": "D-pad hacia abajo", "DPAD_DOWN": "Cruceta Abajo",
"DPAD_LEFT": "D-pad izquierda", "DPAD_LEFT": "Cruceta Izquierda",
"DPAD_RIGHT": "D-pad derecha", "DPAD_RIGHT": "Cruceta Derecha",
"JOYSTICK": "Joystick", "JOYSTICK": "Joystick",
"MENU": "Menú", "MENU": "Menú",
"SHOULDER": "Hombro", "SHOULDER": "Hombro",
"SQUEEZE": "Agarre", "SQUEEZE": "Agarre",
"SYSTEM": "Sistema", "SYSTEM": "Sistema",
"THUMBREST": "Thumbrest", "THUMBREST": "Apoyo del pulgar",
"THUMBSTICK": "Stick analógico", "THUMBSTICK": "Palanca",
"TRACKPAD": "Trackpad", "TRACKPAD": "Trackpad",
"TRIGGER": "Gatillo", "TRIGGER": "Gatillo",
"VIEW": "Ver" "VIEW": "Vista"
}, },
"CLICK": { "CLICK": {
"ANY": "Cualquiera", "ANY": "Cualquiera",
"DOUBLE": "Doble toque", "DOUBLE": "Doble toque",
"TRIPLE": "Triple toque", "TRIPLE": "Triple toque",
"TYPE": "Número de toques" "TYPE": "Cantidad de toques"
}, },
"ACTION": { "ACTION": {
"CLICK": "Clic*", "CLICK": "Clic*",
"GRAB": "Agarrar*", "GRAB": "Agarre*",
"ALT_CLICK": "Ejecución de shell personalizada (establecer alt_click en la configuración)", "ALT_CLICK": "Ejecutable de shell personalizado (configura alt_click en el archivo de config)",
"SHOW_HIDE": "Mostrar, ocultar, recentrar*", "SHOW_HIDE": "Mostrar, ocultar, recentrar*",
"TOGGLE_DASHBOARD": "Alternar dashboard", "TOGGLE_DASHBOARD": "Alternar tablero",
"SPACE_DRAG": "Arrastre del playspace", "SPACE_DRAG": "Arrastre del espacio de juego",
"SPACE_ROTATE": "Rotar playspace", "SPACE_ROTATE": "Rotar espacio de juego",
"SPACE_RESET": "Reinicio del Playspace", "SPACE_RESET": "Restablecer espacio de juego",
"CLICK_MODIFIER_RIGHT": "Modificador de clic derecho", "CLICK_MODIFIER_RIGHT": "Modificador de clic derecho",
"CLICK_MODIFIER_MIDDLE": "Modificador de clic central", "CLICK_MODIFIER_MIDDLE": "Modificador de clic central",
"MOVE_MOUSE": "Mover ratón (si está desactivado por defecto)", "MOVE_MOUSE": "Mover ratón (desactivado por defecto)",
"SCROLL": "Desplazamiento*" "SCROLL": "Desplazar*"
}, },
"LEFT": "Izquierda", "LEFT": "Izquierda",
"RIGHT": "Derecha", "RIGHT": "Derecha",
"COMPONENT": "Tipo de actuación", "COMPONENT": "Tipo de accionamiento",
"SUBPATH": "Control de actuación", "SUBPATH": "Control a accionar",
"THRESHOLD": "Activar cuando supere el valor superior\nDesactivar cuando sea inferior al valor inferior" "THRESHOLD": "Activar al superar el valor superior\nDesactivar al caer bajo el valor inferior"
}, },
"ENABLED": "Activado", "BROWSE_ONLINE_CATALOG": "Explorar catálogo en línea...",
"INPUT_EMULATION_METHOD": "Método de emulación de entrada", "BROWSE_SKYMAPS": "Explorar skymaps",
"INPUT_EMULATION_METHOD_HELP": "Prueba a cambiar esto en caso de que la entrada del\nratón o el teclado no se registre.", "CAPTURE_METHOD": "Método de captura de pantalla",
"INPUT_PROFILES": "Cambiar la configuración de entrada", "CAPTURE_METHOD_HELP": "Prueba a cambiar esto si tienes\npantallas negras o con errores",
"INPUT_PROFILES_HELP": "Vinculaciones de entrada del controlador OpenXR", "COLOR_KEYING": "Clave de color",
"NOT_SUPPORTED": "No compatible",
"ENABLE_WATCH": "Activar watch",
"SPACE_DRAG": "Space drag",
"SPACE_GRAVITY_DAMPING": "Amortiguación",
"SPACE_GRAVITY_DAMPING_HELP": "Resistencia artificial para ralentizar el movimiento. 0.1 - alta resistencia, 1.0 - sin resistencia",
"SPACE_GRAVITY_FLING_STRENGTH": "Fuerza de lanzamiento",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Multiplicador de intensidad de la fuerza de lanzamiento gravitacional tras el space-drag.\n0.0 - sin movimiento alguno, 2.0 - doble intensidad",
"SPACE_GRAVITY_GRAVITY": "Gravedad",
"SPACE_GRAVITY_GRAVITY_HELP": "Cantidad de fuerza hacia abajo. 0.0 - sin gravedad",
"SPACE_GRAVITY_GROUND_FRICTION": "Fricción del suelo",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Cantidad de fricción que te ralentiza si estás tocando el suelo.\n0.0 - sin fricción (como si fuera hielo), 1.0 - superficie rugosa",
"SPACE_GRAVITY_FLOOR_HEIGHT": "Altura del suelo",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "La posición Y donde se encuentra el suelo. La gravedad se detiene cuando alcanzas esta altura.",
"SAVE": "Guardar",
"CANCEL": "Cancelar",
"WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "El modelo seleccionado debe ser descargado.\n¿Deseas descargarlo ahora?",
"REMOVE_UNUSED_MODELS": "Estás desactivando la función de voz a texto.\n¿Te gustaría eliminar los modelos de Whisper descargados para liberar espacio?"
},
"WHISPER_MODEL": "Modelo de voz a texto",
"WHISPER_MODEL_HELP": "Modelo de Whisper a utilizar.\nLos modelos más grandes producen\nresultados más precisos, pero consumen más VRAM.",
"DEFAULT_OVERLAY_SCALE": "Tamaño de la superposición predeterminado",
"DEFAULT_OVERLAY_SCALE_HELP": "Genera nuevas capas de superposición con esta escala.",
"COLOR_PALETTE": "Paleta de colores", "COLOR_PALETTE": "Paleta de colores",
"COLOR_PALETTE_HELP": "Haz clic para explorar paletas de colores.\n¡Para crear las tuyas, visita la web!",
"COLOR_PALETTES": "Paletas de colores", "COLOR_PALETTES": "Paletas de colores",
"COLOR_PALETTE_CURRENT": "Tema actualmente activo.", "COLOR_PALETTE_CURRENT": "Tema actualmente activo.",
"COLOR_PALETTE_ACTIVATE": "Haz clic para usar este tema.",
"APPLY_CHANGES_RESTART": "¿Reiniciar WayVR para aplicar los cambios?",
"COLOR_PALETTE_HELP": "Haz clic para explorar paletas de colores.\nPara crear paletas personalizadas, ¡visita el sitio web!",
"COLOR_PALETTE_CUSTOM_URL": "¡Añade tu propio tema personalizado!", "COLOR_PALETTE_CUSTOM_URL": "¡Añade tu propio tema personalizado!",
"COLOR_PALETTE_CUSTOM_URL2": "Haz clic para abrir el manual web.", "COLOR_PALETTE_CUSTOM_URL2": "Haz clic para abrir el manual web.",
"SNAP_ANGLE_DEG": "Ángulo de ajuste de cabeceo y alabeo de la ventana", "COLOR_PALETTE_ACTIVATE": "Haz clic para usar este tema.",
"SNAP_ANGLE_DEG_HELP": "Las ventanas agarradas se ajustan a este ángulo en los ejes de cabeceo y balanceo." "CLEAR_PIPEWIRE_TOKENS": "Limpiar tokens de PipeWire",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Preguntar por la selección de pantalla al siguiente inicio",
"CLEAR_SAVED_STATE": "Borrar estado guardado",
"CLEAR_SAVED_STATE_HELP": "Restablecer sets y posiciones de los overlays",
"CLICK_FREEZE_TIME_MS": "Tiempo de congelación del clic (ms)",
"CLICK_FREEZE_TIME_MS_HELP": "Ayuda con la precisión del doble clic",
"CLOCK_12H": "Reloj de 12 horas",
"CONTROLS": "Controles",
"DELETE_ALL_CONFIGS": "Borrar configuración",
"DELETE_ALL_CONFIGS_HELP": "Elimina todos los archivos de configuración de conf.d",
"DOUBLE_CURSOR_FIX": "Corrección de doble cursor",
"DOUBLE_CURSOR_FIX_HELP": "Activa esto si ves 2 cursores",
"DEFAULT_OVERLAY_SCALE": "Tamaño predeterminado de la superposición",
"DEFAULT_OVERLAY_SCALE_HELP": "Aparecer nuevos overlays a esta escala.",
"DEFAULT_CURVATURE": "Curvatura predeterminada del overlay",
"DEFAULT_OPACITY": "Opacidad predeterminada del overlay",
"DEFAULT_POSITIONING": "Posicionamiento predeterminado del overlay",
"OVERLAY_DEFAULTS_HELP": "Solo se aplica a los overlays nuevos",
"ENABLED": "Activado",
"FEATURES": "Funciones",
"FOCUS_FOLLOWS_MOUSE_MODE": "Mover ratón al tocar el gatillo",
"HANDSFREE_POINTER": "Modo manos libres",
"HANDSFREE_POINTER_HELP": "Entrada a usar cuando no haya controladores de movimiento.\nPinza izquierda para agarrar, derecha para hacer clic.",
"HANDSFREE_ALT_TAB": "Apuntado del selector de apps",
"HANDSFREE_ALT_TAB_HELP": "Mantén presionado Super+X, apunta a la ventana deseada y suelta para cambiar el foco.",
"HIDE_GRAB_HELP": "Ocultar ayuda de agarre",
"HIDE_USERNAME": "Ocultar nombre de usuario",
"INPUT_EMULATION_METHOD": "Método de emulación de entrada",
"INPUT_EMULATION_METHOD_HELP": "Prueba a cambiar esto si el ratón o\nel teclado no responden.",
"INPUT_CAPTURE_METHOD": "Método de captura de entrada",
"INPUT_CAPTURE_METHOD_HELP": "Permite usar periféricos físicos dentro de WayVR.\n Super+Z: Alternar entrada entre WayVR y el escritorio real\n Super+X: Alternar entre aplicaciones de WayVR",
"INPUT_PROFILES": "Cambiar asignación de controles",
"INPUT_PROFILES_HELP": "Asignaciones de entrada del controlador OpenXR",
"INVERT_SCROLL_DIRECTION_X": "Invertir dirección del desplazamiento horizontal",
"INVERT_SCROLL_DIRECTION_Y": "Invertir dirección del desplazamiento vertical",
"KEYBOARD_MIDDLE_CLICK": "Clic central del teclado",
"KEYBOARD_MIDDLE_CLICK_HELP": "Modificador al escribir\ncon el láser púrpura",
"KEYBOARD_SOUND_ENABLED": "Sonidos del teclado",
"LANGUAGE": "Idioma",
"LEFT_HANDED_MOUSE": "Mouse para zurdos",
"LEFT_HANDED_MOUSE_HELP": "Úsalo si los botones del ratón están invertidos",
"LONG_PRESS_DURATION": "Duración de pulsación larga",
"LOOK_AND_FEEL": "Apariencia",
"MISC": "Diversos",
"NOTIFICATIONS_ENABLED": "Habilitar notificaciones",
"NOTIFICATIONS_SOUND_ENABLED": "Sonidos de notificación",
"NOT_SUPPORTED": "No soportado",
"NO_SKYMAPS_FOUND": "No se encontraron skymaps",
"OPAQUE_BACKGROUND": "Fondo opaco",
"OPTION": {
"ANCHORED_HELP": "Se mueve con el marcador central. Recomendado.",
"FLOATING_HELP": "Se mueve independientemente y se recentra.\nFácil de perder; no recomendado.",
"STATIC_HELP": "Se mantiene fijo respecto al mundo.",
"AUTO": "Automático",
"AUTO_HELP": "ScreenCopy GPU si es compatible,\nsi no, PipeWire GPU.",
"EYE_ONLY": "Láser ocular",
"EYE_PINCH": "Ojo + pinza",
"HMD_ONLY": "Láser del HMD",
"HMD_PINCH": "HMD + pellizco",
"NONE": "Ninguno",
"NONE_INPUT_HELP": "No emular ratón ni teclado.\nNo podrás interactuar con las pantallas.",
"NONE_INPUT_CAPTURE_HELP": "No capturar teclado ni ratón.\nNo podrás usar el ratón o teclado físico en las \naplicaciones lanzadas dentro de WayVR.",
"PIPEWIRE_HELP": "Captura de GPU rápida,\nestándar en todos los escritorios.",
"PW_FALLBACK_HELP": "Método lento con alto uso de CPU.\nPruébalo si PipeWire GPU no funciona",
"SCREENCOPY_GPU_HELP": "Rápido, sin ventanas emergentes al compartir pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Lento, sin ventanas emergentes al compartir pantalla.\nFunciona en: Hyprland, Niri, River, Sway",
"UINPUT": "Emulación de dispositivo",
"UINPUT_HELP": "Usa el módulo uinput para emular un dispositivo.\nFunciona bien en la mayoría de los escritorios.",
"EVDEV_HELP": "Captura los dispositivos de entrada para uso exclusivo.\nTu usuario debe pertenecer al grupo \"input\".",
"WL_VIRTUAL": "Entrada virtual de Wayland",
"WL_VIRTUAL_HELP": "Envía eventos al compositor Wayland usando\nzwlr_virtual_pointer y zwp_virtual_keyboard.\nSolo funciona de forma fiable en algunos escritorios.\nNO funciona en KDE, GNOME o COSMIC."
},
"POINTER_ACCELERATION": "Aceleración del ratón",
"POINTER_ACCELERATION_HELP": "Act.: Aceleración adaptativa del ratón\nDesact.: Velocidad constante",
"POINTER_LERP_FACTOR": "Suavizado del puntero",
"POINTER_SPEED": "Velocidad del ratón",
"REQUIRES_RESTART": "Requiere reiniciar",
"RESET_PLAYSPACE": "Restablecer espacio de juego",
"RESET_PLAYSPACE_HELP": "Elimina el desplazamiento del espacio de juego.",
"SAVE_PLAYSPACE_CENTER": "Guardar centro del espacio de juego",
"SAVE_PLAYSPACE_CENTER_HELP": "Usa el espacio de juego actual para el comando de reiniciar espacio de juego.",
"RESET_PLAYSPACE_CENTER": "Reiniciar centro del espacio de juego",
"RESET_PLAYSPACE_CENTER_HELP": "Restablece el centro del espacio de juego definido previamente.",
"RESTART_SOFTWARE": "Reiniciar software",
"RESTART_SOFTWARE_HELP": "Aplicar ajustes que requieren reiniciar",
"ROUND_MULTIPLIER": "Redondeo de bordes de la UI",
"SCREEN_RENDER_DOWN": "Renderizar pantalla a resolución menor",
"SCREEN_RENDER_DOWN_HELP": "Ayuda con el aliasing en pantallas de alta resolución",
"SCROLL_SPEED": "Velocidad de desplazamiento",
"SELECT_VARIANT": "Seleccionar variante",
"SNAP_ANGLE_DEG": "Ángulo de ajuste de inclinación y rotación de ventana",
"SNAP_ANGLE_DEG_HELP": "Las ventanas agarradas se ajustan a este ángulo en los ejes de cabeceo y balanceo.",
"ENABLE_WATCH": "Habilitar reloj",
"SETS_ON_WATCH": "Sets en el reloj",
"SHOW_WELCOME_SCREEN": "Mostrar pantalla de bienvenida",
"SKYBOX": "Skymap",
"SKYMAP_ALREADY_DOWNLOADED": "Este skymap ya está descargado. Selecciona la acción deseada.",
"SPACE_DRAG": "Espacio de juego",
"SPACE_DRAG_MULTIPLIER": "Multiplicador de Space-drag",
"SPACE_DRAG_AFFECTS_WORLD": "Dejar overlays atrás al mover el espacio de juego",
"SPACE_DRAG_UNLOCKED": "Permitir espacio-drag en todos los ejes",
"SPACE_GRAVITY_DAMPING": "Amortiguación",
"SPACE_GRAVITY_DAMPING_HELP": "Resistencia artificial para frenar el movimiento. 0.1 - mucha resistencia, 1.0 - sin resistencia",
"SPACE_GRAVITY_FLING_STRENGTH": "Fuerza de impulso",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Multiplicador de la intensidad de la fuerza de lanzamiento gravitacional tras el space-drag.\n0.0 - sin movimiento, 2.0 - intensidad doble",
"SPACE_GRAVITY_GRAVITY": "Gravedad",
"SPACE_GRAVITY_GRAVITY_HELP": "Cantidad de fuerza hacia abajo. 0.0 = sin gravedad",
"SPACE_GRAVITY_GROUND_FRICTION": "Fricción del suelo",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Cantidad de fricción que te frena al tocar el suelo.\n0.0 - sin fricción (como sobre hielo), 1.0 - superficie rugosa",
"SPACE_GRAVITY_FLOOR_HEIGHT": "Altura del suelo",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "La posición Y donde se encuentra el suelo. La gravedad se detiene al alcanzar esta altura.",
"SPACE_ROTATE_UNLOCKED": "Permitir rotación del espacio en todos los ejes",
"TROUBLESHOOTING": "Solución de problemas",
"UI_GRADIENT_INTENSITY": "Intensidad del degradado de la interfaz",
"UPRIGHT_SCREEN_FIX": "Corrección de pantalla vertical",
"UPRIGHT_SCREEN_FIX_HELP": "Corrige pantallas verticales en algunos escritorios",
"USE_PASSTHROUGH": "Activar passthrough",
"USE_PASSTHROUGH_HELP": "Permite el passthrough si el entorno XR lo soporta",
"USE_SKYBOX": "Mostrar skymap",
"USE_SKYBOX_HELP": "Mostrar un skymap si no hay una aplicación de escena o passthrough",
"WATCH_VIEW_ANGLE": "Ángulos de visión del reloj",
"WATCH_VIEW_ANGLE_HELP": "Controla cómo se desvanece el reloj",
"WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "El modelo seleccionado necesita descargarse.\n¿Descargarlo ahora?",
"REMOVE_UNUSED_MODELS": "Estás desactivando la función de voz a texto.\n¿Quieres eliminar los modelos de Whisper descargados para liberar espacio?"
},
"WHISPER_MODEL": "Modelo de dictado",
"WHISPER_MODEL_HELP": "Modelo de Whisper a utilizar.\nLos modelos más grandes dan resultados\nmás precisos, pero consumen más VRAM.",
"GRID_OPACITY": "Opacidad de la rejilla del suelo",
"GRID_OPACITY_HELP": "Opacidad de la rejilla del suelo cuando el skymap está activado",
"XWAYLAND_BY_DEFAULT": "Ejecutar apps en modo de compatibilidad por defecto",
"SAVE": "Guardar",
"CANCEL": "Cancelar"
}, },
"HELLO": "¡Hola!", "APPLICATION_LAUNCHER": "Lanzador de aplicaciones",
"AUDIO": {
"VOLUME": "Volumen",
"SETTINGS": "Configuración de audio",
"AUTO_SWITCH_TO_VR_AUDIO": "Conmutar automáticamente al audio VR",
"SPEAKERS": "Altavoces",
"MICROPHONES": "Micrófonos",
"CARDS": "Tarjetas",
"SELECT_AUDIO_CARD_PROFILE": "Seleccionar perfil de tarjeta de audio",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "No se encontraron altavoces VR. Actívelos manualmente.",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "No se encontró micrófono VR. Actívelo manualmente.",
"FAILED_TO_SWITCH_MICROPHONE": "No se pudo cambiar el micrófono",
"MICROPHONE_SET_SUCCESSFULLY": "Micrófono configurado correctamente",
"SPEAKERS_SET_SUCCESSFULLY": "Altavoces configurados correctamente"
},
"ACTIONS": {
"RECENTER_PLAYSPACE": "Re-centrar espacio de juego"
},
"POPUP_ADD_DISPLAY": {
"RESOLUTION": "Resolución"
},
"WIDTH": "Ancho",
"HEIGHT": "Altura",
"HIDE": "Ocultar",
"REMOVE": "Eliminar",
"SHOW": "Mostrar",
"FAILED_TO_LAUNCH_APPLICATION": "No se pudo iniciar la aplicación:",
"APPLICATION_STARTED": "Aplicación iniciada", "APPLICATION_STARTED": "Aplicación iniciada",
"APPLICATIONS": "Aplicaciones",
"AUDIO": {
"AUTO_SWITCH_TO_VR_AUDIO": "Cambiar automáticamente al audio de VR",
"CARDS": "Tarjetas",
"FAILED_TO_SWITCH_MICROPHONE": "Error al cambiar el micrófono",
"MICROPHONE_SET_SUCCESSFULLY": "Micrófono configurado correctamente",
"MICROPHONES": "Micrófonos",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "No se encontró micrófono de VR. Cámbialo manualmente.",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "No se encontraron altavoces de VR. Cámbialos manualmente.",
"SELECT_AUDIO_CARD_PROFILE": "Selecciona el perfil de la tarjeta de sonido",
"SETTINGS": "Ajustes de audio",
"SPEAKERS": "Altavoces",
"SPEAKERS_SET_SUCCESSFULLY": "Altavoces configurados correctamente",
"VOLUME": "Volumen"
},
"CLOSE_WINDOW": "Cerrar ventana", "CLOSE_WINDOW": "Cerrar ventana",
"GAME_LIST": {
"NO_GAMES_FOUND": "No se encontraron juegos",
"RUNNING_GAMES_LIST": "Lista de juegos en ejecución"
},
"TERMINATE_PROCESS": "Finalizar proceso",
"GAME_LAUNCHED": "Juego lanzado",
"APP_LAUNCHER": {
"MODE": {
"NATIVE": "Modo nativo",
"CAGE": "Modo de compatibilidad (Cage)"
},
"RES_TITLE": "Resolución",
"ASPECT_TITLE": "Aspecto",
"ASPECT": {
"WIDE": "Ancho",
"SEMI_WIDE": "Semi-ancho",
"SQUARE": "Cuadrado",
"SEMI_TALL": "Semi alto",
"TALL": "Alto"
},
"POS_TITLE": "Posicionamiento",
"POS": {
"FLOATING": "Flotante",
"ANCHORED": "Anclado",
"STATIC": "Estático",
"FLOATING_HELP": "Se mueve independientemente, se recentra al mostrarse.",
"ANCHORED_HELP": "Se mantiene en su lugar con respecto al marcador central.",
"STATIC_HELP": "No pertenece a ningún conjunto. No se recentra."
},
"AUTOSTART": "Ejecutar automáticamente al inicio",
"LAUNCH": "Iniciar"
},
"DISPLAY_BRIGHTNESS": "Brillo de la pantalla",
"PROCESS_LIST": "Lista de procesos",
"REFRESH": "Actualizar",
"PROCESS": {
"STOP": "Detener",
"FORCE_KILL": "Forzar cierre"
},
"DEBUG_INFO": "Información de depuración",
"CREATION_DATE": "Fecha de creación", "CREATION_DATE": "Fecha de creación",
"DOWNLOADER": "Descargador", "DEBUG_INFO": "Info de depuración",
"DOWNLOAD_AGAIN": "Descargar de nuevo", "DISPLAY_BRIGHTNESS": "Brillo de pantalla",
"DOWNLOADING_FILE": "Descargando archivo...",
"GETTING_STARTED": "Primeros pasos",
"MODIFICATION_DATE": "Fecha de modificación",
"LOADING": "Cargando...",
"APPLY": "Aplicar",
"RELOAD_FROM_DISK": "Recargar desde el disco",
"TARGET_PATH": "Ruta de destino",
"VERSION": "Versión",
"DONATE": { "DONATE": {
"SUPPORT_US": "Apóyanos", "SUPPORT_US": "Apóyanos",
"DESCRIPTION": "Somos un pequeño equipo de 2 desarrolladores que creamos WayVR en nuestro tiempo libre. Si disfrutas usando este software, por favor considera apoyarnos; cada donación nos ayuda a seguir adelante.", "DESCRIPTION": "Somos un pequeño equipo de 2 desarrolladores creando WayVR en nuestro tiempo libre. Si disfrutas usando este software, considera apoyarnos; cada donación nos ayuda a seguir adelante.",
"BUTTON_TOOLTIP": "Donar vía Open Collective", "THANK_YOU_WAYVR": "¡Gracias del equipo de WayVR!",
"BUTTON_TOOLTIP": "Dona a través de Open Collective",
"CURRENT_SUPPORTERS": "Colaboradores actuales", "CURRENT_SUPPORTERS": "Colaboradores actuales",
"THANK_YOU_WAYVR": "¡Gracias de parte del equipo de WayVR!" "BROUGHT_TO_YOU_VARIANTS_OFTEN": "Apoyado por {USER}|Gracias a {USER}|Con el apoyo de {USER}|Patrocinado por {USER}|Un aporte especial de {USER}|Impulsado por {USER}|Haciendo esto posible: {USER}|Sostenible gracias a {USER}|Un agradecimiento a {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Un gran impulso de {USER}|Todo es gracias a {USER}|Con todo el cariño de {USER}|El motor de hoy: {USER}|Sumando valor con {USER}|Haciendo crecer el proyecto: {USER}|De corazón, gracias a {USER}|Con el respaldo de {USER}|La chispa del día: {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "¡Un nivel leyenda: {USER}!|Energía pura gracias a {USER}|Nuestra estrella del día: {USER}|El MVP de hoy: {USER}|Rescatando el día: {USER}|Sosteniendo la aplicación: {USER}|El combustible secreto: {USER}|Manteniendo la cordura: {USER}|Conversor de café en código: {USER}|Salvando la producción: {USER}|¡Simplemente increíble: {USER}!|El corazón de todo: {USER}"
}, },
"DOWNLOAD": "Descargar",
"DOWNLOADER": "Descargador",
"WELCOME": { "WELCOME": {
"ALL_SET": "¡Todo listo!", "ALL_SET": "¡Todo listo!",
"BASICS": "Estos conceptos básicos te permitirán empezar a usar WayVR con facilidad.", "BASICS": "Estos conceptos básicos te permitirán empezar a usar WayVR con facilidad.",
"FEATURES_DOCUMENTATION": "Hay muchas otras funciones que merece la pena personalizar. Para más información, consulta la documentación en", "CENTER_MARKER": "El marcador de centro es lo que aparecerá frente a ti al recentrar. ¡Coloca los overlays alrededor de él!",
"DOUBLE_PRESS_TO_TOGGLE": "Pulsa dos veces B (en Index) o Y (en Meta) para mostrar, recentrar u ocultar tu Set. Pruébalo ahora.",
"FEATURES_DOCUMENTATION": "Hay muchas otras funciones que vale la pena personalizar. Para más información, consulta la documentación en",
"FINISH_TUTORIAL": "Finalizar tutorial", "FINISH_TUTORIAL": "Finalizar tutorial",
"GRAB_BOTH_HANDS": "Agarra el elemento con ambas manos si quieres mover un overlay específico en tu set.", "GRAB_BOTH_HANDS": "Agarralo con ambas manos si quieres mover un overlay específico de tu set.",
"GRAB_ONE_HAND": "Agárralo con una mano para mover tu set.", "GRAB_ONE_HAND": "Agarralo con una mano para mover tu set.",
"GREETING": "¡Hola!", "GREETING": "¡Hola!",
"GUIDE_INTRO": "Permítenos guiarte en tus primeros pasos.", "GUIDE_INTRO": "Déjanos guiarte en tus primeros pasos.",
"LASER_COLORS": "Colores del láser", "LASER_COLORS": "Colores del láser",
"LASER_FUNCTIONALITY": "Gran parte de la funcionalidad de WayVR depende del color de láser que se utilice para interactuar con un elemento de la interfaz. ¡No hace falta pulsar estos botones, solo tocarlos!", "LASER_FUNCTIONALITY": "Gran parte de la funcionalidad de WayVR depende del color del láser usado para interactuar con un elemento de la interfaz. ¡No hace falta pulsar los botones, basta con tocarlos!",
"LAST_PAGE_INFO": "Este tutorial dejará de aparecer una vez que llegues a la última página.", "LAST_PAGE_INFO": "Este tutorial dejará de aparecer una vez que llegues a la última página.",
"LOOK_AT_LEFT_WRIST": "Mira tu muñeca izquierda. Ese es tu watch.", "LOOK_AT_LEFT_WRIST": "Mira tu muñeca izquierda. Ahí tienes tu reloj.",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— Modo de clic central: Láser morado", "MIDDLE_CLICK_MODE_PURPLE_LASER": "Modo clic central: Láser púrpura",
"MOVING_YOUR_SET": "Moviendo tu set", "MOVING_YOUR_SET": "Mover tu set",
"NEXT_BUTTON": "Pulsa el botón \"Siguiente\" de abajo para comenzar.", "NEXT_BUTTON": "Pulsa el botón Siguiente abajo para empezar.",
"REGULAR_MODE_BLUE_LASER": "— Modo Regular: Láser azul", "REGULAR_MODE_BLUE_LASER": "Modo normal: Láser azul",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Reposiciona esta ventana usando la acción de agarre de tu controlador.", "REPOSITION_THIS_WINDOW_BY_GRABBING": "Reposiciona esta ventana usando el agarre (grip) de tu controlador.",
"RIGHT_CLICK_MODE_ORANGE_LASER": "— Modo de clic derecho: Láser naranja", "RIGHT_CLICK_MODE_ORANGE_LASER": "Modo clic derecho: Láser naranja",
"THANKS_FOR_INSTALLING": "¡Gracias por instalar WayVR!", "THANKS_FOR_INSTALLING": "¡Gracias por instalar WayVR!",
"WATCH": "Watch", "WATCH": "Reloj",
"WORKING_SET": "Set de trabajo", "WORKING_SET": "Set actual"
"DOUBLE_PRESS_TO_TOGGLE": "Presiona dos veces B (en Index) o Y (en Meta) para mostrar, recentrar u ocultar tu set. Pruébalo ahora.",
"CENTER_MARKER": "El marcador de centrado es lo que aparecerá frente a ti al recentrar. ¡Coloca las capas alrededor de él!"
}, },
"DOWNLOAD": "Descargar", "DOWNLOAD_AGAIN": "Descargar de nuevo",
"SAVED_TO_FAVOURITES": "Guardado en favoritos", "DOWNLOADING_FILE": "Descargando archivo...",
"ADD_TO_FAVOURITES": "Añadir a favoritos", "FAILED_TO_LAUNCH_APPLICATION": "Error al lanzar la aplicación:",
"ADD_TO_FAVOURITES_HINT": "Guarda el ajuste preestablecido y ánclalo al cajón de aplicaciones", "GAME_LAUNCHED": "Juego iniciado",
"REMOVE_FROM_FAVOURITES": "Eliminar de favoritos", "GAME_LIST": {
"EMPTY": "Vacío", "NO_GAMES_FOUND": "No se encontraron juegos",
"PINNED_APPS": "Aplicaciones ancladas" "RUNNING_GAMES_LIST": "Lista de juegos activos"
},
"GAMES": "Juegos",
"GENERAL_SETTINGS": "Ajustes generales",
"GETTING_STARTED": "Primeros pasos",
"HEIGHT": "Altura",
"HELLO": "¡Hola!",
"HELLO_USER": "¡Hola, {USER}!",
"HIDE": "Ocultar",
"HOME_SCREEN": "Inicio",
"MODIFICATION_DATE": "Fecha de modificación",
"MONADO_RUNTIME": "Runtime de Monado",
"LOADING": "Cargando...",
"POPUP_ADD_DISPLAY": {
"RESOLUTION": "Resolución"
},
"PROCESS": {
"FORCE_KILL": "Forzar cierre",
"STOP": "Detener"
},
"PROCESS_LIST": "Lista de procesos",
"REFRESH": "Actualizar",
"REMOVE": "Eliminar",
"APPLY": "Aplicar",
"RELOAD_FROM_DISK": "Recargar desde disco",
"SETTINGS": "Ajustes",
"SHOW": "Mostrar",
"TARGET_PATH": "Ruta de destino",
"TERMINATE_PROCESS": "Terminar proceso",
"VERSION": "Versión",
"WIDTH": "Ancho",
"PINNED_APPS": "Aplicaciones fijadas",
"SAVED_TO_FAVOURITES": "Guardado en aplicaciones fijadas",
"ADD_TO_FAVOURITES": "Añadir a aplicaciones fijadas",
"ADD_TO_FAVOURITES_HINT": "Guardar ajuste y fijarlo al cajón de aplicaciones",
"REMOVE_FROM_FAVOURITES": "Quitar de aplicaciones fijadas",
"EMPTY": "Vacío"
} }

View File

@ -1,130 +1,51 @@
{ {
"DEFINITIONS": {
"ANCHORED": "Ancorato",
"FLOATING": "Fluttuante",
"STATIC": "Statico",
"SET": "Set",
"WATCH": "Orologio",
"DASHBOARD": "Dashboard",
"EDIT_MODE": "Modalità modifica",
"SETTINGS": "Impostazioni",
"KEYBOARD": "Tastiera",
"TASKBAR": "Barra delle applicazioni",
"FEATURES": "Funzionalità",
"OVERLAY": "Overlay",
"SKYMAP": "Skymap",
"PLAYSPACE": "Playspace",
"D_PAD": "D-pad"
},
"ACTIONS": { "ACTIONS": {
"RECENTER_PLAYSPACE": "Recentra lo spazio di gioco" "RECENTER_PLAYSPACE": "Ricentra playspace"
}, },
"APP_LAUNCHER": { "APP_LAUNCHER": {
"ASPECT": { "ASPECT": {
"SEMI_TALL": "Semi-alto", "SEMI_TALL": "Semi-verticale",
"SEMI_WIDE": "Semi-ampio", "SEMI_WIDE": "Semi-ampio",
"SQUARE": "Quadrato", "SQUARE": "Quadrato",
"TALL": "Alto", "TALL": "Verticale",
"WIDE": "Ampio" "WIDE": "Widescreen"
}, },
"ASPECT_TITLE": "Proporzioni", "ASPECT_TITLE": "Formato",
"AUTOSTART": "Avvia automaticamente all'avvio", "AUTOSTART": "Avvia automaticamente all'avvio",
"LAUNCH": "Avvia", "LAUNCH": "Avvia",
"MODE": { "MODE": {
"CAGE": "Modalità compatibilità (Cage)", "CAGE": "Modalità compatibilità (Cage)",
"NATIVE": "Modalità nativa" "NATIVE": "Modalità nativa"
}, },
"POS": {
"ANCHORED": "Ancorato",
"ANCHORED_HELP": "Rimane fermo rispetto al marcatore centrale.",
"FLOATING": "Fluttuante",
"FLOATING_HELP": "Si muove in modo indipendente, si recentra quando viene mostrato.",
"STATIC": "Statico",
"STATIC_HELP": "Non fa parte di alcun set. Non recentra."
},
"POS_TITLE": "Posizionamento",
"RES_TITLE": "Risoluzione" "RES_TITLE": "Risoluzione"
}, },
"APP_SETTINGS": { "APP_SETTINGS": {
"ALLOW_SLIDING": "Interazione tramite stick durante l'afferrare", "ALLOW_SLIDING": "Interazione stick durante il grab",
"ANIMATION_SPEED": "Velocità dell'animazione dell'interfaccia utente", "ANIMATION_SPEED": "Velocità animazioni UI",
"BLOCK_GAME_INPUT": "Blocca l'input di gioco", "AUTOSTART_APPS": "App all'avvio",
"BLOCK_GAME_INPUT_HELP": "Blocca tutti gli input quando il cursore è sopra un overlay", "BLOCK_GAME_INPUT": "Blocca input di gioco",
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignora il Watch quando si blocca l'input", "BLOCK_GAME_INPUT_HELP": "Blocca ogni input quando un overlay è selezionato",
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Non bloccare l'input quando il watch è evidenziato", "BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignora l'orologio durante il blocco dell'input",
"CAPTURE_METHOD": "Acquisizione dello schermo Wayland", "BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Non bloccare l'input quando il cursore è sull'orologio",
"CAPTURE_METHOD_HELP": "Prova a modificare questa impostazione se riscontri schermate nere o con artefatti.", "BLOCK_POSES_ON_KBD_INTERACTION": "Blocca pose durante l'interazione con la tastiera",
"CLEAR_PIPEWIRE_TOKENS": "Cancella i token PipeWire", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Blocca la ricezione delle pose del gioco quando il cursore è sul tastiera e l'opzione 'Blocca input gioco' è attiva",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Richiedi la selezione dello schermo all'avvio successivo",
"CLEAR_SAVED_STATE": "Cancella stato salvato",
"CLEAR_SAVED_STATE_HELP": "Ripristina set e posizioni degli overlay",
"CLICK_FREEZE_TIME_MS": "Tempo di congelamento del click (ms)",
"CLICK_FREEZE_TIME_MS_HELP": "Aiuta con la precisione dei doppi clic",
"CLOCK_12H": "Orologio a 12 ore",
"CONTROLS": "Controlli",
"DELETE_ALL_CONFIGS": "Elimina configurazione",
"DELETE_ALL_CONFIGS_HELP": "Rimuovi tutti i file di configurazione da conf.d",
"DOUBLE_CURSOR_FIX": "Correzione doppio cursore",
"DOUBLE_CURSOR_FIX_HELP": "Abilita questa opzione se vedi 2 cursori",
"FEATURES": "Funzionalità",
"FOCUS_FOLLOWS_MOUSE_MODE": "Movimento del mouse al tocco del grilletto",
"HIDE_GRAB_HELP": "Nascondi l'aiuto per l'afferrare",
"HIDE_USERNAME": "Nascondi nome utente",
"INVERT_SCROLL_DIRECTION_X": "Inverti direzione dello scorrimento orizzontale",
"INVERT_SCROLL_DIRECTION_Y": "Inverti direzione dello scorrimento verticale",
"KEYBOARD_MIDDLE_CLICK": "Click centrale del tasto",
"KEYBOARD_MIDDLE_CLICK_HELP": "Modificatore da usare durante la digitazione\ncon laser viola",
"KEYBOARD_SOUND_ENABLED": "Suoni della tastiera",
"LEFT_HANDED_MOUSE": "Mouse per mancini",
"LEFT_HANDED_MOUSE_HELP": "Usalo se i pulsanti del mouse sono invertiti",
"LONG_PRESS_DURATION": "Durata pressione prolungata",
"LOOK_AND_FEEL": "Aspetto",
"MISC": "Varie",
"NOTIFICATIONS_ENABLED": "Abilita notifiche",
"NOTIFICATIONS_SOUND_ENABLED": "Suoni di notifica",
"OPAQUE_BACKGROUND": "Sfondo opaco",
"OPTION": {
"AUTO": "Automatico",
"AUTO_HELP": "Copia dello schermo tramite GPU se supportata,\naltrimenti tramite GPU PipeWire.",
"PIPEWIRE_HELP": "Acquisizione GPU veloce,\nstandard su tutti i desktop.",
"PW_FALLBACK_HELP": "Metodo lento con elevato utilizzo della CPU.\nProva in caso PipeWire GPU non funzioni",
"SCREENCOPY_GPU_HELP": "Veloce, senza popup di condivisione schermo.\nFunziona su: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Lento, nessuna finestra pop-up per la condivisione dello schermo.\nFunziona su: Hyprland, Niri, River, Sway",
"NONE": "Nessuno",
"HMD_PINCH": "HMD + pizzico",
"EYE_PINCH": "Occhio + pizzico",
"EYE_ONLY": "Solo occhio",
"HMD_ONLY": "Solo HMD",
"NONE_INPUT_HELP": "Non emulare mouse e tastiera.\nNon sarà possibile interagire con gli schermi.",
"UINPUT": "Emulazione dispositivo",
"UINPUT_HELP": "Utilizza il modulo uinput per emulare un dispositivo.\nL'utente deve far parte del gruppo input.\nRisultato ottimale su quasi tutti i desktop.",
"WL_VIRTUAL": "Input virtuale Wayland",
"WL_VIRTUAL_HELP": "Invia eventi al compositor Wayland utilizzando\nzwlr_virtual_pointer e zwp_virtual_keyboard.\nFunziona in modo affidabile solo su alcuni desktop.\nNON funziona su KDE, GNOME o COSMIC."
},
"POINTER_LERP_FACTOR": "Smussamento puntatore",
"RESTART_SOFTWARE": "Riavvia il software",
"RESTART_SOFTWARE_HELP": "Applica impostazioni che richiedono un riavvio",
"ROUND_MULTIPLIER": "Arrotondamento bordi UI",
"SCREEN_RENDER_DOWN": "Rendering dello schermo a risoluzione inferiore",
"SCREEN_RENDER_DOWN_HELP": "Aiuta a ridurre l'aliasing su schermi ad alta risoluzione",
"SCROLL_SPEED": "Velocità di scorrimento",
"SETS_ON_WATCH": "Set sul Watch",
"SPACE_DRAG_MULTIPLIER": "Moltiplicatore space-drag",
"SPACE_DRAG_UNLOCKED": "Consenti lo space-drag su tutti gli assi",
"SPACE_ROTATE_UNLOCKED": "Consenti la rotazione dello spazio su tutti gli assi",
"TROUBLESHOOTING": "Risoluzione dei problemi",
"UPRIGHT_SCREEN_FIX": "Correzione schermo verticale",
"UPRIGHT_SCREEN_FIX_HELP": "Corregge schermi verticali su alcuni desktop",
"USE_PASSTHROUGH": "Abilita passthrough",
"USE_PASSTHROUGH_HELP": "Consenti il passthrough se supportato dal runtime XR",
"USE_SKYBOX": "Abilita skybox",
"USE_SKYBOX_HELP": "Mostra uno skybox se non c'è un'app di scena o passthrough",
"XWAYLAND_BY_DEFAULT": "Esegui le app in modalità Compatibilità per impostazione predefinita",
"AUTOSTART_APPS": "App da avviare all'avvio",
"HANDSFREE_POINTER": "Modalità a mani libere",
"HANDSFREE_POINTER_HELP": "Input da usare quando i\ncontroller di movimento non sono disponibili.\nPizzico sinistro per afferrare, destro per cliccare.",
"UI_GRADIENT_INTENSITY": "Intensità gradiente dell'interfaccia utente",
"RESET_PLAYSPACE": "Ripristina playspace",
"RESET_PLAYSPACE_HELP": "Cancella l'offset dello spazio di gioco.",
"BLOCK_POSES_ON_KBD_INTERACTION": "Blocca le pose durante l'interazione con la tastiera",
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Impedisce al gioco di ricevere pose quando la tastiera è evidenziata e 'Blocca input di gioco' è abilitato",
"LANGUAGE": "Lingua",
"REQUIRES_RESTART": "Richiede riavvio",
"GRID_OPACITY": "Opacità della griglia del pavimento",
"GRID_OPACITY_HELP": "Opacità della griglia del pavimento quando lo skybox è abilitato",
"BROWSE_ONLINE_CATALOG": "Sfoglia catalogo online...",
"BROWSE_SKYMAPS": "Sfoglia skymap",
"COLOR_KEYING": "Keying del colore",
"NO_SKYMAPS_FOUND": "Nessuna skymap trovata",
"SELECT_VARIANT": "Seleziona variante",
"SHOW_WELCOME_SCREEN": "Mostra schermata di benvenuto",
"SKYBOX": "Skybox",
"SKYMAP_ALREADY_DOWNLOADED": "Questa skymap è già stata scaricata. Seleziona l'azione desiderata.",
"WATCH_VIEW_ANGLE": "Angoli di visualizzazione Watch",
"WATCH_VIEW_ANGLE_HELP": "Controlla come l'orologio sfuma",
"BINDINGS": { "BINDINGS": {
"COMP": { "COMP": {
"CLICK": "Clic", "CLICK": "Clic",
@ -137,97 +58,204 @@
}, },
"TYPE": { "TYPE": {
"BUMPER": "Bumper", "BUMPER": "Bumper",
"DPAD_UP": "D-pad su", "DPAD_UP": "D-pad Su",
"DPAD_DOWN": "D-pad Giù", "DPAD_DOWN": "D-pad Giù",
"DPAD_LEFT": "D-pad Sinistra", "DPAD_LEFT": "D-pad Sinistra",
"DPAD_RIGHT": "D-pad Destra", "DPAD_RIGHT": "D-pad Destra",
"JOYSTICK": "Joystick", "JOYSTICK": "Joystick",
"MENU": "Menu", "MENU": "Menu",
"SHOULDER": "Spalla", "SHOULDER": "Shoulder",
"SQUEEZE": "Grip", "SQUEEZE": "Impugnatura",
"SYSTEM": "Sistema", "SYSTEM": "Sistema",
"THUMBREST": "Appoggio del pollice", "THUMBREST": "Appoggio pollice",
"THUMBSTICK": "Thumbstick", "THUMBSTICK": "Thumbstick",
"TRACKPAD": "Trackpad", "TRACKPAD": "Trackpad",
"TRIGGER": "Grilletto", "TRIGGER": "Trigger",
"VIEW": "Visualizza" "VIEW": "Vista"
}, },
"CLICK": { "CLICK": {
"ANY": "Qualsiasi", "ANY": "Qualsiasi",
"DOUBLE": "Doppio tocco", "DOUBLE": "Doppio tocco",
"TRIPLE": "Triplo tocco", "TRIPLE": "Triplo tocco",
"TYPE": "Numero di tocchi" "TYPE": "Numero di tap"
}, },
"ACTION": { "ACTION": {
"CLICK": "Click*", "CLICK": "Clic*",
"GRAB": "Afferra*", "GRAB": "Afferra*",
"ALT_CLICK": "Esecuzione shell personalizzata (imposta alt_click nella configurazione)", "ALT_CLICK": "Exec shell personalizzato (imposta alt_click nel config)",
"SHOW_HIDE": "Mostra, nascondi, recentra*", "SHOW_HIDE": "Mostra, nascondi, ricentra*",
"TOGGLE_DASHBOARD": "Attiva/disattiva dashboard", "TOGGLE_DASHBOARD": "Attiva/disattiva dashboard",
"SPACE_DRAG": "Trascinamento playspace", "SPACE_DRAG": "Trascinamento Playspace",
"SPACE_ROTATE": "Rotazione playspace", "SPACE_ROTATE": "Rotazione Playspace",
"SPACE_RESET": "Reset playspace", "SPACE_RESET": "Reset playspace",
"CLICK_MODIFIER_RIGHT": "Modificatore click destro", "CLICK_MODIFIER_RIGHT": "Modificatore click destro",
"CLICK_MODIFIER_MIDDLE": "Modificatore click centrale", "CLICK_MODIFIER_MIDDLE": "Modificatore click centrale",
"MOVE_MOUSE": "Muovi mouse (se disattivato di default)", "MOVE_MOUSE": "Sposta mouse (se disattivato per impostazione predefinita)",
"SCROLL": "Scorrimento*" "SCROLL": "Scorri*"
}, },
"LEFT": "Sinistra", "LEFT": "Sinistra",
"RIGHT": "Destra", "RIGHT": "Destro",
"COMPONENT": "Tipo di attivazione", "COMPONENT": "Tipo di attuazione",
"SUBPATH": "Controllo di attivazione", "SUBPATH": "Comando di attivazione",
"THRESHOLD": "Attiva quando sopra il valore superiore\nDisattiva quando sotto il valore inferiore" "THRESHOLD": "Attiva sopra il valore superiore\nDisattiva sotto il valore inferiore"
}, },
"ENABLED": "Abilitato", "BROWSE_ONLINE_CATALOG": "Sfoglia catalogo online...",
"INPUT_EMULATION_METHOD": "Metodo di emulazione input", "BROWSE_SKYMAPS": "Sfoglia skymap",
"INPUT_EMULATION_METHOD_HELP": "Prova a cambiare questa impostazione nel caso in cui l'input del mouse o \ndella tastiera non venga registrato.", "CAPTURE_METHOD": "Metodo di cattura schermo",
"INPUT_PROFILES": "Cambia i binding di input", "CAPTURE_METHOD_HELP": "Prova a cambiarlo se riscontri\nschermi neri o glitch",
"INPUT_PROFILES_HELP": "Binding di input del controller OpenXR", "COLOR_KEYING": "Chroma key",
"NOT_SUPPORTED": "Non supportato",
"ENABLE_WATCH": "Abilita watch",
"SPACE_DRAG": "Space drag",
"SPACE_GRAVITY_DAMPING": "Smorzamento",
"SPACE_GRAVITY_DAMPING_HELP": "Resistenza artificiale per rallentare il movimento. 0.1 - alta resistenza, 1.0 - nessuna resistenza",
"SPACE_GRAVITY_FLING_STRENGTH": "Forza del lancio",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Moltiplicatore dell'intensità della forza di lancio gravitazionale dopo lo space-drag.\n0.0 - nessun movimento, 2.0 - intensità doppia",
"SPACE_GRAVITY_GRAVITY": "Gravità",
"SPACE_GRAVITY_GRAVITY_HELP": "Quantità di forza verso il basso. 0.0 - nessuna gravità",
"SPACE_GRAVITY_GROUND_FRICTION": "Attrito del terreno",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Quantità di attrito che ti rallenta se tocchi il suolo.\n0.0 - nessuna frizione (proprio come sul ghiaccio), 1.0 - superficie ruvida",
"SPACE_GRAVITY_FLOOR_HEIGHT": "Altezza del pavimento",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "La posizione Y in cui si trova il pavimento. La gravità si ferma quando raggiungi questa altezza.",
"SAVE": "Salva",
"CANCEL": "Annulla",
"WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "Il modello selezionato deve essere scaricato.\nVuoi scaricarlo adesso?",
"REMOVE_UNUSED_MODELS": "Stai disattivando la funzione di sintesi vocale.\nDesideri rimuovere i modelli Whisper scaricati per liberare spazio?"
},
"WHISPER_MODEL": "Modello di sintesi vocale (speech-to-text)",
"WHISPER_MODEL_HELP": "Modello Whisper da utilizzare.\nI modelli più grandi producono risultati\npiù accurati, ma consumano più VRAM.",
"DEFAULT_OVERLAY_SCALE": "Dimensioni overlay predefinite",
"DEFAULT_OVERLAY_SCALE_HELP": "Genera nuovi overlay con questa scala.",
"COLOR_PALETTE": "Tavolozza colori", "COLOR_PALETTE": "Tavolozza colori",
"COLOR_PALETTE_HELP": "Clicca per sfogliare le tavolozze dei colori.\nPer crearne di personalizzate, visita il sito web!",
"COLOR_PALETTES": "Tavolozze colori", "COLOR_PALETTES": "Tavolozze colori",
"COLOR_PALETTE_CURRENT": "Tema attualmente attivo.", "COLOR_PALETTE_CURRENT": "Tema attualmente attivo.",
"COLOR_PALETTE_ACTIVATE": "Clicca per usare questo tema.",
"APPLY_CHANGES_RESTART": "Riavviare WayVR per applicare le modifiche?",
"COLOR_PALETTE_HELP": "Clicca per sfogliare le palette di colori.\nPer crearne di personalizzate, visita il sito web!",
"COLOR_PALETTE_CUSTOM_URL": "Aggiungi il tuo tema personalizzato!", "COLOR_PALETTE_CUSTOM_URL": "Aggiungi il tuo tema personalizzato!",
"COLOR_PALETTE_CUSTOM_URL2": "Clicca per aprire il manuale web.", "COLOR_PALETTE_CUSTOM_URL2": "Clicca per aprire il manuale web.",
"SNAP_ANGLE_DEG": "Angolo di scatto beccheggio e rollio finestra", "COLOR_PALETTE_ACTIVATE": "Clicca per usare questo tema.",
"SNAP_ANGLE_DEG_HELP": "Le finestre afferrate si allineano a questo angolo sugli assi di beccheggio e rollio." "CLEAR_PIPEWIRE_TOKENS": "Svuota token PipeWire",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Chiedi la selezione dello schermo al prossimo avvio",
"CLEAR_SAVED_STATE": "Ripristina stato salvato",
"CLEAR_SAVED_STATE_HELP": "Resetta set e posizioni degli overlay",
"CLICK_FREEZE_TIME_MS": "Tempo di freeze del click (ms)",
"CLICK_FREEZE_TIME_MS_HELP": "Aiuta la precisione del doppio clic",
"CLOCK_12H": "Orologio a 12 ore",
"CONTROLS": "Controlli",
"DELETE_ALL_CONFIGS": "Razzera configurazione",
"DELETE_ALL_CONFIGS_HELP": "Rimuovi tutti i file di configurazione da conf.d",
"DOUBLE_CURSOR_FIX": "Correzione doppio cursore",
"DOUBLE_CURSOR_FIX_HELP": "Attivalo se vedi 2 cursori",
"DEFAULT_OVERLAY_SCALE": "Dimensione overlay predefinita",
"DEFAULT_OVERLAY_SCALE_HELP": "Fai apparire i nuovi overlay a questa scala.",
"DEFAULT_CURVATURE": "Curvatura predefinita overlay",
"DEFAULT_OPACITY": "Opacità predefinita overlay",
"DEFAULT_POSITIONING": "Posizionamento overlay predefinito",
"OVERLAY_DEFAULTS_HELP": "Si applica solo ai nuovi overlay",
"ENABLED": "Attivo",
"FEATURES": "Funzionalità",
"FOCUS_FOLLOWS_MOUSE_MODE": "Muovi mouse al tocco del trigger",
"HANDSFREE_POINTER": "Modalità mani libere",
"HANDSFREE_POINTER_HELP": "Input da usare quando i controller \ndi movimento non sono disponibili.\nPizzico sinistro per afferrare, destro per cliccare.",
"HANDSFREE_ALT_TAB": "Mirino commutatore app",
"HANDSFREE_ALT_TAB_HELP": "Tieni premuto Super+X, punta alla finestra desiderata e rilascia per cambiare focus.",
"HIDE_GRAB_HELP": "Nascondi guida alla presa",
"HIDE_USERNAME": "Nascondi nome utente",
"INPUT_EMULATION_METHOD": "Metodo di emulazione input",
"INPUT_EMULATION_METHOD_HELP": "Prova a cambiarlo se l'input del mouse o\ndella tastiera non viene registrato.",
"INPUT_CAPTURE_METHOD": "Metodo di acquisizione input",
"INPUT_CAPTURE_METHOD_HELP": "Permette di usare le periferiche fisiche all'interno di WayVR.\n Super+Z: Passa l'input tra WayVR e il desktop reale\n Super+X: Passa tra le app di WayVR",
"INPUT_PROFILES": "Cambia assegnazione tasti",
"INPUT_PROFILES_HELP": "Binding degli input del controller OpenXR",
"INVERT_SCROLL_DIRECTION_X": "Inverti direzione scorrimento orizzontale",
"INVERT_SCROLL_DIRECTION_Y": "Inverti direzione scorrimento verticale",
"KEYBOARD_MIDDLE_CLICK": "Tasto centrale tastiera",
"KEYBOARD_MIDDLE_CLICK_HELP": "Tasto modificatore da usare quando si scrive\ncon il laser viola",
"KEYBOARD_SOUND_ENABLED": "Suoni tastiera",
"LANGUAGE": "Lingua",
"LEFT_HANDED_MOUSE": "Mouse per mancini",
"LEFT_HANDED_MOUSE_HELP": "Usalo se i tasti del mouse sono invertiti",
"LONG_PRESS_DURATION": "Durata pressione lunga",
"LOOK_AND_FEEL": "Aspetto e stile",
"MISC": "Varie",
"NOTIFICATIONS_ENABLED": "Attiva notifiche",
"NOTIFICATIONS_SOUND_ENABLED": "Suoni di notifica",
"NOT_SUPPORTED": "Non supportato",
"NO_SKYMAPS_FOUND": "Nessun skymap trovato",
"OPAQUE_BACKGROUND": "Sfondo opaco",
"OPTION": {
"ANCHORED_HELP": "Si muove con il marker centrale. Consigliato.",
"FLOATING_HELP": "Si muove indipendentemente, si ricentra.\nFacile da perdere di vista; non consigliato.",
"STATIC_HELP": "Resta fisso rispetto al mondo.",
"AUTO": "Automatico",
"AUTO_HELP": "ScreenCopy GPU se supportata,\naltrimenti PipeWire GPU.",
"EYE_ONLY": "Laser oculare",
"EYE_PINCH": "Occhio + pinch",
"HMD_ONLY": "Laser HMD",
"HMD_PINCH": "HMD + pinch",
"NONE": "Nessuno",
"NONE_INPUT_HELP": "Non emulare mouse e tastiera.\nNon sarà possibile interagire con gli schermi.",
"NONE_INPUT_CAPTURE_HELP": "Non catturare mouse e tastiera.\nNon sarà possibile usare il mouse o la\ntastiera fisica nelle app lanciate in WayVR.",
"PIPEWIRE_HELP": "Cattura GPU rapida,\nstandard su tutti i desktop.",
"PW_FALLBACK_HELP": "Metodo lento con elevato utilizzo della CPU.\nProva se PipeWire GPU non funziona",
"SCREENCOPY_GPU_HELP": "Veloce, senza popup di condivisione schermo.\nFunziona con: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Lenta, senza popup di condivisione schermo.\nFunziona su: Hyprland, Niri, River, Sway",
"UINPUT": "Emulazione dispositivo",
"UINPUT_HELP": "Utilizza il modulo uinput per emulare un dispositivo.\nFunziona bene sulla maggior parte dei desktop.",
"EVDEV_HELP": "Cattura i dispositivi di input per l'uso esclusivo.\nL'utente deve appartenere al gruppo 'input'.",
"WL_VIRTUAL": "Input virtuale Wayland",
"WL_VIRTUAL_HELP": "Invia eventi al compositor Wayland usando\nzwlr_virtual_pointer e zwp_virtual_keyboard.\nFunziona in modo affidabile solo su alcuni desktop.\nNON funziona su KDE, GNOME o COSMIC."
},
"POINTER_ACCELERATION": "Accelerazione mouse",
"POINTER_ACCELERATION_HELP": "On: Accelerazione mouse adattiva\nOff: Velocità costante",
"POINTER_LERP_FACTOR": "Smorzamento puntatore",
"POINTER_SPEED": "Velocità mouse",
"REQUIRES_RESTART": "Richiede riavvio",
"RESET_PLAYSPACE": "Resetta playspace",
"RESET_PLAYSPACE_HELP": "Rimuovi l'offset dello spazio del Playspace.",
"SAVE_PLAYSPACE_CENTER": "Salva centro playspace",
"SAVE_PLAYSPACE_CENTER_HELP": "Usa il playspace corrente per il comando di reset del playspace.",
"RESET_PLAYSPACE_CENTER": "Resetta centro playspace",
"RESET_PLAYSPACE_CENTER_HELP": "Rimuovi il centro del playspace impostato precedentemente.",
"RESTART_SOFTWARE": "Riavvia software",
"RESTART_SOFTWARE_HELP": "Applica le impostazioni che richiedono il riavvio",
"ROUND_MULTIPLIER": "Arrotondamento bordi UI",
"SCREEN_RENDER_DOWN": "Rendering schermo a risoluzione inferiore",
"SCREEN_RENDER_DOWN_HELP": "Riduce l'effetto aliasing sugli schermi ad alta risoluzione",
"SCROLL_SPEED": "Velocità scorrimento",
"SELECT_VARIANT": "Seleziona variante",
"SNAP_ANGLE_DEG": "Angolo di snap beccheggio e rollio finestre",
"SNAP_ANGLE_DEG_HELP": "Le finestre afferrate si allineano a questo angolo sugli assi di beccheggio e rollio.",
"ENABLE_WATCH": "Attiva orologio",
"SETS_ON_WATCH": "Set sull'orologio",
"SHOW_WELCOME_SCREEN": "Mostra schermata di benvenuto",
"SKYBOX": "Skymap",
"SKYMAP_ALREADY_DOWNLOADED": "Questo skymap è già stato scaricato. Seleziona l'azione desiderata.",
"SPACE_DRAG": "Playspace",
"SPACE_DRAG_MULTIPLIER": "Moltiplicatore Space-drag",
"SPACE_DRAG_AFFECTS_WORLD": "Lascia gli overlay durante lo spostamento del playspace",
"SPACE_DRAG_UNLOCKED": "Permetti space-drag su tutti gli assi",
"SPACE_GRAVITY_DAMPING": "Smorzamento",
"SPACE_GRAVITY_DAMPING_HELP": "Attrito artificiale per rallentare il movimento. 0,1 - attrito elevato, 1,0 - nessun attrito",
"SPACE_GRAVITY_FLING_STRENGTH": "Forza del lancio",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Moltiplicatore dell'intensità della spinta gravitazionale dopo lo space-drag.\n0.0 - nessun movimento, 2.0 - intensità doppia",
"SPACE_GRAVITY_GRAVITY": "Gravità",
"SPACE_GRAVITY_GRAVITY_HELP": "Forza verso il basso. 0.0 - assenza di gravità",
"SPACE_GRAVITY_GROUND_FRICTION": "Attrito al suolo",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Quantità di attrito che ti rallenta quando tocchi terra.\n0.0 - nessun attrito (come sul ghiaccio), 1.0 - superficie ruvida",
"SPACE_GRAVITY_FLOOR_HEIGHT": "Altezza pavimento",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "La posizione Y del pavimento. La gravità si interrompe quando raggiungi questa altezza.",
"SPACE_ROTATE_UNLOCKED": "Consenti rotazione del playspace su tutti gli assi",
"TROUBLESHOOTING": "Risoluzione problemi",
"UI_GRADIENT_INTENSITY": "Intensità gradiente UI",
"UPRIGHT_SCREEN_FIX": "Correzione orientamento schermo",
"UPRIGHT_SCREEN_FIX_HELP": "Risolve il problema degli schermi verticali su alcuni desktop",
"USE_PASSTHROUGH": "Abilita passthrough",
"USE_PASSTHROUGH_HELP": "Consenti il passthrough se supportato dal runtime XR",
"USE_SKYBOX": "Mostra skymap",
"USE_SKYBOX_HELP": "Mostra una skymap se non c'è un'app di scena o il passthrough",
"WATCH_VIEW_ANGLE": "Angoli di visualizzazione orologio",
"WATCH_VIEW_ANGLE_HELP": "Controlla come scompare l'orologio",
"WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "Il modello selezionato deve essere scaricato.\nScaricarlo ora?",
"REMOVE_UNUSED_MODELS": "Stai disattivando la funzione di riconoscimento vocale.\nVuoi rimuovere i modelli Whisper scaricati per liberare spazio?"
},
"WHISPER_MODEL": "Modello speech-to-text",
"WHISPER_MODEL_HELP": "Modello Whisper da utilizzare.\nModelli più grandi offrono risultati\npiù precisi, ma consumano più VRAM.",
"GRID_OPACITY": "Opacità griglia pavimento",
"GRID_OPACITY_HELP": "Opacità della griglia del pavimento quando lo skymap è attivo",
"XWAYLAND_BY_DEFAULT": "Avvia le app in modalità compatibilità per impostazione predefinita",
"SAVE": "Salva",
"CANCEL": "Annulla"
}, },
"APPLICATION_LAUNCHER": "Lanciatore applicazioni", "APPLICATION_LAUNCHER": "Avvio applicazioni",
"APPLICATION_STARTED": "Applicazione avviata", "APPLICATION_STARTED": "Applicazione avviata",
"APPLICATIONS": "Applicazioni", "APPLICATIONS": "Applicazioni",
"AUDIO": { "AUDIO": {
"AUTO_SWITCH_TO_VR_AUDIO": "Passa automaticamente all'audio VR", "AUTO_SWITCH_TO_VR_AUDIO": "Passa automaticamente all'audio VR",
"CARDS": "Schede", "CARDS": "Schede",
"FAILED_TO_SWITCH_MICROPHONE": "Impossibile cambiare microfono", "FAILED_TO_SWITCH_MICROPHONE": "Errore nel cambio microfono",
"MICROPHONE_SET_SUCCESSFULLY": "Microfono impostato con successo", "MICROPHONE_SET_SUCCESSFULLY": "Microfono impostato correttamente",
"MICROPHONES": "Microfoni", "MICROPHONES": "Microfoni",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Nessun microfono VR trovato. Attivalo manualmente.", "NO_VR_MICROPHONE_SWITCH_MANUALLY": "Nessun microfono VR trovato. Selezionalo manualmente.",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Nessun altoparlante VR trovato. Selezionali manualmente.", "NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Altoparlanti VR non trovati. Selezionali manualmente.",
"SELECT_AUDIO_CARD_PROFILE": "Seleziona profilo scheda audio", "SELECT_AUDIO_CARD_PROFILE": "Seleziona profilo scheda audio",
"SETTINGS": "Impostazioni audio", "SETTINGS": "Impostazioni audio",
"SPEAKERS": "Altoparlanti", "SPEAKERS": "Altoparlanti",
@ -235,84 +263,87 @@
"VOLUME": "Volume" "VOLUME": "Volume"
}, },
"CLOSE_WINDOW": "Chiudi finestra", "CLOSE_WINDOW": "Chiudi finestra",
"DISPLAY_BRIGHTNESS": "Luminosità display", "CREATION_DATE": "Data di creazione",
"FAILED_TO_LAUNCH_APPLICATION": "Impossibile avviare l'applicazione:", "DEBUG_INFO": "Info debug",
"GAME_LAUNCHED": "Gioco lanciato", "DISPLAY_BRIGHTNESS": "Luminosità schermo",
"DONATE": {
"SUPPORT_US": "Sostienici",
"DESCRIPTION": "Siamo un piccolo team di 2 sviluppatori che realizza WayVR nel tempo libero. Se ti piace usare questo software, considera di supportarci: ogni donazione ci aiuta a continuare.",
"THANK_YOU_WAYVR": "Grazie dal team di WayVR!",
"BUTTON_TOOLTIP": "Donazione tramite Open Collective",
"CURRENT_SUPPORTERS": "Supporter attuali",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Supportato da {USER}|Grazie speciali a {USER}|Sponsorizzato da {USER}|Contributo di {USER}|Sostenuto da membri come {USER}|Reso possibile da {USER}|Sostenuto da {USER}|Grazie a {USER}|Alimentato da {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Caffè offerto da {USER}|Energia pura grazie a {USER}|Un grande applauso a {USER}!|Ci tiene in piedi: {USER}|Ci aiuta a crescere: {USER}|Mantiene i server accesi: {USER}|Con immensa gratitudine a {USER}|Spinto dalla forza di {USER}|Supportato da amici come {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Supportato da leggende come {USER}|Caffeina fornita da {USER}|Una vera leggenda: {USER}|Il nostro eroe del giorno: {USER}|Una superstar assoluta: {USER}|Paga la bolletta della luce: {USER}|Il motore della nostra creatività: {USER}|Il navigatore del nostro percorso: {USER}|Convertitore caffeina-codice fornito da {USER}|Mantiene la produzione stabile: {USER}|L'unico e inimitabile: {USER}|Maestro dei buffer dmabuf: {USER}"
},
"DOWNLOAD": "Scarica",
"DOWNLOADER": "Download",
"WELCOME": {
"ALL_SET": "Sei pronto!",
"BASICS": "Questi concetti base ti permetteranno di usare WayVR con facilità.",
"CENTER_MARKER": "Il marker centrale è ciò che apparirà davanti a te durante il ricentramento. Posiziona gli overlay intorno ad esso!",
"DOUBLE_PRESS_TO_TOGGLE": "Premi due volte B (su Index) o Y (su Meta) per mostrare, ricentrare o nascondere il tuo Set. Prova ora.",
"FEATURES_DOCUMENTATION": "Ci sono molte altre funzioni che vale la pena personalizzare. Per maggiori informazioni, consulta la documentazione su",
"FINISH_TUTORIAL": "Completa tutorial",
"GRAB_BOTH_HANDS": "Afferra con entrambe le mani se vuoi spostare un overlay specifico del tuo set.",
"GRAB_ONE_HAND": "Afferra con una mano per spostare il set.",
"GREETING": "Ciao!",
"GUIDE_INTRO": "Ti guidiamo attraverso i primi passi.",
"LASER_COLORS": "Colori del laser",
"LASER_FUNCTIONALITY": "Gran parte delle funzionalità di WayVR dipende dal colore del laser usato per interagire con gli elementi dell'interfaccia. Non serve premere i pulsanti, basta toccarli!",
"LAST_PAGE_INFO": "Questo tutorial smetterà di apparire una volta raggiunta l'ultima pagina.",
"LOOK_AT_LEFT_WRIST": "Guarda il tuo polso sinistro. Quello è il tuo orologio.",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Modalità click centrale: laser viola",
"MOVING_YOUR_SET": "Spostare il set",
"NEXT_BUTTON": "Premi Avanti qui sotto per iniziare.",
"REGULAR_MODE_BLUE_LASER": "Modalità standard: laser blu",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Riposiziona questa finestra usando il tasto grip del controller.",
"RIGHT_CLICK_MODE_ORANGE_LASER": "Modalità tasto destro: Laser arancione",
"THANKS_FOR_INSTALLING": "Grazie per aver installato WayVR!",
"WATCH": "Orologio",
"WORKING_SET": "Set attivo"
},
"DOWNLOAD_AGAIN": "Scarica di nuovo",
"DOWNLOADING_FILE": "Download file in corso...",
"FAILED_TO_LAUNCH_APPLICATION": "Errore nel lancio dell'applicazione:",
"GAME_LAUNCHED": "Gioco avviato",
"GAME_LIST": { "GAME_LIST": {
"NO_GAMES_FOUND": "Nessun gioco trovato", "NO_GAMES_FOUND": "Nessun gioco trovato",
"RUNNING_GAMES_LIST": "Lista dei giochi in esecuzione" "RUNNING_GAMES_LIST": "Lista giochi in esecuzione"
}, },
"GAMES": "Giochi", "GAMES": "Giochi",
"GENERAL_SETTINGS": "Impostazioni generali", "GENERAL_SETTINGS": "Impostazioni generali",
"GETTING_STARTED": "Inizia qui",
"HEIGHT": "Altezza", "HEIGHT": "Altezza",
"HELLO": "Ciao!", "HELLO": "Ciao!",
"HELLO_USER": "Ciao, {USER}!", "HELLO_USER": "Ciao, {USER}!",
"HIDE": "Nascondi", "HIDE": "Nascondi",
"HOME_SCREEN": "Home", "HOME_SCREEN": "Home",
"MONADO_RUNTIME": "Runtime Monado", "MODIFICATION_DATE": "Data modifica",
"MONADO_RUNTIME": "Runtime di Monado",
"LOADING": "Caricamento...",
"POPUP_ADD_DISPLAY": { "POPUP_ADD_DISPLAY": {
"RESOLUTION": "Risoluzione" "RESOLUTION": "Risoluzione"
}, },
"PROCESS": {
"FORCE_KILL": "Chiudi forzatamente",
"STOP": "Ferma"
},
"PROCESS_LIST": "Lista processi",
"REFRESH": "Aggiorna",
"REMOVE": "Rimuovi", "REMOVE": "Rimuovi",
"APPLY": "Applica",
"RELOAD_FROM_DISK": "Ricarica dal disco",
"SETTINGS": "Impostazioni", "SETTINGS": "Impostazioni",
"SHOW": "Mostra", "SHOW": "Mostra",
"TERMINATE_PROCESS": "Termina processo",
"WIDTH": "Larghezza",
"PROCESS_LIST": "Elenco processi",
"REFRESH": "Aggiorna",
"PROCESS": {
"STOP": "Interrompi",
"FORCE_KILL": "Uccidi forzatamente"
},
"DEBUG_INFO": "Informazioni di debug",
"CREATION_DATE": "Data di creazione",
"DOWNLOADER": "Downloader",
"DOWNLOAD_AGAIN": "Scarica di nuovo",
"DOWNLOADING_FILE": "Download del file in corso...",
"GETTING_STARTED": "Inizio rapido",
"MODIFICATION_DATE": "Data di modifica",
"LOADING": "Caricamento...",
"APPLY": "Applica",
"RELOAD_FROM_DISK": "Ricarica da disco",
"TARGET_PATH": "Percorso di destinazione", "TARGET_PATH": "Percorso di destinazione",
"TERMINATE_PROCESS": "Termina processo",
"VERSION": "Versione", "VERSION": "Versione",
"DONATE": { "WIDTH": "Larghezza",
"SUPPORT_US": "Sostienici", "PINNED_APPS": "Applicazioni fissate",
"DESCRIPTION": "Siamo un piccolo team di 2 sviluppatori che crea WayVR nel tempo libero. Se ti piace usare questo software, considera di supportarci: ogni donazione ci aiuta a continuare.", "SAVED_TO_FAVOURITES": "Salvato nelle applicazioni fissate",
"BUTTON_TOOLTIP": "Dona tramite Open Collective", "ADD_TO_FAVOURITES": "Aggiungi alle applicazioni fissate",
"CURRENT_SUPPORTERS": "Sostenitori attuali",
"THANK_YOU_WAYVR": "Grazie dal team WayVR!"
},
"WELCOME": {
"ALL_SET": "Sei pronto!",
"BASICS": "Queste nozioni di base ti permetteranno di iniziare a usare WayVR con facilità.",
"FEATURES_DOCUMENTATION": "Ci sono molte altre funzioni che vale la pena personalizzare. Per ulteriori informazioni, consulta la documentazione all'indirizzo",
"FINISH_TUTORIAL": "Termina tutorial",
"GRAB_BOTH_HANDS": "Afferralo con entrambe le mani se vuoi spostare un overlay specifico nel tuo set.",
"GRAB_ONE_HAND": "Afferralo con una mano per muovere il tuo set.",
"GREETING": "Ciao!",
"GUIDE_INTRO": "Lascia che ti guidiamo nei tuoi primi passi.",
"LASER_COLORS": "Colori Laser",
"LASER_FUNCTIONALITY": "Gran parte delle funzionalità in WayVR dipende dal colore del laser utilizzato per interagire con un elemento dell'interfaccia utente. Non è necessario premere questi pulsanti, basta toccarli!",
"LAST_PAGE_INFO": "Questo tutorial smetterà di apparire una volta raggiunta l'ultima pagina.",
"LOOK_AT_LEFT_WRIST": "Guarda il tuo polso sinistro. È il tuo watch.",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— Modalità click centrale: Laser viola",
"MOVING_YOUR_SET": "Spostamento del tuo set",
"NEXT_BUTTON": "Premi il pulsante \"Avanti\" qui sotto per iniziare.",
"REGULAR_MODE_BLUE_LASER": "— Modalità Standard: Laser blu",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Riposiziona questa finestra usando l'azione grip del tuo controller.",
"RIGHT_CLICK_MODE_ORANGE_LASER": "— Modalità tasto destro: Laser arancione",
"THANKS_FOR_INSTALLING": "Grazie per aver installato WayVR!",
"WATCH": "Watch",
"WORKING_SET": "Set di lavoro",
"DOUBLE_PRESS_TO_TOGGLE": "Premi due volte B (su Index) o Y (su Meta) per mostrare, ricentrare o nascondere il tuo set. Provalo ora.",
"CENTER_MARKER": "Il marker di centraggio è ciò che apparirà davanti a te durante il ricentramento. Posiziona gli overlay intorno ad esso!"
},
"DOWNLOAD": "Scarica",
"SAVED_TO_FAVOURITES": "Salvato nei preferiti",
"ADD_TO_FAVOURITES": "Aggiungi ai preferiti",
"ADD_TO_FAVOURITES_HINT": "Salva il preset e fissalo al cassetto delle app", "ADD_TO_FAVOURITES_HINT": "Salva il preset e fissalo al cassetto delle app",
"REMOVE_FROM_FAVOURITES": "Rimuovi dai preferiti", "REMOVE_FROM_FAVOURITES": "Rimuovi dalle app fissate",
"EMPTY": "Vuoto", "EMPTY": "Vuoto"
"PINNED_APPS": "Applicazioni fissate"
} }

View File

@ -1,318 +1,349 @@
{ {
"HOME_SCREEN": "ホーム", "DEFINITIONS": {
"MONADO_RUNTIME": "「Monado」ランタイム", "ANCHORED": "セット追従",
"APPLICATIONS": "アプリ", "FLOATING": "フローティング",
"GAMES": "ゲーム", "STATIC": "固定",
"SETTINGS": "設定", "SET": "セット",
"HELLO_USER": "こんにちは、{USER}", "WATCH": "ウォッチ",
"GENERAL_SETTINGS": "全般設定", "DASHBOARD": "ダッシュボード",
"APPLICATION_LAUNCHER": "アプリケーションランチャー", "EDIT_MODE": "編集モード",
"APP_SETTINGS": { "SETTINGS": "設定",
"HIDE_USERNAME": "ユーザー名を非表示", "KEYBOARD": "キーボード",
"OPAQUE_BACKGROUND": "不透明な背景", "TASKBAR": "タスクバー",
"LOOK_AND_FEEL": "外観",
"HIDE_GRAB_HELP": "グリップ動作中にのヘルプを非表示",
"ANIMATION_SPEED": "UIアニメーション速度",
"ROUND_MULTIPLIER": "UI の丸み",
"USE_SKYBOX": "スカイボックスを有効",
"USE_PASSTHROUGH": "パススルーを有効",
"CLOCK_12H": "12時間制",
"FEATURES": "機能", "FEATURES": "機能",
"NOTIFICATIONS_ENABLED": "通知を有効にする", "OVERLAY": "オーバーレイ",
"NOTIFICATIONS_SOUND_ENABLED": "通知音", "SKYMAP": "スカイマップ",
"KEYBOARD_SOUND_ENABLED": "キーボード音", "PLAYSPACE": "プレイスペース",
"SPACE_DRAG_MULTIPLIER": "スペースドラッグ倍率", "D_PAD": "十字キー"
"SPACE_DRAG_UNLOCKED": "全軸のスペースドラッグ", },
"SPACE_ROTATE_UNLOCKED": "全軸のスペース回転", "ACTIONS": {
"BLOCK_GAME_INPUT": "ゲームの入力をブロック", "RECENTER_PLAYSPACE": "プレイスペースをリセンター"
"BLOCK_GAME_INPUT_IGNORE_WATCH": "入力ブロック時に監視を無視", },
"CONTROLS": "コントロール", "APP_LAUNCHER": {
"FOCUS_FOLLOWS_MOUSE_MODE": "トリガータッチでマウス移動", "ASPECT": {
"LEFT_HANDED_MOUSE": "左利きマウス", "SEMI_TALL": "やや縦長",
"ALLOW_SLIDING": "グリップ動作中にスティックを有効", "SEMI_WIDE": "セミワイド",
"INVERT_SCROLL_DIRECTION_X": "水平スクロール方向を反転", "SQUARE": "正方形",
"INVERT_SCROLL_DIRECTION_Y": "垂直スクロール方向を反転", "TALL": "縦長",
"SCROLL_SPEED": "スクロール速度", "WIDE": "ワイド"
"LONG_PRESS_DURATION": "長押し時間",
"POINTER_LERP_FACTOR": "ポインターのスムージング",
"CLICK_FREEZE_TIME_MS": "クリックで一時停止時間 (ms)",
"MISC": "その他",
"XWAYLAND_BY_DEFAULT": "アプリ実行のデフォルトは互換モード",
"UPRIGHT_SCREEN_FIX": "画面の縦向き修正",
"DOUBLE_CURSOR_FIX": "ダブルカーソル修正",
"SCREEN_RENDER_DOWN": "画面の解像度を縮小",
"UPRIGHT_SCREEN_FIX_HELP": "一部のデスクトップで縦向きの画面を修正",
"DOUBLE_CURSOR_FIX_HELP": "2つのカーソルが表示される場合は、これを有効にします",
"CLICK_FREEZE_TIME_MS_HELP": "ダブルクリックの精度向上に役立ちます",
"LEFT_HANDED_MOUSE_HELP": "マウスボタンが入れ替わっている場合に有効にします",
"BLOCK_GAME_INPUT_HELP": "オーバーレイ上にマウスカーソルがあるときに入力をブロックします",
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "ウォッチがホバーされているときは入力をブロックしない",
"USE_SKYBOX_HELP": "シーンアプリまたはパススルーがない場合にスカイボックスを表示します",
"USE_PASSTHROUGH_HELP": "XRランタイムがサポートしていれば、パススルーを有効にします",
"SCREEN_RENDER_DOWN_HELP": "高解像度スクリーンでのエイリアシングを軽減します",
"SETS_ON_WATCH": "ウォッチのセット",
"TROUBLESHOOTING": "トラブルシューティング",
"CLEAR_SAVED_STATE": "保存された状態をクリア",
"CLEAR_PIPEWIRE_TOKENS": "PipeWire トークンをクリア",
"DELETE_ALL_CONFIGS": "設定を消去",
"RESTART_SOFTWARE": "ソフトウェアを再起動",
"CLEAR_SAVED_STATE_HELP": "セットとオーバーレイの位置をリセット",
"CLEAR_PIPEWIRE_TOKENS_HELP": "次の起動時に画面選択のプロンプトを表示",
"DELETE_ALL_CONFIGS_HELP": "conf.d 内のすべての設定ファイルを削除",
"RESTART_SOFTWARE_HELP": "再起動が必要な設定を適用",
"CAPTURE_METHOD": "Waylandスクリーンキャプチャ",
"CAPTURE_METHOD_HELP": "画面が黒くなる、または乱れる場合は、\nこの設定を変更してみてください。",
"KEYBOARD_MIDDLE_CLICK": "キーボードの中ボタンクリック",
"KEYBOARD_MIDDLE_CLICK_HELP": "紫色のレーザーで入力する際の修飾キー",
"OPTION": {
"AUTO": "自動",
"AUTO_HELP": "サポートされている場合はScreenCopy GPU、\nそうでない場合はPipeWire GPU。",
"PIPEWIRE_HELP": "GPU高速キャプチャ。\nすべてのデスクトップで標準です。",
"PW_FALLBACK_HELP": "CPU使用量が多い低速な方法です。\nPipeWire GPUが動作しない場合に試してください。",
"SCREENCOPY_GPU_HELP": "高速で、スクリーン共有ポップアップはありません。\n動作する環境: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "遅延あり、画面共有ポップアップなし。\n動作する環境: Hyprland, Niri, River, Sway",
"NONE": "なし",
"HMD_PINCH": "HMD + ピンチ",
"EYE_PINCH": "つまんで目を合わせる",
"EYE_ONLY": "視野のみ",
"HMD_ONLY": "HMDのみ",
"NONE_INPUT_HELP": "マウスとキーボードをエミュレートしません。\nディスプレイを操作できなくなります。",
"UINPUT": "デバイス・エミュレーション",
"UINPUT_HELP": "uinput モジュールを使用してデバイスをエミュレートします。\nユーザーが input グループに属している必要があります。\nほとんどのデスクトップ環境で正常に動作することが確認されています。",
"WL_VIRTUAL": "Wayland 仮想入力",
"WL_VIRTUAL_HELP": "zwlr_virtual_pointer および zwp_virtual_keyboard を使用して、Wayland コンポジタにイベントを送信します。\n一部のデスクトップ環境でのみ、安定して動作します。\nKDE、GNOME、または COSMIC では動作しません。"
}, },
"ASPECT_TITLE": "アスペクト比",
"AUTOSTART": "起動時に自動的に実行",
"LAUNCH": "起動",
"MODE": {
"CAGE": "互換モード (Cage)",
"NATIVE": "ネイティブモード"
},
"RES_TITLE": "解像度"
},
"APP_SETTINGS": {
"ALLOW_SLIDING": "掴持中のスティック操作",
"ANIMATION_SPEED": "UIアニメーション速度",
"AUTOSTART_APPS": "起動時に実行するアプリ", "AUTOSTART_APPS": "起動時に実行するアプリ",
"HANDSFREE_POINTER": "ハンズフリーモード", "BLOCK_GAME_INPUT": "ゲームへの入力をブロック",
"HANDSFREE_POINTER_HELP": "モーションコントローラーが利用できない場合の入力方法。\n左手のピンチは掴み、右手のピンチはクリックです。", "BLOCK_GAME_INPUT_HELP": "オーバーレイにカーソルが合っている間、すべての入力をブロックする",
"UI_GRADIENT_INTENSITY": "UIグラデーションの強さ", "BLOCK_GAME_INPUT_IGNORE_WATCH": "入力ブロック時にウォッチを無視",
"RESET_PLAYSPACE": "プレイエリアをリセット", "BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "ウォッチホバー時は入力をブロックしない",
"RESET_PLAYSPACE_HELP": "プレイエリアのオフセットをクリアします。", "BLOCK_POSES_ON_KBD_INTERACTION": "キーボード操作時にポーズ入力をブロック",
"BLOCK_POSES_ON_KBD_INTERACTION": "キーボード操作時のポーズをブロック", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "キーボードにカーソルがあり「ゲーム入力をブロック」が有効なとき、ゲームへのポーズ送信を停止する",
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "キーボードがホバーされ、「ゲーム入力をブロック」が有効になっている場合、ゲームがポーズを受信することをブロックします",
"LANGUAGE": "言語",
"REQUIRES_RESTART": "再起動が必要です",
"GRID_OPACITY": "フロアグリッドの不透明度",
"GRID_OPACITY_HELP": "スカイボックスが有効なときの床グリッドの不透明度",
"BROWSE_ONLINE_CATALOG": "オンラインカタログを閲覧...",
"BROWSE_SKYMAPS": "Skymapを閲覧",
"COLOR_KEYING": "カラーキーイング",
"NO_SKYMAPS_FOUND": "スカイマップが見つかりません",
"SELECT_VARIANT": "バリアントを選択",
"SHOW_WELCOME_SCREEN": "ウェルカムスクリーンを表示する",
"SKYBOX": "スカイボックス",
"SKYMAP_ALREADY_DOWNLOADED": "このスカイマップは既にダウンロードされています。希望のアクションを選択してください。",
"WATCH_VIEW_ANGLE": "Watchの表示角度",
"WATCH_VIEW_ANGLE_HELP": "ウォッチのフェードアウト具合を調整する",
"BINDINGS": { "BINDINGS": {
"COMP": { "COMP": {
"CLICK": "クリック", "CLICK": "クリック",
"FORCE": "Force", "FORCE": "押し込み強度",
"TOUCH": "タッチ", "TOUCH": "タッチ",
"VALUE": "値", "VALUE": "値",
"PROXIMITY": "近接", "PROXIMITY": "近接",
"X_AXIS": "X軸", "X_AXIS": "X軸",
"Y_AXIS": "Y軸" "Y_AXIS": "Y軸"
}, },
"TYPE": { "TYPE": {
"BUMPER": "バンパー", "BUMPER": "バンパー",
"DPAD_UP": "Dパッド上", "DPAD_UP": "十字キー上",
"DPAD_DOWN": "Dパッド 下", "DPAD_DOWN": "十字キー下",
"DPAD_LEFT": "Dパッド左", "DPAD_LEFT": "十字キー左",
"DPAD_RIGHT": "Dパッド右", "DPAD_RIGHT": "十字キー右",
"JOYSTICK": "ジョイスティック", "JOYSTICK": "ジョイスティック",
"MENU": "メニュー", "MENU": "メニュー",
"SHOULDER": "ショルダー", "SHOULDER": "ショルダーボタン",
"SQUEEZE": "グリップ", "SQUEEZE": "グリップ",
"SYSTEM": "システム", "SYSTEM": "システム",
"THUMBREST": "サムレスト", "THUMBREST": "親指置き場",
"THUMBSTICK": "サムスティック", "THUMBSTICK": "サムスティック",
"TRACKPAD": "トラックパッド", "TRACKPAD": "トラックパッド",
"TRIGGER": "トリガー", "TRIGGER": "トリガー",
"VIEW": "表示" "VIEW": "ビュー"
}, },
"CLICK": { "CLICK": {
"ANY": "任意", "ANY": "任意",
"DOUBLE": "ダブルタップ", "DOUBLE": "ダブルタップ",
"TRIPLE": "トリプルタップ", "TRIPLE": "トリプルタップ",
"TYPE": "タップ数" "TYPE": "タップ数"
}, },
"ACTION": { "ACTION": {
"CLICK": "クリック*", "CLICK": "クリック*",
"GRAB": "掴む*", "GRAB": "掴む*",
"ALT_CLICK": "カスタムシェル実行 (configでalt_clickを設定)", "ALT_CLICK": "カスタムシェル実行 (configでalt_clickを設定)",
"SHOW_HIDE": "表示・非表示再中心化*", "SHOW_HIDE": "表示・非表示再中心化*",
"TOGGLE_DASHBOARD": "ダッシュボードの切り替え", "TOGGLE_DASHBOARD": "ダッシュボードの切り替え",
"SPACE_DRAG": "Playspaceドラッグ", "SPACE_DRAG": "プレイスペースのドラッグ",
"SPACE_ROTATE": "Playspace 回転", "SPACE_ROTATE": "プレイスペース回転",
"SPACE_RESET": "Playspace リセット", "SPACE_RESET": "プレイスペースのリセット",
"CLICK_MODIFIER_RIGHT": "右クリック修飾キー", "CLICK_MODIFIER_RIGHT": "右クリック修飾キー",
"CLICK_MODIFIER_MIDDLE": "中クリック修飾キー", "CLICK_MODIFIER_MIDDLE": "中クリック修飾キー",
"MOVE_MOUSE": "マウス移動 (デフォルトでオフの場合)", "MOVE_MOUSE": "マウス移動 (デフォルトでオフ)",
"SCROLL": "スクロール*" "SCROLL": "スクロール*"
}, },
"LEFT": "左", "LEFT": "左",
"RIGHT": "右", "RIGHT": "右",
"COMPONENT": "作動タイプ", "COMPONENT": "入力形式",
"SUBPATH": "アクチュエーション制御", "SUBPATH": "操作ボタン",
"THRESHOLD": "上限値を超えたときに有効化\n下限値を下回ったときに無効化" "THRESHOLD": "上の値を超えると有効\n下の値を下回ると無効"
}, },
"ENABLED": "有効", "BROWSE_ONLINE_CATALOG": "オンラインカタログを見る...",
"INPUT_EMULATION_METHOD": "入力エミュレーション方法", "BROWSE_SKYMAPS": "スカイマップを選択",
"INPUT_EMULATION_METHOD_HELP": "マウスやキーボードの入力が\n認識されない場合は、ここを変更してみてください。", "CAPTURE_METHOD": "画面キャプチャ方式",
"INPUT_PROFILES": "入力バインドの変更", "CAPTURE_METHOD_HELP": "画面が黒くなったり、表示が乱れたりする場合は\nここを変更して試してください",
"INPUT_PROFILES_HELP": "OpenXRコントローラーの入力バインディング", "COLOR_KEYING": "カラーキー",
"NOT_SUPPORTED": "未対応",
"ENABLE_WATCH": "Watchを有効にする",
"SPACE_DRAG": "Space drag",
"SPACE_GRAVITY_DAMPING": "減衰",
"SPACE_GRAVITY_DAMPING_HELP": "動きを減速させるための人工的な抵抗です。0.1 - 強い抵抗、1.0 - 抵抗なし",
"SPACE_GRAVITY_FLING_STRENGTH": "スリングの強さ",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Space-drag 後の重力による打ち出し強度の倍率です。\n0.0 - 全く動きません、2.0 - 強度が2倍になります",
"SPACE_GRAVITY_GRAVITY": "重力",
"SPACE_GRAVITY_GRAVITY_HELP": "下向きの力の強さ。0.0 - 重力なし",
"SPACE_GRAVITY_GROUND_FRICTION": "地面の摩擦",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "地面に触れている際に、移動を遅らせる摩擦の強さです。\n0.0 - 摩擦なし氷の上のような状態、1.0 - 粗い表面",
"SPACE_GRAVITY_FLOOR_HEIGHT": "床の高さ",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "床のY座標です。この高さに達すると重力が停止します。",
"SAVE": "保存",
"CANCEL": "キャンセル",
"WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "選択されたモデルをダウンロードする必要があります。\n今すぐダウンロードしますか",
"REMOVE_UNUSED_MODELS": "文字起こし機能をオフにします。\n空き容量を増やすために、ダウンロード済みのモデルファイルを削除しますか"
},
"WHISPER_MODEL": "文字起こしモデル",
"WHISPER_MODEL_HELP": "使用するWhisperモデル。\nモデルが大きいほど精度は向上しますが、\nVRAMの消費量が増加します。",
"DEFAULT_OVERLAY_SCALE": "デフォルトのオーバーレイサイズ",
"DEFAULT_OVERLAY_SCALE_HELP": "新しいオーバーレイをこのスケールで生成します。",
"COLOR_PALETTE": "カラーパレット", "COLOR_PALETTE": "カラーパレット",
"COLOR_PALETTE_HELP": "クリックしてカラーパレットを選択。\nカスタムパレットの作成方法はウェブサイトを確認",
"COLOR_PALETTES": "カラーパレット", "COLOR_PALETTES": "カラーパレット",
"COLOR_PALETTE_CURRENT": "現在有効なテーマ。", "COLOR_PALETTE_CURRENT": "現在適用中のテーマ",
"COLOR_PALETTE_ACTIVATE": "クリックしてこのテーマを適用します。", "COLOR_PALETTE_CUSTOM_URL": "カスタムテーマを追加!",
"APPLY_CHANGES_RESTART": "変更を適用するためにWayVRを再起動しますか", "COLOR_PALETTE_CUSTOM_URL2": "Webマニュアルを開く",
"COLOR_PALETTE_HELP": "クリックしてカラーパレットを選択してください。\nカスタムパレットの作成については、ウェブサイトを参照してください", "COLOR_PALETTE_ACTIVATE": "クリックしてこのテーマを適用。",
"COLOR_PALETTE_CUSTOM_URL": "カスタムテーマを追加しましょう!", "CLEAR_PIPEWIRE_TOKENS": "PipeWireトークンを消去",
"COLOR_PALETTE_CUSTOM_URL2": "クリックしてウェブマニュアルを開く。", "CLEAR_PIPEWIRE_TOKENS_HELP": "次回起動時に画面選択を促す",
"SNAP_ANGLE_DEG": "ウィンドウのピッチ・ロールのスナップ角度", "CLEAR_SAVED_STATE": "保存済み状態をリセット",
"SNAP_ANGLE_DEG_HELP": "掴んでいるウィンドウが、ピッチ軸とロール軸でこの角度にスナップします。" "CLEAR_SAVED_STATE_HELP": "セットとオーバーレイの位置をリセット",
"CLICK_FREEZE_TIME_MS": "クリック固定時間 (ms)",
"CLICK_FREEZE_TIME_MS_HELP": "ダブルクリックの精度を向上させます",
"CLOCK_12H": "12時間表記",
"CONTROLS": "操作設定",
"DELETE_ALL_CONFIGS": "設定をリセット",
"DELETE_ALL_CONFIGS_HELP": "conf.d内のすべての設定ファイルを削除する",
"DOUBLE_CURSOR_FIX": "カーソル二重表示の修正",
"DOUBLE_CURSOR_FIX_HELP": "カーソルが2つ表示される場合に有効にする",
"DEFAULT_OVERLAY_SCALE": "デフォルトのオーバーレイサイズ",
"DEFAULT_OVERLAY_SCALE_HELP": "新しいオーバーレイをこの倍率で表示する。",
"DEFAULT_CURVATURE": "デフォルトのオーバーレイ曲率",
"DEFAULT_OPACITY": "デフォルトのオーバーレイ不透明度",
"DEFAULT_POSITIONING": "オーバーレイのデフォルト配置",
"OVERLAY_DEFAULTS_HELP": "新規オーバーレイにのみ適用",
"ENABLED": "有効",
"FEATURES": "機能",
"FOCUS_FOLLOWS_MOUSE_MODE": "トリガー接触でマウス移動",
"HANDSFREE_POINTER": "ハンズフリーモード",
"HANDSFREE_POINTER_HELP": "コントローラーがない時に使用する入力方式。\n左手のピンチで掴み、右手のピンチでクリック。",
"HANDSFREE_ALT_TAB": "アプリ切替の方向",
"HANDSFREE_ALT_TAB_HELP": "Super+Xを押しながら目的のウィンドウに向け、離すとフォーカスが切り替わる。",
"HIDE_GRAB_HELP": "掴み方のヒントを隠す",
"HIDE_USERNAME": "ユーザー名を隠す",
"INPUT_EMULATION_METHOD": "入力エミュレーション方式",
"INPUT_EMULATION_METHOD_HELP": "マウスやキーボードの入力が\n反応しない場合はここを変更してください。",
"INPUT_CAPTURE_METHOD": "入力キャプチャ方式",
"INPUT_CAPTURE_METHOD_HELP": "WayVR内で物理周辺機器を使用可能にする。\n Super+Z: WayVRと実デスクトップの間で入力を切り替え\n Super+X: WayVRアプリ間を切り替え",
"INPUT_PROFILES": "入力バインドを変更",
"INPUT_PROFILES_HELP": "OpenXRコントローラー入力バインド",
"INVERT_SCROLL_DIRECTION_X": "水平スクロール方向を反転",
"INVERT_SCROLL_DIRECTION_Y": "垂直スクロール方向を反転",
"KEYBOARD_MIDDLE_CLICK": "キーボード中クリック",
"KEYBOARD_MIDDLE_CLICK_HELP": "紫色のレーザーで\n入力する際の修飾キー",
"KEYBOARD_SOUND_ENABLED": "キーボード入力音",
"LANGUAGE": "言語",
"LEFT_HANDED_MOUSE": "左利きマウス",
"LEFT_HANDED_MOUSE_HELP": "マウスボタンを入れ替えて使用する場合にチェック",
"LONG_PRESS_DURATION": "長押し時間",
"LOOK_AND_FEEL": "外観と操作感",
"MISC": "その他",
"NOTIFICATIONS_ENABLED": "通知を有効にする",
"NOTIFICATIONS_SOUND_ENABLED": "通知音",
"NOT_SUPPORTED": "非対応",
"NO_SKYMAPS_FOUND": "スカイマップが見つかりません",
"OPAQUE_BACKGROUND": "不透明な背景",
"OPTION": {
"ANCHORED_HELP": "センターマーカーと共に移動。推奨。",
"FLOATING_HELP": "独立して移動し、中心位置を再設定する。\n紛失しやすいため、あまり推奨されない。",
"STATIC_HELP": "ワールド基準で固定される。",
"AUTO": "自動",
"AUTO_HELP": "対応していればScreenCopy GPUを、\nそうでなければPipeWire GPUを使用。",
"EYE_ONLY": "視線レーザー",
"EYE_PINCH": "視線 + ピンチ",
"HMD_ONLY": "HMDレーザー",
"HMD_PINCH": "HMD + ピンチ",
"NONE": "なし",
"NONE_INPUT_HELP": "マウスとキーボードをエミュレートしない。\n画面とのインタラクトができなくなる。",
"NONE_INPUT_CAPTURE_HELP": "マウスとキーボードをキャプチャしない。\nWayVR内で起動したアプリで物理マウスや\nキーボードが使用できなくなる。",
"PIPEWIRE_HELP": "高速なGPUキャプチャ。\nデスクトップの標準的な方式。",
"PW_FALLBACK_HELP": "CPU負荷が高い低速な方式。\nPipeWire GPUが動作しない場合に試行すること",
"SCREENCOPY_GPU_HELP": "高速で、画面共有のポップアップが表示されない。\n対応Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "低速だが、画面共有のポップアップが出ない。\n対応: Hyprland, Niri, River, Sway",
"UINPUT": "デバイスエミュレーション",
"UINPUT_HELP": "uinputモジュールを使用してデバイスをエミュレートします。\nほとんどのデスクトップ環境で良好に動作します。",
"EVDEV_HELP": "入力デバイスを排他的に使用する。\nユーザーが input グループに属している必要がある。",
"WL_VIRTUAL": "Wayland仮想入力",
"WL_VIRTUAL_HELP": "zwlr_virtual_pointer と zwp_virtual_keyboard を使用して\nWayland コンポジターにイベントを送信する。\nデスクトップ環境によって安定性が異なり、\nKDE、GNOME、COSMIC では動作しない。"
},
"POINTER_ACCELERATION": "マウス加速",
"POINTER_ACCELERATION_HELP": "オン: 適応型マウス加速\nオフ: 等速",
"POINTER_LERP_FACTOR": "ポインタの平滑化",
"POINTER_SPEED": "マウス速度",
"REQUIRES_RESTART": "要再起動",
"RESET_PLAYSPACE": "プレイスペースをリセット",
"RESET_PLAYSPACE_HELP": "プレイスペースのオフセットをリセットする。",
"SAVE_PLAYSPACE_CENTER": "プレイスペースの中心を保存",
"SAVE_PLAYSPACE_CENTER_HELP": "現在のプレイスペースを、プレイスペースリセットのバインディングに使用する。",
"RESET_PLAYSPACE_CENTER": "プレイスペースの中心をリセット",
"RESET_PLAYSPACE_CENTER_HELP": "設定済みのプレイスペースの中心点をリセットする。",
"RESTART_SOFTWARE": "ソフトウェアを再起動",
"RESTART_SOFTWARE_HELP": "再起動が必要な設定を適用する",
"ROUND_MULTIPLIER": "UIの角の丸み",
"SCREEN_RENDER_DOWN": "低解像度で画面をレンダリング",
"SCREEN_RENDER_DOWN_HELP": "高解像度ディスプレイでのジャギーを軽減する",
"SCROLL_SPEED": "スクロール速度",
"SELECT_VARIANT": "バリアントを選択",
"SNAP_ANGLE_DEG": "ウィンドウのピッチ・ロール吸着角",
"SNAP_ANGLE_DEG_HELP": "掴んでいるウィンドウが、ピッチ軸とロール軸でこの角度にスナップします。",
"ENABLE_WATCH": "ウォッチを有効にする",
"SETS_ON_WATCH": "ウォッチにセットを表示",
"SHOW_WELCOME_SCREEN": "ウェルカムスクリーンを表示",
"SKYBOX": "スカイマップ",
"SKYMAP_ALREADY_DOWNLOADED": "このスカイマップはすでにダウンロード済みです。操作を選択してください。",
"SPACE_DRAG": "プレイスペース",
"SPACE_DRAG_MULTIPLIER": "プレイスペース移動倍率",
"SPACE_DRAG_AFFECTS_WORLD": "プレイスペース移動時にオーバーレイをその場に残す",
"SPACE_DRAG_UNLOCKED": "全軸でスペースドラッグを許可",
"SPACE_GRAVITY_DAMPING": "減衰",
"SPACE_GRAVITY_DAMPING_HELP": "動きを緩やかにする擬似的な抵抗。0.1抵抗大、1.0:抵抗なし",
"SPACE_GRAVITY_FLING_STRENGTH": "弾き飛ばし強度",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "スペースドラッグ後の重力投射の強度倍率。\n0.0動きなし、2.0強度2倍",
"SPACE_GRAVITY_GRAVITY": "重力",
"SPACE_GRAVITY_GRAVITY_HELP": "下向きの力の強さ。0.0は無重力",
"SPACE_GRAVITY_GROUND_FRICTION": "接地摩擦",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "接地時の摩擦量。\n0.0 - 摩擦なし氷の上のように、1.0 - 粗い表面",
"SPACE_GRAVITY_FLOOR_HEIGHT": "床の高さ",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "床のY軸位置。この高さに達すると重力による落下が止まる。",
"SPACE_ROTATE_UNLOCKED": "全軸でのプレイスペース回転を許可",
"TROUBLESHOOTING": "トラブルシューティング",
"UI_GRADIENT_INTENSITY": "UIグラデーションの強度",
"UPRIGHT_SCREEN_FIX": "画面直立補正",
"UPRIGHT_SCREEN_FIX_HELP": "一部のデスクトップで画面の向きを垂直に固定する",
"USE_PASSTHROUGH": "パススルーを有効にする",
"USE_PASSTHROUGH_HELP": "XRランタイムが対応している場合、パススルーを有効にする",
"USE_SKYBOX": "スカイマップを表示",
"USE_SKYBOX_HELP": "シーンアプリやパススルーがない場合にスカイマップを表示する",
"WATCH_VIEW_ANGLE": "ウォッチの表示角度",
"WATCH_VIEW_ANGLE_HELP": "ウォッチが消えていくタイミングを調整",
"WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "選択したモデルをダウンロードする必要があります。\n今すぐダウンロードしますか",
"REMOVE_UNUSED_MODELS": "音声入力機能をオフにします。\n空き容量を増やすため、ダウンロード済みのWhisperモデルを削除しますか"
},
"WHISPER_MODEL": "音声認識モデル",
"WHISPER_MODEL_HELP": "使用するWhisperモデルを選択。\nモデルが大きいほど精度は向上するが、\nVRAMの消費量が増える。",
"GRID_OPACITY": "フロアグリッドの不透明度",
"GRID_OPACITY_HELP": "スカイマップ有効時のフロアグリッドの不透明度",
"XWAYLAND_BY_DEFAULT": "デフォルトで互換モードでアプリを起動",
"SAVE": "保存",
"CANCEL": "キャンセル"
}, },
"HELLO": "こんにちは!", "APPLICATION_LAUNCHER": "アプリランチャー",
"APPLICATION_STARTED": "アプリが起動しました",
"APPLICATIONS": "アプリ",
"AUDIO": { "AUDIO": {
"VOLUME": "音量", "AUTO_SWITCH_TO_VR_AUDIO": "VRオーディオへ自動切り替え",
"SETTINGS": "オーディオ設定", "CARDS": "サウンドカード",
"AUTO_SWITCH_TO_VR_AUDIO": "VRオーディオに自動切り替え",
"SPEAKERS": "スピーカー",
"MICROPHONES": "マイク",
"CARDS": "カード",
"SELECT_AUDIO_CARD_PROFILE": "オーディオカードプロファイルを選択",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "VRスピーカーが見つかりませんでした。手動で切り替えてください。",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "VRマイクが見つかりませんでした。手動で切り替えてください。",
"FAILED_TO_SWITCH_MICROPHONE": "マイクの切り替えに失敗しました", "FAILED_TO_SWITCH_MICROPHONE": "マイクの切り替えに失敗しました",
"MICROPHONE_SET_SUCCESSFULLY": "マイクの設定が完了しました", "MICROPHONE_SET_SUCCESSFULLY": "マイクを設定しました",
"SPEAKERS_SET_SUCCESSFULLY": "スピーカーを設定しました" "MICROPHONES": "マイク",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "VRマイクが見つかりません。手動で切り替えてください。",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "VRスピーカーが見つかりませんでした。手動で切り替えてください。",
"SELECT_AUDIO_CARD_PROFILE": "オーディオカードプロファイルを選択",
"SETTINGS": "オーディオ設定",
"SPEAKERS": "スピーカー",
"SPEAKERS_SET_SUCCESSFULLY": "スピーカーを設定完了",
"VOLUME": "音量"
}, },
"ACTIONS": { "CLOSE_WINDOW": "ウィンドウを閉じる",
"RECENTER_PLAYSPACE": "プレイスペースを再中央" "CREATION_DATE": "作成日",
"DEBUG_INFO": "デバッグ情報",
"DISPLAY_BRIGHTNESS": "ディスプレイの明るさ",
"DONATE": {
"SUPPORT_US": "支援する",
"DESCRIPTION": "WayVRは、2人の開発者が空き時間を利用して作っている小規模なプロジェクトです。もしこのソフトを気に入っていただけたら、ぜひサポートをお願いします。皆様の寄付が開発の大きな励みになります。",
"THANK_YOU_WAYVR": "WayVRチームより、感謝を込めて",
"BUTTON_TOOLTIP": "Open Collectiveで寄付する",
"CURRENT_SUPPORTERS": "現在のサポーター",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "{USER}さんにサポートされています|{USER}さんに感謝!|{USER}さんのご支援で成り立っています|{USER}さんが支えてくれています|{USER}さんの後押しのおかげです|{USER}さんが後援しています|{USER}さんのご協力に感謝|{USER}さんが応援してくれています|本日のサポーターは{USER}さんです",
"BROUGHT_TO_YOU_VARIANTS_RARE": "{USER}さんの優しさに感謝|{USER}さんが背中を押してくれました|{USER}さんの心強いサポート|{USER}さんが彩りを添えてくれました|{USER}さんのおかげで前進しています|{USER}さんの温かいご支援|{USER}さんが笑顔を届けてくれました|{USER}さんが道を照らしてくれました|{USER}さんに心から感謝して",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "今日のMVPは{USER}さん!|{USER}さんが神降臨!|{USER}さんが限界突破させてくれた!|{USER}さんのパワーで爆走中!|救世主、現る:{USER}さん!|{USER}さんが文明を支えています|{USER}さんの情熱が燃料です!|本日のスーパーヒーロー:{USER}さん!|{USER}さんがバグをなぎ倒してくれた!|{USER}さんの応援でテンションMAX|全宇宙から{USER}さんに拍手を!"
}, },
"DOWNLOAD": "ダウンロード",
"DOWNLOADER": "ダウンローダー",
"WELCOME": {
"ALL_SET": "準備完了!",
"BASICS": "これらの基本を抑えれば、簡単にWayVRを使い始めることができる。",
"CENTER_MARKER": "センターマーカーはリセンタリング時に目の前に現れる印だ。この周りにオーバーレイを配置しよう!",
"DOUBLE_PRESS_TO_TOGGLE": "セットの表示、再中心化、または非表示にするには、BボタンIndexまたはYボタンMetaをダブルプレスして下さい。今すぐ試してみよう。",
"FEATURES_DOCUMENTATION": "他にもカスタマイズ次第で多くの機能が活用できます。詳細はドキュメントを確認してください:",
"FINISH_TUTORIAL": "チュートリアルを終了",
"GRAB_BOTH_HANDS": "セット内の特定のオーバーレイを移動させるには、両手で掴んでください。",
"GRAB_ONE_HAND": "片手で掴んでセットを移動させよう。",
"GREETING": "ようこそ!",
"GUIDE_INTRO": "まずは基本操作から案内する。",
"LASER_COLORS": "レーザーの色",
"LASER_FUNCTIONALITY": "WayVRの機能の多くは、UI要素を操作するレーザーの色によって決まります。ボタンを押し込む必要はなく、軽く触れるだけで操作可能です",
"LAST_PAGE_INFO": "最終ページに到達すると、このチュートリアルは表示されなくなります。",
"LOOK_AT_LEFT_WRIST": "左手首を見てください。それがあなたのウォッチです。",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "中クリックモード:紫色のレーザー",
"MOVING_YOUR_SET": "セットの移動",
"NEXT_BUTTON": "下の「次へ」ボタンを押して開始してください。",
"REGULAR_MODE_BLUE_LASER": "通常モード:青色レーザー",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "コントローラーのグリップボタンでこのウィンドウを移動させる。",
"RIGHT_CLICK_MODE_ORANGE_LASER": "右クリックモード:オレンジ色のレーザー",
"THANKS_FOR_INSTALLING": "WayVRをインストールしてくれてありがとう",
"WATCH": "ウォッチ",
"WORKING_SET": "使用中のセット"
},
"DOWNLOAD_AGAIN": "再ダウンロード",
"DOWNLOADING_FILE": "ファイルをダウンロード中...",
"FAILED_TO_LAUNCH_APPLICATION": "アプリケーションの起動に失敗しました:",
"GAME_LAUNCHED": "ゲームを起動しました",
"GAME_LIST": {
"NO_GAMES_FOUND": "ゲームが見つかりません",
"RUNNING_GAMES_LIST": "実行中のゲーム一覧"
},
"GAMES": "ゲーム",
"GENERAL_SETTINGS": "一般設定",
"GETTING_STARTED": "はじめに",
"HEIGHT": "高さ",
"HELLO": "こんにちは!",
"HELLO_USER": "こんにちは、{USER}",
"HIDE": "非表示",
"HOME_SCREEN": "ホーム",
"MODIFICATION_DATE": "更新日",
"MONADO_RUNTIME": "Monado ランタイム",
"LOADING": "読み込み中...",
"POPUP_ADD_DISPLAY": { "POPUP_ADD_DISPLAY": {
"RESOLUTION": "解像度" "RESOLUTION": "解像度"
}, },
"WIDTH": "幅", "PROCESS": {
"HEIGHT": "高さ", "FORCE_KILL": "強制終了",
"HIDE": "隠す", "STOP": "停止"
"REMOVE": "削除",
"SHOW": "表示",
"FAILED_TO_LAUNCH_APPLICATION": "アプリケーションの起動に失敗しました:",
"APPLICATION_STARTED": "アプリケーションが起動しました",
"CLOSE_WINDOW": "ウィンドウを閉じる",
"GAME_LIST": {
"NO_GAMES_FOUND": "ゲームが見つかりませんでした",
"RUNNING_GAMES_LIST": "実行中のゲーム一覧"
}, },
"TERMINATE_PROCESS": "プロセスを終了する",
"GAME_LAUNCHED": "ゲームが起動しました",
"APP_LAUNCHER": {
"MODE": {
"NATIVE": "ネイティブモード",
"CAGE": "互換モードCage"
},
"RES_TITLE": "解像度",
"ASPECT_TITLE": "アスペクト",
"ASPECT": {
"WIDE": "ワイド",
"SEMI_WIDE": "半広角",
"SQUARE": "正方形",
"SEMI_TALL": "半縦長",
"TALL": "縦長"
},
"POS_TITLE": "配置",
"POS": {
"FLOATING": "フローティング",
"ANCHORED": "固定",
"STATIC": "固定",
"FLOATING_HELP": "独立して移動し、表示時に中央に再配置されます。",
"ANCHORED_HELP": "中央マーカーに対して固定された位置に留まります。",
"STATIC_HELP": "どのセットにも属していません。リセンターされません。"
},
"AUTOSTART": "起動時に自動実行",
"LAUNCH": "起動"
},
"DISPLAY_BRIGHTNESS": "ディスプレイの明るさ",
"PROCESS_LIST": "プロセスリスト", "PROCESS_LIST": "プロセスリスト",
"REFRESH": "更新", "REFRESH": "更新",
"PROCESS": { "REMOVE": "削除",
"STOP": "停止",
"FORCE_KILL": "強制終了"
},
"DEBUG_INFO": "デバッグ情報",
"CREATION_DATE": "作成日",
"DOWNLOADER": "ダウンローダー",
"DOWNLOAD_AGAIN": "再ダウンロード",
"DOWNLOADING_FILE": "ファイルをダウンロード中...",
"GETTING_STARTED": "はじめに",
"MODIFICATION_DATE": "更新日",
"LOADING": "読み込み中...",
"APPLY": "適用", "APPLY": "適用",
"RELOAD_FROM_DISK": "ディスクからリロード", "RELOAD_FROM_DISK": "ディスクから再読み込み",
"TARGET_PATH": "ターゲットパス", "SETTINGS": "設定",
"SHOW": "表示",
"TARGET_PATH": "保存先パス",
"TERMINATE_PROCESS": "プロセスを終了",
"VERSION": "バージョン", "VERSION": "バージョン",
"DONATE": { "WIDTH": "幅",
"SUPPORT_US": "私たちを支援する", "PINNED_APPS": "固定済みアプリ",
"DESCRIPTION": "私たちは、空き時間にWayVRを開発している2人の開発者からなる小さなチームです。もしこのソフトウェアを気に入っていただけたなら、ぜひ支援をご検討ください。皆様からの寄付は、開発を継続していくための大きな助けとなります。", "SAVED_TO_FAVOURITES": "固定済みアプリに保存した",
"BUTTON_TOOLTIP": "Open Collectiveで寄付する", "ADD_TO_FAVOURITES": "固定済みアプリに追加",
"CURRENT_SUPPORTERS": "現在のサポーター", "ADD_TO_FAVOURITES_HINT": "プリセットを保存し、アプリドロワーに固定する",
"THANK_YOU_WAYVR": "WayVRチーム一同より、感謝を込めて" "REMOVE_FROM_FAVOURITES": "固定済みアプリから外す",
}, "EMPTY": "なし"
"WELCOME": {
"ALL_SET": "準備完了です!",
"BASICS": "これらの基本操作を学ぶことで、WayVRを簡単に使い始めることができます。",
"FEATURES_DOCUMENTATION": "他にもカスタマイズする価値のある機能がたくさんあります。詳細については、以下のドキュメントを確認してください。",
"FINISH_TUTORIAL": "チュートリアルを終了する",
"GRAB_BOTH_HANDS": "セット内の特定のオーバーレイを移動させたい場合は、両手で掴んでください。",
"GRAB_ONE_HAND": "片手で掴んでセットを移動させます。",
"GREETING": "こんにちは!",
"GUIDE_INTRO": "最初の手順をご案内します。",
"LASER_COLORS": "レーザーの色",
"LASER_FUNCTIONALITY": "WayVRの機能の多くは、UI要素を操作する際に使用されるレーザーの色に依存しています。これらのボタンは押す必要はなく、ただ触れるだけで操作できます",
"LAST_PAGE_INFO": "最後のページに到達すると、このチュートリアルは表示されなくなります。",
"LOOK_AT_LEFT_WRIST": "左手首を見てください。それがあなたのWatchです。",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— ミドルクリックモード:紫色のレーザー",
"MOVING_YOUR_SET": "セットを移動中",
"NEXT_BUTTON": "「次へ」ボタンを押して開始してください。",
"REGULAR_MODE_BLUE_LASER": "— 通常モード: ブルーレーザー",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "コントローラーのグリップアクションを使用して、このウィンドウの位置を再設定します。",
"RIGHT_CLICK_MODE_ORANGE_LASER": "— 右クリックモード:オレンジ色のレーザー",
"THANKS_FOR_INSTALLING": "WayVRをインストールしていただきありがとうございます",
"WATCH": "Watch",
"WORKING_SET": "ワーキングセット",
"DOUBLE_PRESS_TO_TOGGLE": "BボタンIndexまたはYボタンMetaを2回押して、セットの表示・中心合わせ・非表示を切り替えてください。今すぐ試してみましょう。",
"CENTER_MARKER": "リセンタリング時に目の前に表示されるのがセンターマーカーです。このマーカーを中心にオーバーレイを配置してください!"
},
"DOWNLOAD": "ダウンロード",
"SAVED_TO_FAVOURITES": "お気に入りに保存しました",
"ADD_TO_FAVOURITES": "お気に入りに追加",
"ADD_TO_FAVOURITES_HINT": "プリセットを保存してアプリドロワーにピン留めします",
"REMOVE_FROM_FAVOURITES": "お気に入りから削除",
"EMPTY": "空",
"PINNED_APPS": "ピン留めされたアプリケーション"
} }

View File

@ -1,110 +1,56 @@
{ {
"DEFINITIONS": {
"ANCHORED": "Przytwierdzone",
"FLOATING": "Pływający",
"STATIC": "Stacjonarny",
"SET": "Zestaw",
"WATCH": "Zegarek",
"DASHBOARD": "Panel sterowania",
"EDIT_MODE": "Tryb edycji",
"SETTINGS": "Ustawienia",
"KEYBOARD": "Klawiatura",
"TASKBAR": "Pasek zadań",
"FEATURES": "Funkcje",
"OVERLAY": "Nakładka",
"SKYMAP": "Skymap",
"PLAYSPACE": "Przestrzeń gry",
"D_PAD": "D-pad"
},
"ACTIONS": { "ACTIONS": {
"RECENTER_PLAYSPACE": "Wycentruj przestrzeń" "RECENTER_PLAYSPACE": "Resetuj centrum przestrzeni gry"
},
"APP_LAUNCHER": {
"ASPECT": {
"SEMI_TALL": "Półwysoki",
"SEMI_WIDE": "Półszeroki",
"SQUARE": "Kwadratowy",
"TALL": "W pionie",
"WIDE": "Szeroki"
},
"ASPECT_TITLE": "Proporcje",
"AUTOSTART": "Uruchamiaj automatycznie przy starcie",
"LAUNCH": "Uruchom",
"MODE": {
"CAGE": "Tryb kompatybilności (Cage)",
"NATIVE": "Tryb natywny"
},
"RES_TITLE": "Rozdzielczość"
}, },
"APP_SETTINGS": { "APP_SETTINGS": {
"HIDE_USERNAME": "Ukryj nazwę użytkownika", "ALLOW_SLIDING": "Interakcja drążkiem podczas przesuwania",
"OPAQUE_BACKGROUND": "Nieprzezroczyste tło",
"LOOK_AND_FEEL": "Wygląd i działanie",
"HIDE_GRAB_HELP": "Ukryj pomoc dotyczącą chwytania",
"ANIMATION_SPEED": "Prędkość animacji UI", "ANIMATION_SPEED": "Prędkość animacji UI",
"ROUND_MULTIPLIER": "Zaokrąglenie krawędzi UI", "AUTOSTART_APPS": "Aplikacje uruchamiane przy starcie",
"USE_SKYBOX": "Włącz niebo", "BLOCK_GAME_INPUT": "Blokuj wejście do gry",
"USE_PASSTHROUGH": "Włącz passthrough", "BLOCK_GAME_INPUT_HELP": "Blokuje wszystkie wejścia, gdy kursor znajduje się nad nakładką",
"CLOCK_12H": "Zegar 12-godzinny", "BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignoruj zegarek przy blokowaniu wejścia",
"FEATURES": "Funkcje", "BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Nie blokuj wejścia podczas najechania na zegarek",
"NOTIFICATIONS_ENABLED": "Włącz powiadomienia", "BLOCK_POSES_ON_KBD_INTERACTION": "Blokuj pozę podczas interakcji z klawiaturą",
"NOTIFICATIONS_SOUND_ENABLED": "Dźwięki powiadomień", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Blokuje przesyłanie pozycji do gry, gdy kursor znajduje się nad klawiaturą, a opcja „Blokuj wejście do gry” jest włączona",
"KEYBOARD_SOUND_ENABLED": "Dźwięki klawiatury",
"SPACE_DRAG_MULTIPLIER": "Mnożnik przesuwania przestrzeni",
"SPACE_DRAG_UNLOCKED": "Pozwól na przesuwanie przestrzeni na wszystkich osiach",
"SPACE_ROTATE_UNLOCKED": "Pozwól na rotację przestrzeni na wszystkich osiach",
"BLOCK_GAME_INPUT": "Blokuj input z gry",
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Nie blokuj inputu gry, gdy zegarek jest używany",
"CONTROLS": "Sterowanie",
"FOCUS_FOLLOWS_MOUSE_MODE": "Ruch myszą po dotknięciu spustu",
"LEFT_HANDED_MOUSE": "Myszka dla leworęcznych",
"ALLOW_SLIDING": "Interakcja z drążkami podczas chwytania",
"INVERT_SCROLL_DIRECTION_X": "Odwróć kierunek przewijania w poziomie",
"INVERT_SCROLL_DIRECTION_Y": "Odwróć kierunek przewijania w pionie",
"SCROLL_SPEED": "Prędkość przewijania",
"LONG_PRESS_DURATION": "Czas długiego przytrzymania",
"POINTER_LERP_FACTOR": "Wygładzanie wskaźnika",
"CLICK_FREEZE_TIME_MS": "Czas zamrożenia po kliknięciu (ms)",
"XWAYLAND_BY_DEFAULT": "Uruchamiaj aplikacje domyślnie w trybie kompatybilności",
"UPRIGHT_SCREEN_FIX": "Naprawa pozycji ekranu",
"DOUBLE_CURSOR_FIX": "Naprawa podwójnego kursora",
"SCREEN_RENDER_DOWN": "Renderuj ekran w niższej rozdzielczości",
"UPRIGHT_SCREEN_FIX_HELP": "Naprawia pionowe ekrany na niektórych komputerach",
"DOUBLE_CURSOR_FIX_HELP": "Włącz to, jeśli widzisz 2 kursory",
"CLICK_FREEZE_TIME_MS_HELP": "Pomaga w precyzji podwójnego kliknięcia",
"LEFT_HANDED_MOUSE_HELP": "Użyj tego, jeśli przyciski myszy są zamienione",
"BLOCK_GAME_INPUT_HELP": "Blokuje wszystkie dane wejściowe, gdy kursor najedzie na nakładkę",
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "Nie blokuj inputu, gdy wskaźnik jest najedzony",
"USE_SKYBOX_HELP": "Wyświetlaj niebo, jeśli nie ma aplikacji sceny lub passthrough",
"USE_PASSTHROUGH_HELP": "Pozwól na passthrough, jeśli runtime XR to obsługuje",
"SCREEN_RENDER_DOWN_HELP": "Pomaga redukować aliasing na ekranach o wysokiej rozdzielczości",
"ENABLE_WATCH": "Włącz zegarek",
"SETS_ON_WATCH": "Lista zestawów na zegarku",
"TROUBLESHOOTING": "Rozwiązywanie problemów",
"CLEAR_SAVED_STATE": "Wyczyść zapisany stan",
"CLEAR_PIPEWIRE_TOKENS": "Wyczyść tokeny PipeWire",
"DELETE_ALL_CONFIGS": "Wyczyść konfigurację",
"RESTART_SOFTWARE": "Restartuj WayVR",
"CLEAR_SAVED_STATE_HELP": "Zresetuj zestawy i pozycje nakładek",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Zapytaj o wybór ekranu przy następnym uruchomieniu",
"DELETE_ALL_CONFIGS_HELP": "Usuń wszystkie pliki konfiguracyjne z katalogu conf.d",
"RESTART_SOFTWARE_HELP": "Zastosuj ustawienia wymagające ponownego uruchomienia",
"CAPTURE_METHOD": "Przechwytywanie ekranu Wayland",
"CAPTURE_METHOD_HELP": "Spróbuj zmienić tę opcję, jeśli masz\nproblemy z czarnym lub migoczącym ekranem",
"KEYBOARD_MIDDLE_CLICK": "Środkowy przycisk myszy na klawiaturze",
"KEYBOARD_MIDDLE_CLICK_HELP": "Modyfikator, który ma zostać użyty podczas pisania\nfioletową wiązką lasera",
"OPTION": {
"AUTO": "Automatycznie",
"AUTO_HELP": "Skopiuj ekran za pomocą GPU, jeśli obsługiwane,\nw przeciwnym razie GPU PipeWire.",
"PIPEWIRE_HELP": "Szybkie przechwytywanie GPU,\nstandard na wszystkich komputerach.",
"PW_FALLBACK_HELP": "Powolna metoda z wysokim użyciem procesora.\nWypróbuj w przypadku, gdy PipeWire GPU nie działa",
"SCREENCOPY_GPU_HELP": "Szybkie działanie, brak wyskakujących okien z informacją o udostępnianiu ekranu.\nDziała na: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Wolne, bez wyskakujących okienek udostępniania ekranu.\nDziała na: Hyprland, Niri, River, Sway",
"NONE": "Brak",
"HMD_PINCH": "HMD + ściśnięcie placami",
"EYE_PINCH": "Ściśnięcie palcami + oko",
"EYE_ONLY": "Tylko oko",
"HMD_ONLY": "Tylko HMD",
"NONE_INPUT_HELP": "Nie emuluj myszy ani klawiatury.\nBrak możliwości interakcji z ekranami.",
"UINPUT": "Emulacja urządzenia",
"UINPUT_HELP": "Używa modułu uinput do emulowania urządzenia.\nTwoje konto użytkownika musi należeć do grupy input.\nWiadomo, że działa dobrze na większości komputerów stacjonarnych.",
"WL_VIRTUAL": "Wirtualne wejście Wayland",
"WL_VIRTUAL_HELP": "Wysyłaj wejście myszki/klawiatury do kompozytora Wayland za pomocą\nzwlr_virtual_pointer i zwp_virtual_keyboard.\nDziała niezawodnie tylko na niektórych pulpitach.\nNIE działa na KDE, GNOME ani COSMIC."
},
"AUTOSTART_APPS": "Aplikacje auto-start",
"HANDSFREE_POINTER": "Tryb bez użycia rąk",
"HANDSFREE_POINTER_HELP": "Wejście do użycia, gdy kontrolery ruchu\nsą niedostępne. Lewy szczyptak to chwyt,\nprawy to kliknięcie.",
"UI_GRADIENT_INTENSITY": "Intensywność gradientu UI",
"RESET_PLAYSPACE": "Zresetuj przestrzeń gry",
"RESET_PLAYSPACE_HELP": "Wyczyść przesunięcie przestrzeni gry.",
"BLOCK_POSES_ON_KBD_INTERACTION": "Blokuj pozy podczas interakcji z klawiaturą",
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "Blokuje odbieranie póz przez grę, gdy kursor myszy znajduje się nad klawiaturą i włączona jest opcja 'Blokuj dane wejściowe z gry'",
"LANGUAGE": "Język",
"REQUIRES_RESTART": "Wymaga restartu",
"MISC": "Różne",
"GRID_OPACITY": "Przezroczystość siatki podłogowej",
"GRID_OPACITY_HELP": "Przezroczystość siatki podłogowej, gdy włączony jest skybox",
"BROWSE_ONLINE_CATALOG": "Przeglądaj katalog online...",
"BROWSE_SKYMAPS": "Przeglądaj skymaps",
"COLOR_KEYING": "Kluczowanie kolorem",
"NO_SKYMAPS_FOUND": "Nie znaleziono skymap",
"SELECT_VARIANT": "Wybierz wariant",
"SHOW_WELCOME_SCREEN": "Pokaż ekran powitalny",
"SKYBOX": "Skymap",
"SKYMAP_ALREADY_DOWNLOADED": "Ta skymapa została już pobrana. Wybierz żądaną akcję.",
"WATCH_VIEW_ANGLE": "Kąty widzenia Watch",
"WATCH_VIEW_ANGLE_HELP": "Kontroluj, jak zegarek zanika",
"BINDINGS": { "BINDINGS": {
"COMP": { "COMP": {
"CLICK": "Kliknięcie", "CLICK": "Kliknięcie",
"FORCE": "Siła", "FORCE": "Siła nacisku",
"TOUCH": "Dotyk", "TOUCH": "Dotknięcie",
"VALUE": "Wartość", "VALUE": "Wartość",
"PROXIMITY": "Bliskość", "PROXIMITY": "Bliskość",
"X_AXIS": "Oś X", "X_AXIS": "Oś X",
@ -112,20 +58,20 @@
}, },
"TYPE": { "TYPE": {
"BUMPER": "Bumper", "BUMPER": "Bumper",
"DPAD_UP": "D-pad w górę", "DPAD_UP": "D-pad góra",
"DPAD_DOWN": "D-pad w dół", "DPAD_DOWN": "D-pad dół",
"DPAD_LEFT": "D-pad w lewo", "DPAD_LEFT": "D-pad lewo",
"DPAD_RIGHT": "D-pad w prawo", "DPAD_RIGHT": "D-pad prawo",
"JOYSTICK": "Joystick", "JOYSTICK": "Drążek",
"MENU": "Menu", "MENU": "Menu",
"SHOULDER": "Boczny przycisk", "SHOULDER": "Ramiona",
"SQUEEZE": "Chwyt", "SQUEEZE": "Chwyt",
"SYSTEM": "System", "SYSTEM": "System",
"THUMBREST": "Thumbrest", "THUMBREST": "Podpora kciuka",
"THUMBSTICK": "Thumbstick", "THUMBSTICK": "Thumbstick",
"TRACKPAD": "Trackpad", "TRACKPAD": "Gładzik",
"TRIGGER": "Spust", "TRIGGER": "Spust",
"VIEW": "Widok" "VIEW": "View"
}, },
"CLICK": { "CLICK": {
"ANY": "Dowolny", "ANY": "Dowolny",
@ -135,184 +81,269 @@
}, },
"ACTION": { "ACTION": {
"CLICK": "Kliknięcie*", "CLICK": "Kliknięcie*",
"GRAB": "Chwyć*", "GRAB": "Chwytanie*",
"ALT_CLICK": "Własne polecenie shell exec (ustaw alt_click w konfiguracji)", "ALT_CLICK": "Własna komenda shell (ustaw alt_click w konfiguracji)",
"SHOW_HIDE": "Pokaż, ukryj, wycentruj ponownie*", "SHOW_HIDE": "Pokaż, ukryj, wycentruj*",
"TOGGLE_DASHBOARD": "Przełącz dashboard", "TOGGLE_DASHBOARD": "Przełącz pulpit",
"SPACE_DRAG": "Przesuwanie Playspace", "SPACE_DRAG": "Przeciąganie przestrzeni gry",
"SPACE_ROTATE": "Obrót Playspace", "SPACE_ROTATE": "Obrót przestrzeni gry",
"SPACE_RESET": "Resetowanie playspace", "SPACE_RESET": "Reset przestrzeni gry",
"CLICK_MODIFIER_RIGHT": "Modyfikator prawego kliknięcia", "CLICK_MODIFIER_RIGHT": "Modyfikator prawego kliknięcia",
"CLICK_MODIFIER_MIDDLE": "Modyfikator środkowego kliknięcia", "CLICK_MODIFIER_MIDDLE": "Modyfikator środkowego przycisku myszy",
"MOVE_MOUSE": "Ruszaj myszą (jeśli domyślnie wyłączone)", "MOVE_MOUSE": "Przesuń mysz (jeśli domyślnie wyłączona)",
"SCROLL": "Przewijanie*" "SCROLL": "Przewijanie*"
}, },
"LEFT": "Lewy", "LEFT": "Lewy",
"RIGHT": "Prawy", "RIGHT": "Prawy",
"COMPONENT": "Typ aktywacji", "COMPONENT": "Typ aktywacji",
"SUBPATH": "Sterowanie aktywacją", "SUBPATH": "Aktywujący sterownik",
"THRESHOLD": "Aktywuj po przekroczeniu górnej wartości\nDezaktywuj po spadku poniżej dolnej wartości" "THRESHOLD": "Aktywuj powyżej górnej wartości\nDeaktywuj poniżej dolnej wartości"
}, },
"BROWSE_ONLINE_CATALOG": "Przeglądaj katalog online...",
"BROWSE_SKYMAPS": "Przeglądaj skymapy",
"CAPTURE_METHOD": "Metoda przechwytywania ekranu",
"CAPTURE_METHOD_HELP": "Spróbuj zmienić tę opcję, jeśli \nekran jest czarny lub migocze",
"COLOR_KEYING": "Kluczowanie koloru",
"COLOR_PALETTE": "Paleta kolorów",
"COLOR_PALETTE_HELP": "Kliknij, aby przeglądać palety kolorów.\nAby stworzyć własne, odwiedź stronę internetową!",
"COLOR_PALETTES": "Palety kolorów",
"COLOR_PALETTE_CURRENT": "Aktualnie aktywny motyw.",
"COLOR_PALETTE_CUSTOM_URL": "Dodaj własny motyw!",
"COLOR_PALETTE_CUSTOM_URL2": "Kliknij, aby otworzyć podręcznik online.",
"COLOR_PALETTE_ACTIVATE": "Kliknij, aby użyć tego motywu.",
"CLEAR_PIPEWIRE_TOKENS": "Wyczyść tokeny PipeWire",
"CLEAR_PIPEWIRE_TOKENS_HELP": "Zapytaj o wybór ekranu przy następnym uruchomieniu",
"CLEAR_SAVED_STATE": "Wyczyść zapisany stan",
"CLEAR_SAVED_STATE_HELP": "Zresetuj zestawy i pozycje nakładek",
"CLICK_FREEZE_TIME_MS": "Czas zamrożenia kliknięcia (ms)",
"CLICK_FREEZE_TIME_MS_HELP": "Ułatwia precyzję dwukliku",
"CLOCK_12H": "Zegar 12-godzinny",
"CONTROLS": "Sterowanie",
"DELETE_ALL_CONFIGS": "Wyczyść konfigurację",
"DELETE_ALL_CONFIGS_HELP": "Usuń wszystkie pliki konfiguracyjne z conf.d",
"DOUBLE_CURSOR_FIX": "Poprawka podwójnego kursora",
"DOUBLE_CURSOR_FIX_HELP": "Włącz, jeśli widzisz dwa kursory",
"DEFAULT_OVERLAY_SCALE": "Domyślny rozmiar nakładki",
"DEFAULT_OVERLAY_SCALE_HELP": "Twórz nowe nakładki w tej skali.",
"DEFAULT_CURVATURE": "Domyślna krzywizna nakładki",
"DEFAULT_OPACITY": "Domyślna przezroczystość nakładki",
"DEFAULT_POSITIONING": "Domyślne pozycjonowanie nakładki",
"OVERLAY_DEFAULTS_HELP": "Dotyczy tylko nowych nakładek",
"ENABLED": "Włączone", "ENABLED": "Włączone",
"FEATURES": "Funkcje",
"FOCUS_FOLLOWS_MOUSE_MODE": "Kursor podąża za spustem",
"HANDSFREE_POINTER": "Tryb bezkontaktowy",
"HANDSFREE_POINTER_HELP": "Metoda sterowania, gdy kontrolery ruchu są niedostępne.\nLewy chwyt to przeciąganie, prawy to kliknięcie.",
"HANDSFREE_ALT_TAB": "Kierowanie przełącznikiem aplikacji",
"HANDSFREE_ALT_TAB_HELP": "Przytrzymaj Super+X, wyceluj w wybrane okno, a następnie puść, aby zmienić focus.",
"HIDE_GRAB_HELP": "Ukryj pomoc chwytania",
"HIDE_USERNAME": "Ukryj nazwę użytkownika",
"INPUT_EMULATION_METHOD": "Metoda emulacji wejścia", "INPUT_EMULATION_METHOD": "Metoda emulacji wejścia",
"INPUT_EMULATION_METHOD_HELP": "Spróbuj zmienić tę opcję w przypadku, gdy wejście myszy lub\nklawiatury nie jest rejestrowane.", "INPUT_EMULATION_METHOD_HELP": "Zmień tę opcję, jeśli wejście z myszy lub \nklawiatury nie jest rejestrowane.",
"INPUT_PROFILES": "Zmień klawiszologię", "INPUT_CAPTURE_METHOD": "Metoda przechwytywania wejścia",
"INPUT_PROFILES_HELP": "Przypisania przycisków kontrolera OpenXR", "INPUT_CAPTURE_METHOD_HELP": "Pozwala na korzystanie z fizycznych urządzeń wejściowych w WayVR.\n Super+Z: Przełącz sterowanie między WayVR a prawdziwym pulpitem\n Super+X: Przełączaj aplikacje WayVR",
"INPUT_PROFILES": "Zmień mapowanie przycisków",
"INPUT_PROFILES_HELP": "Mapowanie przycisków kontrolera OpenXR",
"INVERT_SCROLL_DIRECTION_X": "Odwróć kierunek przewijania w poziomie",
"INVERT_SCROLL_DIRECTION_Y": "Odwróć kierunek przewijania w pionie",
"KEYBOARD_MIDDLE_CLICK": "Środkowy przycisk myszy (klawiatura)",
"KEYBOARD_MIDDLE_CLICK_HELP": "Modyfikator używany podczas\npisania fioletowym laserem",
"KEYBOARD_SOUND_ENABLED": "Dźwięki klawiatury",
"LANGUAGE": "Język",
"LEFT_HANDED_MOUSE": "Mysz dla leworęcznych",
"LEFT_HANDED_MOUSE_HELP": "Użyj, jeśli przyciski myszy są zamienione",
"LONG_PRESS_DURATION": "Czas przytrzymania",
"LOOK_AND_FEEL": "Wygląd i styl",
"MISC": "Różnorodne",
"NOTIFICATIONS_ENABLED": "Włącz powiadomienia",
"NOTIFICATIONS_SOUND_ENABLED": "Dźwięki powiadomień",
"NOT_SUPPORTED": "Nieobsługiwane", "NOT_SUPPORTED": "Nieobsługiwane",
"SPACE_DRAG": "Space-drag", "NO_SKYMAPS_FOUND": "Nie znaleziono skymapów",
"SPACE_GRAVITY_DAMPING": "Spowalnianie", "OPAQUE_BACKGROUND": "Nieprzezroczyste tło",
"SPACE_GRAVITY_DAMPING_HELP": "Sztuczne spowalnianie mające na celu zatrzymywanie ruchu po pewnym czasie. 0.1 - wysokie spowolnienie, 1.0 - brak spowolnienia", "OPTION": {
"ANCHORED_HELP": "Porusza się wraz z markerem środka. Zalecane.",
"FLOATING_HELP": "Przesuwa się niezależnie, centruje ponownie.\nŁatwo go zgubić; niezalecane.",
"STATIC_HELP": "Pozostaje w stałym miejscu względem świata.",
"AUTO": "Automatycznie",
"AUTO_HELP": "ScreenCopy GPU (jeśli wspierane),\nw przeciwnym razie PipeWire GPU.",
"EYE_ONLY": "Laser z oczu",
"EYE_PINCH": "Wzrok + szczypnięcie",
"HMD_ONLY": "Laser HMD",
"HMD_PINCH": "HMD + szczypnięcie",
"NONE": "Brak",
"NONE_INPUT_HELP": "Nie emuluj myszy i klawiatury.\nInterakcja z ekranami będzie niemożliwa.",
"NONE_INPUT_CAPTURE_HELP": "Nie przechwytuj myszy i klawiatury.\nBrak możliwości korzystania z fizycznej myszy lub\nklawiatury w aplikacjach uruchomionych w WayVR.",
"PIPEWIRE_HELP": "Szybkie przechwytywanie obrazu z GPU,\nstandard na wszystkich pulpitach.",
"PW_FALLBACK_HELP": "Powolna metoda z dużym obciążeniem procesora.\nWypróbuj, jeśli PipeWire GPU nie działa.",
"SCREENCOPY_GPU_HELP": "Szybka metoda, bez wyskakujących okien udostępniania ekranu.\nDziała w: Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "Powolne, bez wyskakujących okien udostępniania ekranu.\nDziała na: Hyprland, Niri, River, Sway",
"UINPUT": "Emulacja urządzenia",
"UINPUT_HELP": "Wykorzystuje moduł uinput do emulacji urządzenia.\nSprawdzone i działa dobrze na większości systemów desktopowych.",
"EVDEV_HELP": "Przejmij urządzenia wejściowe na wyłączność.\nUżytkownik musi należeć do grupy input.",
"WL_VIRTUAL": "Wirtualny input Wayland",
"WL_VIRTUAL_HELP": "Wysyłaj zdarzenia do kompozytora Wayland za pomocą\nzwlr_virtual_pointer i zwp_virtual_keyboard.\nDziała stabilnie tylko w niektórych środowiskach.\nNIE działa w KDE, GNOME ani COSMIC."
},
"POINTER_ACCELERATION": "Przyspieszenie myszy",
"POINTER_ACCELERATION_HELP": "Wł.: Adaptacyjne przyspieszenie myszy\nWył.: Stała prędkość",
"POINTER_LERP_FACTOR": "Wygładzanie wskaźnika",
"POINTER_SPEED": "Prędkość myszy",
"REQUIRES_RESTART": "Wymaga restartu",
"RESET_PLAYSPACE": "Resetuj przestrzeń gry",
"RESET_PLAYSPACE_HELP": "Wyczyść przesunięcie przestrzeni gry.",
"SAVE_PLAYSPACE_CENTER": "Zapisz środek przestrzeni gry",
"SAVE_PLAYSPACE_CENTER_HELP": "Użyj aktualnej przestrzeni gry dla przypisania resetowania przestrzeni.",
"RESET_PLAYSPACE_CENTER": "Zresetuj centrum przestrzeni gry",
"RESET_PLAYSPACE_CENTER_HELP": "Resetuj aktualny środek przestrzeni gry.",
"RESTART_SOFTWARE": "Uruchom ponownie program",
"RESTART_SOFTWARE_HELP": "Zastosuj ustawienia wymagające restartu",
"ROUND_MULTIPLIER": "Zaokrąglenie krawędzi UI",
"SCREEN_RENDER_DOWN": "Renderuj ekran w niższej rozdzielczości",
"SCREEN_RENDER_DOWN_HELP": "Pomaga zredukować aliasing na ekranach o wysokiej rozdzielczości",
"SCROLL_SPEED": "Prędkość przewijania",
"SELECT_VARIANT": "Wybierz wariant",
"SNAP_ANGLE_DEG": "Kąt przyciągania pochylenia i obrotu okna",
"SNAP_ANGLE_DEG_HELP": "Chwycone okna przyciągają się do tego kąta na osi pochylenia i obrotu.",
"ENABLE_WATCH": "Włącz zegarek",
"SETS_ON_WATCH": "Zestawy na zegarku",
"SHOW_WELCOME_SCREEN": "Pokaż ekran powitalny",
"SKYBOX": "Skymap",
"SKYMAP_ALREADY_DOWNLOADED": "Ta skymapa jest już pobrana. Wybierz żądaną akcję.",
"SPACE_DRAG": "Przestrzeń gry",
"SPACE_DRAG_MULTIPLIER": "Mnożnik przesuwania w przestrzeni",
"SPACE_DRAG_AFFECTS_WORLD": "Pozostaw nakładki podczas przesuwania przestrzeni gry",
"SPACE_DRAG_UNLOCKED": "Pozwól na przesuwanie w przestrzeni we wszystkich osiach",
"SPACE_GRAVITY_DAMPING": "Opór",
"SPACE_GRAVITY_DAMPING_HELP": "Sztuczny opór spowalniający ruch. 0,1 duży opór, 1,0 brak oporu",
"SPACE_GRAVITY_FLING_STRENGTH": "Siła wyrzutu", "SPACE_GRAVITY_FLING_STRENGTH": "Siła wyrzutu",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Mnożnik intensywności siły grawitacyjnego wyrzutu po użyciu funkcji space-drag.\n0.0 - brak ruchu, 2.0 - podwójna intensywność", "SPACE_GRAVITY_FLING_STRENGTH_HELP": "Mnożnik intensywności siły wyrzutu grawitacyjnego po Space-dragu.\n0.0 - brak ruchu, 2.0 - podwójna intensywność",
"SPACE_GRAVITY_GRAVITY": "Grawitacja", "SPACE_GRAVITY_GRAVITY": "Grawitacja",
"SPACE_GRAVITY_GRAVITY_HELP": "Wielkość siły działającej w dół. 0.0 - brak grawitacji", "SPACE_GRAVITY_GRAVITY_HELP": "Siła przyciągania w dół. 0.0 - brak grawitacji",
"SPACE_GRAVITY_GROUND_FRICTION": "Tarcie podłoża", "SPACE_GRAVITY_GROUND_FRICTION": "Tarcie o podłoże",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "Moc tarcia spowalniającego Cię podczas kontaktu z podłożem.\n0.0 - brak tarcia (jak na lodzie), 1.0 - chropowata powierzchnia", "SPACE_GRAVITY_GROUND_FRICTION_HELP": "Wartość tarcia spowalniającego ruch przy kontakcie z podłożem.\n0.0 - brak tarcia (jak na lodzie), 1.0 - chropowata powierzchnia",
"SPACE_GRAVITY_FLOOR_HEIGHT": "Wysokość podłogi", "SPACE_GRAVITY_FLOOR_HEIGHT": "Wysokość podłogi",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "Pozycja Y, w której znajduje się podłoga. Grawitacja przestaje działać po osiągnięciu tej wysokości.", "SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "Pozycja Y podłogi. Grawitacja zatrzymuje się na tej wysokości.",
"SAVE": "Zapisz", "SPACE_ROTATE_UNLOCKED": "Pozwól na obrót przestrzeni gry we wszystkich osiach",
"CANCEL": "Anuluj", "TROUBLESHOOTING": "Rozwiązywanie problemów",
"UI_GRADIENT_INTENSITY": "Intensywność gradientu UI",
"UPRIGHT_SCREEN_FIX": "Korekta pionowego ekranu",
"UPRIGHT_SCREEN_FIX_HELP": "Naprawia pionowe ekrany na niektórych pulpitach",
"USE_PASSTHROUGH": "Włącz passthrough",
"USE_PASSTHROUGH_HELP": "Włącz passthrough, jeśli środowisko XR je obsługuje",
"USE_SKYBOX": "Pokaż skymap",
"USE_SKYBOX_HELP": "Wyświetl skymap, gdy nie ma uruchomionej aplikacji sceny lub trybu passthrough",
"WATCH_VIEW_ANGLE": "Kąty widzenia zegarka",
"WATCH_VIEW_ANGLE_HELP": "Steruj tym, jak zegarek znika",
"WHISPER": { "WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "Wybrany model musi zostać pobrany.\nPobrać go teraz?", "NEED_TO_DOWNLOAD_MODEL": "Wybrany model musi zostać pobrany.\nPobrać go teraz?",
"REMOVE_UNUSED_MODELS": "Wyłączasz funkcję zamiany mowy na tekst.\nCzy chcesz usunąć pobrane modele Whisper, aby zwolnić miejsce?" "REMOVE_UNUSED_MODELS": "Wyłączasz funkcję zamiany mowy na tekst.\nCzy chcesz usunąć pobrane modele Whisper, aby zwolnić miejsce?"
}, },
"WHISPER_MODEL": "Model mowy na tekst", "WHISPER_MODEL": "Model mowy na tekst",
"WHISPER_MODEL_HELP": "Model Whisper do wykorzystania.\nWiększe modele dają dokładniejsze\nwyniki, ale zużywają więcej pamięci VRAM.", "WHISPER_MODEL_HELP": "Model Whisper do użycia.\nWiększe modele dają dokładniejsze\nwyniki, ale zużywają więcej pamięci VRAM.",
"DEFAULT_OVERLAY_SCALE": "Domyślny rozmiar nakładki", "GRID_OPACITY": "Przezroczystość siatki podłogi",
"DEFAULT_OVERLAY_SCALE_HELP": "Twórz nowe nakładki w tej skali.", "GRID_OPACITY_HELP": "Przezroczystość siatki podłogi przy włączonym Skymapie",
"COLOR_PALETTE": "Paleta kolorów", "XWAYLAND_BY_DEFAULT": "Uruchamiaj aplikacje domyślnie w trybie kompatybilności",
"COLOR_PALETTES": "Palety kolorów", "SAVE": "Zapisz",
"COLOR_PALETTE_CURRENT": "Obecnie aktywny motyw.", "CANCEL": "Anuluj"
"COLOR_PALETTE_ACTIVATE": "Kliknij, aby użyć tego motywu.",
"APPLY_CHANGES_RESTART": "Zrestartować WayVR, aby zastosować zmiany?",
"COLOR_PALETTE_HELP": "Kliknij, aby przeglądać palety kolorów.\nAby stworzyć własne, odwiedź stronę internetową!",
"COLOR_PALETTE_CUSTOM_URL": "Dodaj własny motyw!",
"COLOR_PALETTE_CUSTOM_URL2": "Kliknij, aby otworzyć instrukcję internetową.",
"SNAP_ANGLE_DEG": "Kąt przyciągania pochylenia i przechyłu okna",
"SNAP_ANGLE_DEG_HELP": "Chwycone okna przyciągają się do tego kąta na osi pochylenia i obrotu."
}, },
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji", "APPLICATION_LAUNCHER": "Launcher aplikacji",
"APPLICATION_STARTED": "Uruchomiono aplikację",
"APPLICATIONS": "Aplikacje", "APPLICATIONS": "Aplikacje",
"AUDIO": { "AUDIO": {
"AUTO_SWITCH_TO_VR_AUDIO": "Automatyczne przełączanie na dźwięk VR", "AUTO_SWITCH_TO_VR_AUDIO": "Auto-przełączanie na dźwięk VR",
"CARDS": "Karty", "CARDS": "Karty dźwiękowe",
"FAILED_TO_SWITCH_MICROPHONE": "Nie udało się przełączyć mikrofon", "FAILED_TO_SWITCH_MICROPHONE": "Błąd przełączania mikrofonu",
"MICROPHONE_SET_SUCCESSFULLY": "Mikrofon ustawiono pomyślnie", "MICROPHONE_SET_SUCCESSFULLY": "Mikrofon ustawiony pomyślnie",
"MICROPHONES": "Mikrofony", "MICROPHONES": "Mikrofony",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "Brak mikrofonu VR. Włącz go ręcznie.", "NO_VR_MICROPHONE_SWITCH_MANUALLY": "Nie znaleziono mikrofonu VR. Przełącz go ręcznie.",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Brak głośników VR. Włącz je ręcznie.", "NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "Nie znaleziono głośników VR. Przełącz je ręcznie.",
"SELECT_AUDIO_CARD_PROFILE": "Wybierz profil karty dźwiękowej", "SELECT_AUDIO_CARD_PROFILE": "Wybierz profil karty dźwiękowej",
"SETTINGS": "Ustawienia dźwięku", "SETTINGS": "Ustawienia dźwięku",
"SPEAKERS": "Głośniki", "SPEAKERS": "Głośniki",
"SPEAKERS_SET_SUCCESSFULLY": "Głośniki ustawiono pomyślnie", "SPEAKERS_SET_SUCCESSFULLY": "Głośniki ustawione pomyślnie",
"VOLUME": "Głośność" "VOLUME": "Głośność"
}, },
"CLOSE_WINDOW": "Zamknij okno",
"CREATION_DATE": "Data utworzenia",
"DEBUG_INFO": "Informacje diagnostyczne",
"DISPLAY_BRIGHTNESS": "Jasność ekranu",
"DONATE": {
"SUPPORT_US": "Wesprzyj nas",
"DESCRIPTION": "Jesteśmy małym zespołem dwóch programistów, którzy tworzą WayVR w wolnym czasie. Jeśli lubisz korzystać z tego programu, rozważ wsparcie nas finansowo każda darowizna pomaga nam działać dalej.",
"THANK_YOU_WAYVR": "Dzięki od zespołu WayVR!",
"BUTTON_TOOLTIP": "Wesprzyj projekt przez Open Collective",
"CURRENT_SUPPORTERS": "Obecni darczyńcy",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "Wspierane przez {USER}|Dzięki dla {USER}|Sponsor: {USER}|Z pomocą {USER}|Wkład od {USER}|Umożliwione przez {USER}|Dzięki wsparciu {USER}|Patron: {USER}|Działamy dzięki {USER}",
"BROUGHT_TO_YOU_VARIANTS_RARE": "Kawa od {USER}|Energia dostarczona przez {USER}|Wielkie brawa dla {USER}!|Dzięki {USER} idziemy do przodu|Razem z {USER} rośniemy w siłę|Serwery napędzane przez {USER}|Z ogromną wdzięcznością dla {USER}|Napędzane przez {USER}|Wsparcie od przyjaciół takich jak {USER}",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "Wspierane przez legendę: {USER}|Dostawa kofeiny od {USER}|Prawdziwa legenda: {USER}|Gwiazda dnia: {USER}|Absolutna supergwiazda: {USER}|Opłaca rachunki za prąd: {USER}|Ludzie, którzy czynią to możliwe: {USER}|Sponsor spokoju ducha: {USER}|Konwerter kawy na kod: {USER}|Strażnik stabilności produkcji: {USER}|Jedyny w swoim rodzaju: {USER}|Przesyła bufory dmabuf: {USER}"
},
"DOWNLOAD": "Pobierz",
"DOWNLOADER": "Menedżer pobierania",
"WELCOME": {
"ALL_SET": "Wszystko gotowe!",
"BASICS": "Te podstawy pozwolą Ci z łatwością zacząć korzystać z WayVR.",
"CENTER_MARKER": "Znacznik środkowy pojawi się przed Tobą podczas centrowania. Rozmieść wokół niego nakładki!",
"DOUBLE_PRESS_TO_TOGGLE": "Dwukrotnie naciśnij B (na Index) lub Y (na Meta), aby wyświetlić, wycentrować lub ukryć swój zestaw. Wypróbuj teraz.",
"FEATURES_DOCUMENTATION": "Istnieje wiele innych funkcji wartych dostosowania. Więcej informacji znajdziesz w dokumentacji pod adresem",
"FINISH_TUTORIAL": "Zakończ samouczek",
"GRAB_BOTH_HANDS": "Chwyć oburącz, aby przesunąć konkretny element zestawu.",
"GRAB_ONE_HAND": "Chwyć go jedną ręką, aby przesunąć zestaw.",
"GREETING": "Cześć!",
"GUIDE_INTRO": "Przeprowadźmy Cię przez pierwsze kroki.",
"LASER_COLORS": "Kolory laserów",
"LASER_FUNCTIONALITY": "Wiele funkcji WayVR zależy od koloru lasera użytego do interakcji z elementem UI. Nie musisz naciskać tych przycisków wystarczy ich dotknąć!",
"LAST_PAGE_INFO": "Ten samouczek przestanie się wyświetlać po dotarciu do ostatniej strony.",
"LOOK_AT_LEFT_WRIST": "Spójrz na lewy nadgarstek. To twój zegarek.",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "Tryb środkowego kliknięcia: Purpurowy laser",
"MOVING_YOUR_SET": "Przesuwanie zestawu",
"NEXT_BUTTON": "Naciśnij przycisk Dalej poniżej, aby zacząć.",
"REGULAR_MODE_BLUE_LASER": "Tryb standardowy: Niebieski laser",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Przesuń to okno, używając przycisku chwytu kontrolera.",
"RIGHT_CLICK_MODE_ORANGE_LASER": "Tryb prawego kliknięcia: Pomarańczowy laser",
"THANKS_FOR_INSTALLING": "Dzięki za zainstalowanie WayVR!",
"WATCH": "Zegarek",
"WORKING_SET": "Aktywny zestaw"
},
"DOWNLOAD_AGAIN": "Pobierz ponownie",
"DOWNLOADING_FILE": "Pobieranie pliku...",
"FAILED_TO_LAUNCH_APPLICATION": "Błąd uruchamiania aplikacji:",
"GAME_LAUNCHED": "Gra uruchomiona",
"GAME_LIST": {
"NO_GAMES_FOUND": "Nie znaleziono gier",
"RUNNING_GAMES_LIST": "Lista uruchomionych gier"
},
"GAMES": "Gry", "GAMES": "Gry",
"GENERAL_SETTINGS": "Ustawienia ogólne", "GENERAL_SETTINGS": "Ustawienia ogólne",
"GETTING_STARTED": "Pierwsze kroki",
"HEIGHT": "Wysokość", "HEIGHT": "Wysokość",
"HELLO": "Witaj!", "HELLO": "Witaj!",
"HELLO_USER": "Witaj, {USER}!", "HELLO_USER": "Witaj, {USER}!",
"HIDE": "Ukryj", "HIDE": "Ukryj",
"HOME_SCREEN": "Ekran główny", "HOME_SCREEN": "Ekran główny",
"MODIFICATION_DATE": "Data modyfikacji",
"MONADO_RUNTIME": "Środowisko Monado", "MONADO_RUNTIME": "Środowisko Monado",
"LOADING": "Ładowanie...",
"POPUP_ADD_DISPLAY": { "POPUP_ADD_DISPLAY": {
"RESOLUTION": "Rozdzielczość" "RESOLUTION": "Rozdzielczość"
}, },
"REMOVE": "Usuń", "PROCESS": {
"SETTINGS": "Ustawienia", "FORCE_KILL": "Wymuś zamknięcie",
"SHOW": "Pokaż", "STOP": "Zatrzymaj"
"WIDTH": "Szerokość",
"FAILED_TO_LAUNCH_APPLICATION": "Nie udało się uruchomić aplikacji:",
"APPLICATION_STARTED": "Aplikacja uruchomiona",
"CLOSE_WINDOW": "Zamknij okno",
"GAME_LIST": {
"NO_GAMES_FOUND": "Nie znaleziono gier",
"RUNNING_GAMES_LIST": "Lista uruchomionych gier"
}, },
"TERMINATE_PROCESS": "Zakończ proces",
"GAME_LAUNCHED": "Gra uruchomiona",
"APP_LAUNCHER": {
"MODE": {
"NATIVE": "Tryb natywny",
"CAGE": "Tryb kompatybilności (Cage)"
},
"RES_TITLE": "Rozdzielczość",
"ASPECT_TITLE": "Proporcje",
"ASPECT": {
"WIDE": "Szeroki",
"SEMI_WIDE": "Półszeroki",
"SQUARE": "Kwadrat",
"SEMI_TALL": "Pół-wysoki",
"TALL": "Wysoki"
},
"POS_TITLE": "Pozycjonowanie",
"POS": {
"FLOATING": "Pływający",
"ANCHORED": "Przymocowane",
"STATIC": "Statyczny",
"FLOATING_HELP": "Porusza się niezależnie, wycentrowuje się po otwarciu.",
"ANCHORED_HELP": "Pozostaje nieruchoma względem centralnego znacznika.",
"STATIC_HELP": "Nie należy do żadnego zestawu. Nie wyśrodkowuje."
},
"AUTOSTART": "Uruchom automatycznie przy starcie",
"LAUNCH": "Uruchom"
},
"DISPLAY_BRIGHTNESS": "Jasność wyświetlacza",
"PROCESS_LIST": "Lista procesów", "PROCESS_LIST": "Lista procesów",
"REFRESH": "Odśwież", "REFRESH": "Odśwież",
"PROCESS": { "REMOVE": "Usuń",
"STOP": "Zatrzymaj",
"FORCE_KILL": "Wymuś zakończenie"
},
"DEBUG_INFO": "Informacje debugowania",
"CREATION_DATE": "Data utworzenia",
"DOWNLOADER": "Pobieranie",
"DOWNLOAD_AGAIN": "Pobierz ponownie",
"DOWNLOADING_FILE": "Pobieranie pliku...",
"GETTING_STARTED": "Rozpoczęcie",
"MODIFICATION_DATE": "Data modyfikacji",
"LOADING": "Ładowanie...",
"APPLY": "Zastosuj", "APPLY": "Zastosuj",
"RELOAD_FROM_DISK": "Przeładuj z dysku", "RELOAD_FROM_DISK": "Przeładuj z dysku",
"SETTINGS": "Ustawienia",
"SHOW": "Pokaż",
"TARGET_PATH": "Ścieżka docelowa", "TARGET_PATH": "Ścieżka docelowa",
"TERMINATE_PROCESS": "Zakończ proces",
"VERSION": "Wersja", "VERSION": "Wersja",
"DONATE": { "WIDTH": "Szerokość",
"SUPPORT_US": "Wesprzyj nas", "PINNED_APPS": "Przypięte aplikacje",
"DESCRIPTION": "Jesteśmy małym, dwuosobowym zespołem programistów, którzy tworzą WayVR w wolnym czasie. Jeśli korzystanie z tego oprogramowania sprawia Ci przyjemność, rozważ wsparcie nas każda darowizna pomaga nam działać dalej.", "SAVED_TO_FAVOURITES": "Dodano do przypiętych aplikacji",
"BUTTON_TOOLTIP": "Przekaż darowiznę przez Open Collective", "ADD_TO_FAVOURITES": "Przypnij aplikację",
"CURRENT_SUPPORTERS": "Obecni Wspierający", "ADD_TO_FAVOURITES_HINT": "Zapisz preset i przypnij go do szuflady aplikacji",
"THANK_YOU_WAYVR": "Dziękujemy od zespołu WayVR!" "REMOVE_FROM_FAVOURITES": "Usuń z przypiętych aplikacji",
}, "EMPTY": "Puste"
"WELCOME": {
"ALL_SET": "Wszystko gotowe!",
"BASICS": "Te podstawowe informacje pozwolą Ci z łatwością zacząć korzystać z WayVR.",
"FEATURES_DOCUMENTATION": "Istnieje wiele innych funkcji, które warto spersonalizować. Aby uzyskać więcej informacji, sprawdź dokumentację pod adresem:",
"FINISH_TUTORIAL": "Zakończ samouczek",
"GRAB_BOTH_HANDS": "Chwyć to obiema rękami, jeśli chcesz przenieść konkretny overlay ze swojego zestawu.",
"GRAB_ONE_HAND": "Chwyć to jedną ręką, aby przemieścić swój zestaw.",
"GREETING": "Cześć!",
"GUIDE_INTRO": "Pozwól nam przeprowadzić Cię przez Twoje pierwsze kroki.",
"LASER_COLORS": "Kolory lasera",
"LASER_FUNCTIONALITY": "Wiele funkcji w WayVR zależy od koloru lasera używanego do interakcji z elementami interfejsu użytkownika. Nie musisz naciskać tych przycisków, wystarczy je dotknąć!",
"LAST_PAGE_INFO": "Ten samouczek przestanie się pojawiać po dotarciu do ostatniej strony.",
"LOOK_AT_LEFT_WRIST": "Spójrz na swój lewy nadgarstek. To jest Twój watch.",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— Tryb środkowego przycisku: Fioletowy laser",
"MOVING_YOUR_SET": "Przesuwanie Twojego zestawu",
"NEXT_BUTTON": "Naciśnij poniższy przycisk „Dalej”, aby rozpocząć.",
"REGULAR_MODE_BLUE_LASER": "— Tryb regularny: Niebieski laser",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "Zmień położenie tego okna, używając przycisku chwytu (grip) na kontrolerze.",
"RIGHT_CLICK_MODE_ORANGE_LASER": "— Tryb prawego przycisku: Pomarańczowy laser",
"THANKS_FOR_INSTALLING": "Dziękujemy za zainstalowanie WayVR!",
"WATCH": "Watch",
"WORKING_SET": "Aktywny zestaw",
"DOUBLE_PRESS_TO_TOGGLE": "Naciśnij dwukrotnie przycisk B (na Index) lub Y (na Meta), aby wyświetlić, wycentrować lub ukryć swój zestaw. Wypróbuj to teraz.",
"CENTER_MARKER": "Znacznik środka to punkt, który pojawi się przed Tobą podczas centrowania. Umieść wokół niego nakładki!"
},
"DOWNLOAD": "Pobierz",
"SAVED_TO_FAVOURITES": "Dodano do ulubionych",
"ADD_TO_FAVOURITES": "Dodaj do ulubionych",
"ADD_TO_FAVOURITES_HINT": "Zapisz ustawienie i przypnij je do szuflady aplikacji",
"REMOVE_FROM_FAVOURITES": "Usuń z ulubionych",
"EMPTY": "Puste",
"PINNED_APPS": "Przypięte aplikacje"
} }

View File

@ -1,156 +1,77 @@
{ {
"DEFINITIONS": {
"ANCHORED": "同步移动",
"FLOATING": "悬浮",
"STATIC": "静态",
"SET": "套装",
"WATCH": "手表",
"DASHBOARD": "控制面板",
"EDIT_MODE": "编辑模式",
"SETTINGS": "设置",
"KEYBOARD": "键盘",
"TASKBAR": "任务栏",
"FEATURES": "功能",
"OVERLAY": "叠加层",
"SKYMAP": "天空盒",
"PLAYSPACE": "活动空间",
"D_PAD": "方向键"
},
"ACTIONS": { "ACTIONS": {
"RECENTER_PLAYSPACE": "重置游玩区中心" "RECENTER_PLAYSPACE": "重新中心化活动空间"
}, },
"APP_LAUNCHER": { "APP_LAUNCHER": {
"ASPECT": { "ASPECT": {
"SEMI_TALL": "略高", "SEMI_TALL": "高",
"SEMI_WIDE": "略宽", "SEMI_WIDE": "宽",
"SQUARE": "正方形", "SQUARE": "正方形",
"TALL": "高", "TALL": "纵向",
"WIDE": "宽" "WIDE": "宽"
}, },
"ASPECT_TITLE": "比例", "ASPECT_TITLE": "宽高比",
"AUTOSTART": "启动时自动运行", "AUTOSTART": "启动时自动运行",
"LAUNCH": "启动", "LAUNCH": "启动",
"MODE": { "MODE": {
"CAGE": "兼容模式 (Cage)", "CAGE": "兼容模式 (Cage)",
"NATIVE": "原生模式" "NATIVE": "原生模式"
}, },
"POS": {
"ANCHORED": "锚定",
"ANCHORED_HELP": "相对于中心标记保持固定。",
"FLOATING": "悬浮",
"FLOATING_HELP": "独立移动,显示时自动重置中心。",
"STATIC": "静态",
"STATIC_HELP": "不属于任何集合。不会重置中心。"
},
"POS_TITLE": "定位",
"RES_TITLE": "分辨率" "RES_TITLE": "分辨率"
}, },
"APP_SETTINGS": { "APP_SETTINGS": {
"ALLOW_SLIDING": "抓取时允许摇杆交互", "ALLOW_SLIDING": "抓取时允许摇杆交互",
"ANIMATION_SPEED": "UI 动画速度", "ANIMATION_SPEED": "UI 动画速度",
"AUTOSTART_APPS": "启动时运行的应用程序",
"BLOCK_GAME_INPUT": "屏蔽游戏输入", "BLOCK_GAME_INPUT": "屏蔽游戏输入",
"BLOCK_GAME_INPUT_HELP": "悬停在覆盖层上时屏蔽所有输入", "BLOCK_GAME_INPUT_HELP": "当悬停在覆盖层上时,屏蔽所有输入",
"BLOCK_GAME_INPUT_IGNORE_WATCH": "屏蔽输入时忽略手表", "BLOCK_GAME_INPUT_IGNORE_WATCH": "拦截输入时忽略手表",
"BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "悬停在手表上时不屏蔽输入", "BLOCK_GAME_INPUT_IGNORE_WATCH_HELP": "当光标悬停在手表上时,不拦截输入",
"CAPTURE_METHOD": "Wayland 屏幕采集", "BLOCK_POSES_ON_KBD_INTERACTION": "与键盘交互时禁用姿态输入",
"CAPTURE_METHOD_HELP": "如果您遇到黑屏或花屏,请尝试更改此项", "BLOCK_POSES_ON_KBD_INTERACTION_HELP": "当光标悬停在键盘上且启用了“拦截游戏输入”时,拦截游戏接收的姿态数据",
"CLEAR_PIPEWIRE_TOKENS": "清除 PipeWire 令牌",
"CLEAR_PIPEWIRE_TOKENS_HELP": "下次启动时提示选择屏幕",
"CLEAR_SAVED_STATE": "清除保存的状态",
"CLEAR_SAVED_STATE_HELP": "重置集合与覆盖层位置",
"CLICK_FREEZE_TIME_MS": "点击冻结时间 (毫秒)",
"CLICK_FREEZE_TIME_MS_HELP": "有助于提高双击精度",
"CLOCK_12H": "12 小时制时钟",
"CONTROLS": "控制",
"DELETE_ALL_CONFIGS": "擦除配置",
"DELETE_ALL_CONFIGS_HELP": "从 conf.d 中删除所有配置文件",
"DOUBLE_CURSOR_FIX": "双光标修复",
"DOUBLE_CURSOR_FIX_HELP": "如果您看到两个光标,请启用此项",
"FEATURES": "功能",
"FOCUS_FOLLOWS_MOUSE_MODE": "触摸扳机时移动鼠标",
"HIDE_GRAB_HELP": "隐藏抓取帮助",
"HIDE_USERNAME": "隐藏用户名",
"INVERT_SCROLL_DIRECTION_X": "反转水平滚动方向",
"INVERT_SCROLL_DIRECTION_Y": "反转垂直滚动方向",
"KEYBOARD_MIDDLE_CLICK": "键盘中键点击",
"KEYBOARD_MIDDLE_CLICK_HELP": "使用紫色激光打字时的修饰键",
"KEYBOARD_SOUND_ENABLED": "键盘音效",
"LEFT_HANDED_MOUSE": "左手鼠标",
"LEFT_HANDED_MOUSE_HELP": "如果鼠标按钮反置,请使用此项",
"LONG_PRESS_DURATION": "长按持续时间",
"LOOK_AND_FEEL": "外观与体验",
"MISC": "杂项",
"NOTIFICATIONS_ENABLED": "启用通知",
"NOTIFICATIONS_SOUND_ENABLED": "通知音效",
"OPAQUE_BACKGROUND": "不透明背景",
"OPTION": {
"AUTO": "自动",
"AUTO_HELP": "如果支持,则使用 ScreenCopy GPU\n否则使用 PipeWire GPU。",
"PIPEWIRE_HELP": "快速 GPU 采集,\n所有桌面环境的标准方式。",
"PW_FALLBACK_HELP": "高 CPU 占用的慢速方法。\n在 PipeWire GPU 不起作用时尝试。",
"SCREENCOPY_GPU_HELP": "快速,无屏幕共享弹窗。\n支持Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "慢速,无屏幕共享弹窗。\n支持Hyprland, Niri, River, Sway",
"NONE": "无",
"HMD_PINCH": "HMD + 捏合",
"EYE_PINCH": "眼睛 + 捏合",
"EYE_ONLY": "仅眼球",
"HMD_ONLY": "仅限头显",
"NONE_INPUT_HELP": "不模拟鼠标和键盘。\n将无法与屏幕进行交互。",
"UINPUT": "设备模拟",
"UINPUT_HELP": "使用 uinput 模块来模拟设备。\n您的用户必须处于 input 用户组中。\n已知在大多数桌面上运行良好。",
"WL_VIRTUAL": "Wayland 虚拟输入",
"WL_VIRTUAL_HELP": "使用 zwlr_virtual_pointer 和 zwp_virtual_keyboard 向 Wayland 合成器发送事件。\n仅在部分桌面环境下能可靠工作。\n在 KDE、GNOME 或 COSMIC 上无法工作。"
},
"POINTER_LERP_FACTOR": "指针平滑",
"RESTART_SOFTWARE": "重启软件",
"RESTART_SOFTWARE_HELP": "应用需要重启的设置",
"ROUND_MULTIPLIER": "UI 边缘圆角",
"SCREEN_RENDER_DOWN": "以较低分辨率渲染屏幕",
"SCREEN_RENDER_DOWN_HELP": "有助于解决高分辨率屏幕的锯齿问题",
"SCROLL_SPEED": "滚动速度",
"SETS_ON_WATCH": "在手表上显示集合",
"SPACE_DRAG_MULTIPLIER": "空间拖拽倍率",
"SPACE_DRAG_UNLOCKED": "允许在所有轴上进行空间拖拽",
"SPACE_ROTATE_UNLOCKED": "允许在所有轴上进行空间旋转",
"TROUBLESHOOTING": "故障排除",
"UPRIGHT_SCREEN_FIX": "垂直屏幕修复",
"UPRIGHT_SCREEN_FIX_HELP": "修复某些桌面上的垂直屏幕问题",
"USE_PASSTHROUGH": "启用穿透",
"USE_PASSTHROUGH_HELP": "如果 XR 运行时支持,则允许穿透",
"USE_SKYBOX": "启用天空盒",
"USE_SKYBOX_HELP": "如果没有场景应用或穿透,则显示天空盒",
"XWAYLAND_BY_DEFAULT": "默认以兼容模式运行应用",
"AUTOSTART_APPS": "开机启动应用",
"HANDSFREE_POINTER": "免提模式",
"HANDSFREE_POINTER_HELP": "当运动控制器不可用时使用的输入。\n左手捏合为抓取右手为点击。",
"UI_GRADIENT_INTENSITY": "UI 渐变强度",
"RESET_PLAYSPACE": "重置游戏空间",
"RESET_PLAYSPACE_HELP": "清除舞台空间偏移。",
"BLOCK_POSES_ON_KBD_INTERACTION": "与键盘交互时阻止姿势",
"BLOCK_POSES_ON_KBD_INTERACTION_HELP": "当键盘悬停且启用“阻止游戏输入”时,阻止游戏接收姿势",
"LANGUAGE": "语言",
"REQUIRES_RESTART": "需要重启",
"GRID_OPACITY": "地面网格不透明度",
"GRID_OPACITY_HELP": "启用天空盒时地板网格的不透明度",
"BROWSE_ONLINE_CATALOG": "浏览在线目录...",
"BROWSE_SKYMAPS": "浏览 Skymaps",
"COLOR_KEYING": "颜色键控",
"NO_SKYMAPS_FOUND": "未找到 Skymaps",
"SELECT_VARIANT": "选择变体",
"SHOW_WELCOME_SCREEN": "显示欢迎屏幕",
"SKYBOX": "Skybox",
"SKYMAP_ALREADY_DOWNLOADED": "此 Skymap 已下载。请选择所需操作。",
"WATCH_VIEW_ANGLE": "Watch 视角角度",
"WATCH_VIEW_ANGLE_HELP": "控制表盘的淡出方式",
"BINDINGS": { "BINDINGS": {
"COMP": { "COMP": {
"CLICK": "点击", "CLICK": "点击",
"FORCE": "力度", "FORCE": "力度",
"TOUCH": "触", "TOUCH": "触碰",
"VALUE": "值", "VALUE": "数值",
"PROXIMITY": "临近度", "PROXIMITY": "距离",
"X_AXIS": "X 轴", "X_AXIS": "X 轴",
"Y_AXIS": "Y 轴" "Y_AXIS": "Y 轴"
}, },
"TYPE": { "TYPE": {
"BUMPER": "键", "BUMPER": "肩键",
"DPAD_UP": "方向键上", "DPAD_UP": "方向键-上",
"DPAD_DOWN": "方向键下", "DPAD_DOWN": "方向键-下",
"DPAD_LEFT": "方向键左", "DPAD_LEFT": "方向键-左",
"DPAD_RIGHT": "方向键右", "DPAD_RIGHT": "方向键-右",
"JOYSTICK": "摇杆", "JOYSTICK": "摇杆",
"MENU": "菜单", "MENU": "菜单",
"SHOULDER": "肩键", "SHOULDER": "肩键",
"SQUEEZE": "抓取", "SQUEEZE": "握持",
"SYSTEM": "系统", "SYSTEM": "系统",
"THUMBREST": "拇指托", "THUMBREST": "大拇指托",
"THUMBSTICK": "摇杆", "THUMBSTICK": "摇杆 (Thumbstick)",
"TRACKPAD": "触控板", "TRACKPAD": "触控板",
"TRIGGER": "扳机键", "TRIGGER": "扳机键",
"VIEW": "视图" "VIEW": "View 键"
}, },
"CLICK": { "CLICK": {
"ANY": "任意", "ANY": "任意",
@ -162,72 +83,179 @@
"CLICK": "点击*", "CLICK": "点击*",
"GRAB": "抓取*", "GRAB": "抓取*",
"ALT_CLICK": "自定义 Shell 执行 (在配置中设置 alt_click)", "ALT_CLICK": "自定义 Shell 执行 (在配置中设置 alt_click)",
"SHOW_HIDE": "显示、隐藏、重新中心化*", "SHOW_HIDE": "显示、隐藏、居中*",
"TOGGLE_DASHBOARD": "切换控制面板", "TOGGLE_DASHBOARD": "切换控制面板",
"SPACE_DRAG": "Playspace 拖拽", "SPACE_DRAG": "活动空间拖拽",
"SPACE_ROTATE": "Playspace 旋转", "SPACE_ROTATE": "旋转活动空间",
"SPACE_RESET": "Playspace 重置", "SPACE_RESET": "重置活动空间",
"CLICK_MODIFIER_RIGHT": "右键修饰键", "CLICK_MODIFIER_RIGHT": "右键修饰键",
"CLICK_MODIFIER_MIDDLE": "中键修饰键", "CLICK_MODIFIER_MIDDLE": "中键点击修饰键",
"MOVE_MOUSE": "移动鼠标 (如果默认关闭)", "MOVE_MOUSE": "移动鼠标(默认关闭)",
"SCROLL": "滚动*" "SCROLL": "滚动*"
}, },
"LEFT": "左", "LEFT": "左",
"RIGHT": "右", "RIGHT": "右",
"COMPONENT": "触发类型", "COMPONENT": "触发类型",
"SUBPATH": "动作控制", "SUBPATH": "激活控件",
"THRESHOLD": "高于上限值时激活\n低于下限值时停用" "THRESHOLD": "高于上限值时激活\n低于下限值时取消激活"
}, },
"ENABLED": "已启用", "BROWSE_ONLINE_CATALOG": "浏览在线目录...",
"INPUT_EMULATION_METHOD": "输入仿真方法", "BROWSE_SKYMAPS": "浏览天空盒",
"INPUT_EMULATION_METHOD_HELP": "如果鼠标或键盘输入未被识别,请尝试更改此设置。", "CAPTURE_METHOD": "屏幕采集方式",
"INPUT_PROFILES": "更改输入绑定", "CAPTURE_METHOD_HELP": "如果屏幕出现黑色或花屏,请尝试更改此项",
"INPUT_PROFILES_HELP": "OpenXR 控制器输入绑定", "COLOR_KEYING": "颜色键控",
"NOT_SUPPORTED": "不支持", "COLOR_PALETTE": "颜色面板",
"ENABLE_WATCH": "启用手表", "COLOR_PALETTE_HELP": "点击浏览配色方案。\n如需创建自定义方案请访问网站",
"SPACE_DRAG": "空间拖拽",
"SPACE_GRAVITY_DAMPING": "阻尼",
"SPACE_GRAVITY_DAMPING_HELP": "用于减缓移动速度的人造阻力。0.1 - 高阻力1.0 - 无阻力",
"SPACE_GRAVITY_FLING_STRENGTH": "投掷力度",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "Space-drag 后的重力发射力强度倍数。\n0.0 - 完全没有位移2.0 - 双倍强度",
"SPACE_GRAVITY_GRAVITY": "重力",
"SPACE_GRAVITY_GRAVITY_HELP": "向下作用的力的大小。0.0 - 无重力",
"SPACE_GRAVITY_GROUND_FRICTION": "地面摩擦力",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "如果你接触地面时,减慢你移动速度的摩擦力大小。\n0.0 - 无摩擦就像在冰面上一样1.0 - 粗糙表面",
"SPACE_GRAVITY_FLOOR_HEIGHT": "地面高度",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "地面所在 Y 轴位置。达到该高度时重力停止。",
"SAVE": "保存",
"CANCEL": "取消",
"WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "所选模型需要下载。\n现在开始下载吗",
"REMOVE_UNUSED_MODELS": "您正在关闭语音转文本功能。\n是否删除已下载的 Whisper 模型以释放空间?"
},
"WHISPER_MODEL": "语音转文本模型",
"WHISPER_MODEL_HELP": "要使用的 Whisper 模型。\n模型越大结果越准确\n但消耗的显存 (VRAM) 越多。",
"DEFAULT_OVERLAY_SCALE": "默认叠加层大小",
"DEFAULT_OVERLAY_SCALE_HELP": "以该比例生成新的叠加层。",
"COLOR_PALETTE": "调色板",
"COLOR_PALETTES": "配色方案", "COLOR_PALETTES": "配色方案",
"COLOR_PALETTE_CURRENT": "当前激活的主题。", "COLOR_PALETTE_CURRENT": "当前激活的主题。",
"COLOR_PALETTE_ACTIVATE": "点击以使用此主题。",
"APPLY_CHANGES_RESTART": "重启 WayVR 以应用更改吗?",
"COLOR_PALETTE_HELP": "点击浏览配色方案。\n如需创建自定义配色请参阅网站",
"COLOR_PALETTE_CUSTOM_URL": "添加自定义主题!", "COLOR_PALETTE_CUSTOM_URL": "添加自定义主题!",
"COLOR_PALETTE_CUSTOM_URL2": "点击打开网页版手册。", "COLOR_PALETTE_CUSTOM_URL2": "点击查看网络手册",
"SNAP_ANGLE_DEG": "窗口俯仰与翻滚捕捉角度", "COLOR_PALETTE_ACTIVATE": "点击使用此主题。",
"SNAP_ANGLE_DEG_HELP": "抓取的窗口在俯仰轴和翻滚轴上将对齐到此角度。" "CLEAR_PIPEWIRE_TOKENS": "清除 PipeWire 令牌",
"CLEAR_PIPEWIRE_TOKENS_HELP": "下次启动时提示选择屏幕",
"CLEAR_SAVED_STATE": "清除保存的状态",
"CLEAR_SAVED_STATE_HELP": "重置套装与叠加层位置",
"CLICK_FREEZE_TIME_MS": "点击冻结时间 (ms)",
"CLICK_FREEZE_TIME_MS_HELP": "提高双击精度",
"CLOCK_12H": "12 小时制",
"CONTROLS": "控制",
"DELETE_ALL_CONFIGS": "重置配置",
"DELETE_ALL_CONFIGS_HELP": "删除 conf.d 中的所有配置文件",
"DOUBLE_CURSOR_FIX": "双光标修复",
"DOUBLE_CURSOR_FIX_HELP": "看到两个光标时请开启此项",
"DEFAULT_OVERLAY_SCALE": "默认叠加层大小",
"DEFAULT_OVERLAY_SCALE_HELP": "新生成的叠加层将以此比例显示。",
"DEFAULT_CURVATURE": "默认叠加层曲率",
"DEFAULT_OPACITY": "默认叠加层不透明度",
"DEFAULT_POSITIONING": "叠加层默认位置",
"OVERLAY_DEFAULTS_HELP": "仅适用于新创建的叠加层",
"ENABLED": "已启用",
"FEATURES": "功能",
"FOCUS_FOLLOWS_MOUSE_MODE": "触摸扳机移动鼠标",
"HANDSFREE_POINTER": "免手持模式",
"HANDSFREE_POINTER_HELP": "无手柄时的输入方式。\n左手捏合为抓取右手捏合为点击。",
"HANDSFREE_ALT_TAB": "应用切换器瞄准方式",
"HANDSFREE_ALT_TAB_HELP": "按住 Super+X对准目标窗口然后松开以切换焦点。",
"HIDE_GRAB_HELP": "隐藏抓取提示",
"HIDE_USERNAME": "隐藏用户名",
"INPUT_EMULATION_METHOD": "输入模拟方式",
"INPUT_EMULATION_METHOD_HELP": "如果鼠标或键盘输入没有反应,请尝试更改此项。",
"INPUT_CAPTURE_METHOD": "输入捕获方式",
"INPUT_CAPTURE_METHOD_HELP": "允许在 WayVR 中使用物理外设。\n Super+Z在 WayVR 和真实桌面之间切换输入\n Super+X在 WayVR 应用之间切换",
"INPUT_PROFILES": "修改输入绑定",
"INPUT_PROFILES_HELP": "OpenXR 控制器输入绑定",
"INVERT_SCROLL_DIRECTION_X": "反转水平滚动方向",
"INVERT_SCROLL_DIRECTION_Y": "反转垂直滚动方向",
"KEYBOARD_MIDDLE_CLICK": "键盘鼠标中键",
"KEYBOARD_MIDDLE_CLICK_HELP": "使用紫色激光输入时的\n修饰键",
"KEYBOARD_SOUND_ENABLED": "键盘声音",
"LANGUAGE": "语言",
"LEFT_HANDED_MOUSE": "左手鼠标模式",
"LEFT_HANDED_MOUSE_HELP": "若鼠标按键已互换,请启用此项",
"LONG_PRESS_DURATION": "长按时间",
"LOOK_AND_FEEL": "外观与体感",
"MISC": "其他",
"NOTIFICATIONS_ENABLED": "开启通知",
"NOTIFICATIONS_SOUND_ENABLED": "通知音效",
"NOT_SUPPORTED": "暂不支持",
"NO_SKYMAPS_FOUND": "未找到天空盒",
"OPAQUE_BACKGROUND": "不透明背景",
"OPTION": {
"ANCHORED_HELP": "随中心标记移动。推荐。",
"FLOATING_HELP": "独立移动,自动居中。\n容易丢失位置不推荐使用。",
"STATIC_HELP": "相对于世界空间保持固定。",
"AUTO": "自动",
"AUTO_HELP": "优先使用 ScreenCopy GPU\n否则使用 PipeWire GPU。",
"EYE_ONLY": "眼动激光",
"EYE_PINCH": "注视 + 捏合",
"HMD_ONLY": "HMD 激光指针",
"HMD_PINCH": "头显 + 捏合",
"NONE": "无",
"NONE_INPUT_HELP": "不模拟鼠标和键盘。\n无法与屏幕进行交互。",
"NONE_INPUT_CAPTURE_HELP": "不捕获鼠标和键盘。\n在 WayVR 中启动的应用将无法使用\n实体鼠标或键盘。",
"PIPEWIRE_HELP": "快速 GPU 采集,\n所有桌面端的标准配置。",
"PW_FALLBACK_HELP": "较慢且 CPU 占用较高。\n在 PipeWire GPU 模式无效时尝试使用。",
"SCREENCOPY_GPU_HELP": "速度快,且没有屏幕共享弹窗。\n适用于Hyprland, Niri, River, Sway",
"SCREENCOPY_HELP": "速度较慢,无屏幕共享弹窗。\n适用Hyprland, Niri, River, Sway",
"UINPUT": "设备模拟",
"UINPUT_HELP": "使用 uinput 模块来模拟设备。\n在大多数桌面环境下运行良好。",
"EVDEV_HELP": "独占捕捉输入设备。\n用户必须在 input 组中。",
"WL_VIRTUAL": "Wayland 虚拟输入",
"WL_VIRTUAL_HELP": "使用 zwlr_virtual_pointer 和 zwp_virtual_keyboard 向 Wayland 合成器发送事件。\n仅在部分桌面环境下运行稳定。\n在 KDE、GNOME 或 COSMIC 上无效。"
},
"POINTER_ACCELERATION": "鼠标加速",
"POINTER_ACCELERATION_HELP": "开启:自适应鼠标加速\n关闭恒定速度",
"POINTER_LERP_FACTOR": "光标平滑度",
"POINTER_SPEED": "鼠标速度",
"REQUIRES_RESTART": "需要重启",
"RESET_PLAYSPACE": "重置活动空间",
"RESET_PLAYSPACE_HELP": "清除活动空间的偏移量。",
"SAVE_PLAYSPACE_CENTER": "保存活动空间中心",
"SAVE_PLAYSPACE_CENTER_HELP": "将当前的活动空间设置为重置活动空间的绑定点。",
"RESET_PLAYSPACE_CENTER": "重置活动空间中心",
"RESET_PLAYSPACE_CENTER_HELP": "重置之前设置的活动空间中心。",
"RESTART_SOFTWARE": "重启软件",
"RESTART_SOFTWARE_HELP": "应用需要重启才能生效的设置",
"ROUND_MULTIPLIER": "UI 边缘圆角",
"SCREEN_RENDER_DOWN": "低分辨率渲染屏幕",
"SCREEN_RENDER_DOWN_HELP": "有助于减轻高分辨率屏幕上的锯齿现象",
"SCROLL_SPEED": "滚动速度",
"SELECT_VARIANT": "选择变体",
"SNAP_ANGLE_DEG": "窗口俯仰与翻滚吸附角度",
"SNAP_ANGLE_DEG_HELP": "抓取窗口在俯仰轴和翻滚轴上按此角度对齐。",
"ENABLE_WATCH": "启用手表",
"SETS_ON_WATCH": "手表显示套装",
"SHOW_WELCOME_SCREEN": "显示欢迎界面",
"SKYBOX": "天空图",
"SKYMAP_ALREADY_DOWNLOADED": "此天空盒已下载。请选择操作。",
"SPACE_DRAG": "活动空间",
"SPACE_DRAG_MULTIPLIER": "活动空间拖拽倍率",
"SPACE_DRAG_AFFECTS_WORLD": "移动活动空间时保留叠加层位置",
"SPACE_DRAG_UNLOCKED": "允许在所有轴向上进行空间拖拽",
"SPACE_GRAVITY_DAMPING": "阻尼",
"SPACE_GRAVITY_DAMPING_HELP": "用于减缓运动的人造阻尼。0.1 - 高阻尼1.0 - 无阻尼",
"SPACE_GRAVITY_FLING_STRENGTH": "弹射强度",
"SPACE_GRAVITY_FLING_STRENGTH_HELP": "活动空间拖拽后重力发射强度的倍数。\n0.0 - 完全不动2.0 - 强度加倍",
"SPACE_GRAVITY_GRAVITY": "重力",
"SPACE_GRAVITY_GRAVITY_HELP": "向下的力大小。0.0 - 无重力",
"SPACE_GRAVITY_GROUND_FRICTION": "地面摩擦力",
"SPACE_GRAVITY_GROUND_FRICTION_HELP": "触地时的摩擦力大小。\n0.0 - 无摩擦像在冰上一样1.0 - 粗糙表面",
"SPACE_GRAVITY_FLOOR_HEIGHT": "地板高度",
"SPACE_GRAVITY_FLOOR_HEIGHT_HELP": "地板所在的 Y 轴位置。到达此高度时重力停止作用。",
"SPACE_ROTATE_UNLOCKED": "允许活动空间在所有轴上旋转",
"TROUBLESHOOTING": "故障排除",
"UI_GRADIENT_INTENSITY": "UI 渐变强度",
"UPRIGHT_SCREEN_FIX": "垂直屏幕修复",
"UPRIGHT_SCREEN_FIX_HELP": "修复部分桌面端屏幕方向不正确的问题",
"USE_PASSTHROUGH": "启用透视模式",
"USE_PASSTHROUGH_HELP": "若 XR 运行时支持,则允许透视模式",
"USE_SKYBOX": "显示天空盒",
"USE_SKYBOX_HELP": "如果没有场景应用或透视模式,则显示天空盒",
"WATCH_VIEW_ANGLE": "手表视角范围",
"WATCH_VIEW_ANGLE_HELP": "控制手表的渐隐效果",
"WHISPER": {
"NEED_TO_DOWNLOAD_MODEL": "选中的模型需要下载。\n现在下载吗",
"REMOVE_UNUSED_MODELS": "正在关闭语音转文本功能。\n是否删除已下载的 Whisper 模型以释放空间?"
},
"WHISPER_MODEL": "语音转文本模型",
"WHISPER_MODEL_HELP": "所使用的 Whisper 模型。\n模型越大结果越准确\n但占用的显存 (VRAM) 越多。",
"GRID_OPACITY": "地面网格不透明度",
"GRID_OPACITY_HELP": "启用天空盒时地面网格的不透明度",
"XWAYLAND_BY_DEFAULT": "默认以兼容模式运行应用程序",
"SAVE": "保存",
"CANCEL": "取消"
}, },
"APPLICATION_LAUNCHER": "应用启动器", "APPLICATION_LAUNCHER": "应用启动器",
"APPLICATION_STARTED": "应用已启动", "APPLICATION_STARTED": "应用程序已启动",
"APPLICATIONS": "应用", "APPLICATIONS": "应用程序",
"AUDIO": { "AUDIO": {
"AUTO_SWITCH_TO_VR_AUDIO": "自动切换到 VR 音频", "AUTO_SWITCH_TO_VR_AUDIO": "自动切换 VR 音频",
"CARDS": "声卡", "CARDS": "声卡",
"FAILED_TO_SWITCH_MICROPHONE": "切换麦克风失败", "FAILED_TO_SWITCH_MICROPHONE": "麦克风切换失败",
"MICROPHONE_SET_SUCCESSFULLY": "麦克风设置成功", "MICROPHONE_SET_SUCCESSFULLY": "麦克风设置成功",
"MICROPHONES": "麦克风", "MICROPHONES": "麦克风",
"NO_VR_MICROPHONE_SWITCH_MANUALLY": "未找到 VR 麦克风。请手动切换。", "NO_VR_MICROPHONE_SWITCH_MANUALLY": "未找到 VR 麦克风请手动切换。",
"NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "未找到 VR 扬声器。请手动切换。", "NO_VR_SPEAKERS_FOUND_SWITCH_MANUALLY": "未检测到 VR 扬声器,请手动切换。",
"SELECT_AUDIO_CARD_PROFILE": "选择声卡配置", "SELECT_AUDIO_CARD_PROFILE": "选择声卡配置",
"SETTINGS": "音频设置", "SETTINGS": "音频设置",
"SPEAKERS": "扬声器", "SPEAKERS": "扬声器",
@ -235,84 +263,87 @@
"VOLUME": "音量" "VOLUME": "音量"
}, },
"CLOSE_WINDOW": "关闭窗口", "CLOSE_WINDOW": "关闭窗口",
"DISPLAY_BRIGHTNESS": "显示亮度", "CREATION_DATE": "创建日期",
"FAILED_TO_LAUNCH_APPLICATION": "启动应用失败:", "DEBUG_INFO": "调试信息",
"DISPLAY_BRIGHTNESS": "屏幕亮度",
"DONATE": {
"SUPPORT_US": "支持我们",
"DESCRIPTION": "我们是由两名开发者组成的小团队,在业余时间构建 WayVR。如果你喜欢这款软件请考虑支持我们 —— 每一份捐赠都能帮助我们坚持下去。",
"THANK_YOU_WAYVR": "WayVR 团队向您致谢!",
"BUTTON_TOOLTIP": "通过 Open Collective 捐赠",
"CURRENT_SUPPORTERS": "当前支持者",
"BROUGHT_TO_YOU_VARIANTS_OFTEN": "由 {USER} 赞助|感谢 {USER} 的支持|由 {USER} 助力|来自 {USER} 的贡献|{USER} 让这一切成为可能|由 {USER} 维持运行|特别感谢 {USER}|{USER} 给予了支持|由 {USER} 驱动",
"BROUGHT_TO_YOU_VARIANTS_RARE": "感谢 {USER} 的温暖支持|{USER} 为我们注入了能量|由 {USER} 助力成长|感谢 {USER} 的无私奉献|{USER} 让今天变得更美好|今日的动力源泉:{USER}|由 {USER} 悉心支持|感恩 {USER} 的陪伴|{USER} 是今天的闪光点",
"BROUGHT_TO_YOU_VARIANTS_VERY_RARE": "今日之神:{USER}|全场 MVP{USER}|{USER} 拯救了世界|给 {USER} 递上一朵小红花|由 {USER} 承包了今天的快乐|{USER} 承包了今日的电费|代码之光:{USER}|{USER} 拯救了我们的发际线|简直是超级英雄:{USER}|{USER} 让生产环境稳如老狗|唯一且无可替代的:{USER}|{USER} 是今天的顶梁柱"
},
"DOWNLOAD": "下载",
"DOWNLOADER": "下载管理器",
"WELCOME": {
"ALL_SET": "一切就绪!",
"BASICS": "掌握这些基础知识,即可轻松开始使用 WayVR。",
"CENTER_MARKER": "中心标记在重新对齐时会出现在你面前。请围绕它布置叠加层!",
"DOUBLE_PRESS_TO_TOGGLE": "双击 B 键Index或 Y 键Meta以显示、重置中心或隐藏您的套装。现在试一下吧。",
"FEATURES_DOCUMENTATION": "还有许多其他值得自定义的功能。欲了解更多信息,请参阅文档:",
"FINISH_TUTORIAL": "完成教程",
"GRAB_BOTH_HANDS": "如需移动 Set 中的特定覆盖层,请用双手抓取。",
"GRAB_ONE_HAND": "单手抓取以移动你的 Set。",
"GREETING": "你好!",
"GUIDE_INTRO": "让我们带你快速上手。",
"LASER_COLORS": "射线颜色",
"LASER_FUNCTIONALITY": "WayVR 的大部分功能取决于与 UI 元素交互时使用的激光颜色。无需按下这些按钮,只需触碰它们即可!",
"LAST_PAGE_INFO": "到达最后一页后,本教程将不再显示。",
"LOOK_AT_LEFT_WRIST": "看向你的左腕。那就是你的手表。",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "中键模式:紫色激光",
"MOVING_YOUR_SET": "移动您的 Set",
"NEXT_BUTTON": "点击下方“下一步”按钮开始。",
"REGULAR_MODE_BLUE_LASER": "普通模式:蓝色激光",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "使用控制器的抓取操作来重新定位此窗口。",
"RIGHT_CLICK_MODE_ORANGE_LASER": "右键模式:橙色激光",
"THANKS_FOR_INSTALLING": "感谢安装 WayVR",
"WATCH": "手表",
"WORKING_SET": "当前套装"
},
"DOWNLOAD_AGAIN": "重新下载",
"DOWNLOADING_FILE": "正在下载文件...",
"FAILED_TO_LAUNCH_APPLICATION": "启动应用程序失败:",
"GAME_LAUNCHED": "游戏已启动", "GAME_LAUNCHED": "游戏已启动",
"GAME_LIST": { "GAME_LIST": {
"NO_GAMES_FOUND": "未找到游戏", "NO_GAMES_FOUND": "未找到游戏",
"RUNNING_GAMES_LIST": "正在运行的游戏列表" "RUNNING_GAMES_LIST": "运行的游戏列表"
}, },
"GAMES": "游戏", "GAMES": "游戏",
"GENERAL_SETTINGS": "通用设置", "GENERAL_SETTINGS": "常规设置",
"GETTING_STARTED": "快速入门",
"HEIGHT": "高度", "HEIGHT": "高度",
"HELLO": "你好!", "HELLO": "你好!",
"HELLO_USER": "你好,{USER}", "HELLO_USER": "你好,{USER}",
"HIDE": "隐藏", "HIDE": "隐藏",
"HOME_SCREEN": "主页", "HOME_SCREEN": "首页",
"MODIFICATION_DATE": "修改日期",
"MONADO_RUNTIME": "Monado 运行时", "MONADO_RUNTIME": "Monado 运行时",
"LOADING": "加载中...",
"POPUP_ADD_DISPLAY": { "POPUP_ADD_DISPLAY": {
"RESOLUTION": "分辨率" "RESOLUTION": "分辨率"
}, },
"REMOVE": "移除", "PROCESS": {
"SETTINGS": "设置", "FORCE_KILL": "强制结束",
"SHOW": "显示", "STOP": "停止"
"TERMINATE_PROCESS": "终止进程", },
"WIDTH": "宽度",
"PROCESS_LIST": "进程列表", "PROCESS_LIST": "进程列表",
"REFRESH": "刷新", "REFRESH": "刷新",
"PROCESS": { "REMOVE": "移除",
"STOP": "停止",
"FORCE_KILL": "强制关闭"
},
"DEBUG_INFO": "调试信息",
"CREATION_DATE": "创建日期",
"DOWNLOADER": "下载器",
"DOWNLOAD_AGAIN": "重新下载",
"DOWNLOADING_FILE": "正在下载文件...",
"GETTING_STARTED": "入门指南",
"MODIFICATION_DATE": "修改日期",
"LOADING": "正在加载...",
"APPLY": "应用", "APPLY": "应用",
"RELOAD_FROM_DISK": "从磁盘重新加载", "RELOAD_FROM_DISK": "从磁盘重新加载",
"SETTINGS": "设置",
"SHOW": "显示",
"TARGET_PATH": "目标路径", "TARGET_PATH": "目标路径",
"TERMINATE_PROCESS": "终止进程",
"VERSION": "版本", "VERSION": "版本",
"DONATE": { "WIDTH": "宽度",
"SUPPORT_US": "支持我们", "PINNED_APPS": "固定应用",
"DESCRIPTION": "我们是一个由 2 名开发者组成的精简团队,在业余时间开发 WayVR。如果您喜欢这款软件请考虑支持我们 —— 每一次捐赠都能帮助我们继续开发下去。", "SAVED_TO_FAVOURITES": "已添加到固定应用",
"BUTTON_TOOLTIP": "通过 Open Collective 捐赠", "ADD_TO_FAVOURITES": "添加到固定应用",
"CURRENT_SUPPORTERS": "当前支持者",
"THANK_YOU_WAYVR": "WayVR 团队向您表示感谢!"
},
"WELCOME": {
"ALL_SET": "你已准备就绪!",
"BASICS": "这些基础知识将帮助您轻松开始使用 WayVR。",
"FEATURES_DOCUMENTATION": "还有许多其他值得自定义的功能。欲了解更多信息,请查看文档:",
"FINISH_TUTORIAL": "完成教程",
"GRAB_BOTH_HANDS": "如果你想移动 Set 中的特定叠加层,请用双手抓取。",
"GRAB_ONE_HAND": "用一只手抓取即可移动你的 Set。",
"GREETING": "你好!",
"GUIDE_INTRO": "让我们引导你完成初步设置。",
"LASER_COLORS": "激光颜色",
"LASER_FUNCTIONALITY": "WayVR 中的许多功能都取决于使用何种颜色的激光来与 UI 元素进行交互。您不需要按下这些按钮,只需触摸它们即可!",
"LAST_PAGE_INFO": "一旦你到达最后一页,此教程将不再显示。",
"LOOK_AT_LEFT_WRIST": "看向你的左手腕。那就是你的手表。",
"MIDDLE_CLICK_MODE_PURPLE_LASER": "— 中键模式:紫色激光",
"MOVING_YOUR_SET": "正在移动您的 Set",
"NEXT_BUTTON": "按下下方的“下一步”按钮以开始。",
"REGULAR_MODE_BLUE_LASER": "— 普通模式:蓝色激光",
"REPOSITION_THIS_WINDOW_BY_GRABBING": "使用控制器的抓取操作重新定位此窗口。",
"RIGHT_CLICK_MODE_ORANGE_LASER": "— 右键模式:橙色激光",
"THANKS_FOR_INSTALLING": "感谢安装 WayVR",
"WATCH": "Watch",
"WORKING_SET": "工作集",
"DOUBLE_PRESS_TO_TOGGLE": "双击 B 键 (Index) 或 Y 键 (Meta) 以显示、重新居中或隐藏您的集合。现在就试一下吧。",
"CENTER_MARKER": "中心标记是重新居中时出现在你面前的标志。请将覆盖层放置在它周围!"
},
"DOWNLOAD": "下载",
"SAVED_TO_FAVOURITES": "已保存至收藏夹",
"ADD_TO_FAVOURITES": "添加到收藏",
"ADD_TO_FAVOURITES_HINT": "保存预设并将其固定到应用抽屉", "ADD_TO_FAVOURITES_HINT": "保存预设并将其固定到应用抽屉",
"REMOVE_FROM_FAVOURITES": "从收藏中移除", "REMOVE_FROM_FAVOURITES": "从固定应用中移除",
"EMPTY": "空", "EMPTY": "暂无"
"PINNED_APPS": "已固定应用程序"
} }

View File

@ -22,7 +22,7 @@ use wgui::{
use wlx_common::{ use wlx_common::{
async_executor::AsyncExecutor, async_executor::AsyncExecutor,
audio, audio,
dash_interface::{BoxDashInterface, ConfigChangeKind, RecenterMode}, dash_interface::{BoxDashInterface, ConfigChangeKind, DashPlayspaceTask},
locale::WayVRLangProvider, locale::WayVRLangProvider,
palette::load_palette, palette::load_palette,
timestep::{self, Timestep}, timestep::{self, Timestep},
@ -56,7 +56,7 @@ pub struct Frontend<T> {
pub interface: BoxDashInterface<T>, pub interface: BoxDashInterface<T>,
// async runtime executor // single-threaded async runtime executor
pub executor: AsyncExecutor, pub executor: AsyncExecutor,
#[allow(dead_code)] #[allow(dead_code)]
@ -98,6 +98,7 @@ pub struct InitParams<'a, T> {
pub has_monado: bool, pub has_monado: bool,
pub theme: Rc<WguiTheme>, pub theme: Rc<WguiTheme>,
pub color_palette: &'a str, pub color_palette: &'a str,
pub executor: AsyncExecutor,
} }
#[derive(Clone)] #[derive(Clone)]
@ -202,7 +203,7 @@ impl<T: 'static> Frontend<T> {
toast_manager, toast_manager,
window_audio_settings: WguiWindow::default(), window_audio_settings: WguiWindow::default(),
view_audio_settings: None, view_audio_settings: None,
executor: Rc::new(smol::LocalExecutor::new()), executor: params.executor,
sounds_to_play: Vec::new(), sounds_to_play: Vec::new(),
}; };
@ -254,9 +255,6 @@ impl<T: 'static> Frontend<T> {
self.current_tab = Some(tab); self.current_tab = Some(tab);
} }
// process async runtime tasks
while self.executor.try_tick() {}
let res = self.tick(params)?; let res = self.tick(params)?;
self.ticks += 1; self.ticks += 1;
@ -553,7 +551,7 @@ impl<T: 'static> Frontend<T> {
} }
fn action_recenter_playspace(&mut self, data: &mut T) -> anyhow::Result<()> { fn action_recenter_playspace(&mut self, data: &mut T) -> anyhow::Result<()> {
self.interface.recenter_playspace(data, RecenterMode::Recenter)?; self.interface.playspace_task(data, DashPlayspaceTask::Recenter)?;
Ok(()) Ok(())
} }

View File

@ -1,6 +1,7 @@
mod assets; mod assets;
pub mod frontend; pub mod frontend;
mod tab; mod tab;
mod test;
mod util; mod util;
mod various; mod various;
mod views; mod views;

View File

@ -4,19 +4,23 @@ use wgui::{
assets::AssetPath, assets::AssetPath,
components::button::ComponentButton, components::button::ComponentButton,
globals::WguiGlobals, globals::WguiGlobals,
layout::WidgetID, layout::{Layout, WidgetID},
parser::{Fetchable, ParseDocumentParams, ParserState}, parser::{Fetchable, ParseDocumentParams, ParserState, TemplateParams},
taffy::{self, style_helpers::length},
task::Tasks, task::Tasks,
widget::div::WidgetDiv,
}; };
use crate::{ use crate::{
frontend::{Frontend, FrontendTask}, frontend::{Frontend, FrontendTask},
tab::{Tab, TabType}, tab::{Tab, TabType},
util::cached_fetcher,
}; };
#[derive(Clone)]
#[allow(clippy::enum_variant_names)] #[allow(clippy::enum_variant_names)]
enum Task {} enum Task {
SetSupporters(cached_fetcher::Supporters),
}
pub struct TabDonate<T> { pub struct TabDonate<T> {
#[allow(dead_code)] #[allow(dead_code)]
@ -24,6 +28,8 @@ pub struct TabDonate<T> {
marker: PhantomData<T>, marker: PhantomData<T>,
#[allow(dead_code)] #[allow(dead_code)]
tasks: Tasks<Task>, tasks: Tasks<Task>,
id_current_supporters: WidgetID,
} }
impl<T> Tab<T> for TabDonate<T> { impl<T> Tab<T> for TabDonate<T> {
@ -31,10 +37,14 @@ impl<T> Tab<T> for TabDonate<T> {
TabType::Donate TabType::Donate
} }
fn update(&mut self, _frontend: &mut Frontend<T>, _time_ms: u32, _user_data: &mut T) -> anyhow::Result<()> { fn update(&mut self, frontend: &mut Frontend<T>, _time_ms: u32, _user_data: &mut T) -> anyhow::Result<()> {
// for task in self.tasks.drain() { while !self.tasks.is_empty() {
// match task {} for task in self.tasks.drain() {
// } match task {
Task::SetSupporters(supporters) => self.set_supporters(&mut frontend.layout, supporters)?,
}
}
}
Ok(()) Ok(())
} }
@ -48,9 +58,62 @@ fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
} }
} }
async fn request_supporters(tasks: Tasks<Task>) {
if let Some(supporters) = cached_fetcher::request_supporters().await {
tasks.push(Task::SetSupporters(supporters))
}
}
impl<T> TabDonate<T> { impl<T> TabDonate<T> {
fn set_supporters(&mut self, layout: &mut Layout, supporters: cached_fetcher::Supporters) -> anyhow::Result<()> {
let globals = layout.state.globals.clone();
layout.remove_children(self.id_current_supporters);
let mut current_tier = None;
let mut tier_parent = WidgetID::default();
for supporter in &supporters.supporters {
if Some(supporter.tier) != current_tier {
current_tier = Some(supporter.tier);
let mut params = TemplateParams::new();
params.insert_str("text", supporter.tier.pretty_str());
params.insert("color", supporter.tier.color_str());
self.state.realize_template(
&doc_params(&globals),
"TierCell",
layout,
self.id_current_supporters,
params,
)?;
tier_parent = layout
.add_child(
self.id_current_supporters,
WidgetDiv::create(),
taffy::Style {
gap: length(8.0_f32),
flex_wrap: taffy::FlexWrap::Wrap,
..Default::default()
},
)?
.0
.id;
}
let mut params = TemplateParams::new();
params.insert("username", &supporter.username);
self
.state
.realize_template(&doc_params(&globals), "SupporterCell", layout, tier_parent, params)?;
}
Ok(())
}
pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, _data: &mut T) -> anyhow::Result<Self> { pub fn new(frontend: &mut Frontend<T>, parent_id: WidgetID, _data: &mut T) -> anyhow::Result<Self> {
let state = wgui::parser::parse_from_assets(&doc_params(&frontend.globals), &mut frontend.layout, parent_id)?; let state = wgui::parser::parse_from_assets(&doc_params(&frontend.globals), &mut frontend.layout, parent_id)?;
let id_current_supporters = state.get_widget_id("current_supporters")?;
frontend.tasks.handle_button( frontend.tasks.handle_button(
&state.fetch_component_as::<ComponentButton>("btn_donate")?, &state.fetch_component_as::<ComponentButton>("btn_donate")?,
@ -59,10 +122,13 @@ impl<T> TabDonate<T> {
let tasks = Tasks::<Task>::new(); let tasks = Tasks::<Task>::new();
frontend.executor.spawn(request_supporters(tasks.clone())).detach();
Ok(Self { Ok(Self {
state, state,
marker: PhantomData, marker: PhantomData,
tasks, tasks,
id_current_supporters,
}) })
} }
} }

View File

@ -1,11 +1,13 @@
use std::marker::PhantomData; use std::{marker::PhantomData, rc::Rc};
use wgui::{ use wgui::{
animation::{Animation, AnimationEasing},
assets::AssetPath, assets::AssetPath,
components::button::ComponentButton, color::{WguiColor, WguiColorName, WguiNamedColor},
components::{ComponentTrait, button::ComponentButton},
event::CallbackDataCommon, event::CallbackDataCommon,
i18n::Translation, i18n::Translation,
layout::{Widget, WidgetID}, layout::{LayoutTask, LayoutTasks, Widget, WidgetID},
parser::{Fetchable, ParseDocumentParams, ParserState}, parser::{Fetchable, ParseDocumentParams, ParserState},
widget::label::WidgetLabel, widget::label::WidgetLabel,
}; };
@ -14,6 +16,7 @@ use wlx_common::config::GeneralConfig;
use crate::{ use crate::{
frontend::{Frontend, FrontendTask}, frontend::{Frontend, FrontendTask},
tab::{Tab, TabType}, tab::{Tab, TabType},
util::cached_fetcher,
various, various,
}; };
@ -29,14 +32,101 @@ impl<T> Tab<T> for TabHome<T> {
} }
} }
fn configure_label_hello(common: &mut CallbackDataCommon, label_hello: Widget, config: &GeneralConfig) { fn get_supporter_anim(
let mut username = various::get_username(); btn: Rc<ComponentButton>,
// first character as uppercase tasks: LayoutTasks,
if let Some(first) = username.chars().next() { supporters: Rc<cached_fetcher::Supporters>,
let first = first.to_uppercase().to_string(); prev_supporter_name: String,
username.replace_range(0..1, &first); ) -> Animation {
let username = loop {
let total_tickets: u32 = supporters.supporters.iter().map(|s| s.tickets()).sum();
let jackpot = rand::random_range(0..total_tickets);
let mut cumulative = 0u32;
let random_supporter = supporters
.supporters
.iter()
.find(|s| {
cumulative += s.tickets();
cumulative >= jackpot
})
.unwrap();
let username = random_supporter.username.clone();
if username != prev_supporter_name {
break username;
}
};
const FADE_SPEED: f32 = 10.0;
Animation::new_ex(
btn.base().get_id(),
1234,
480,
AnimationEasing::Linear,
Box::new(move |common, data| {
let opacity_in = f32::clamp(data.pos * FADE_SPEED, 0.0, 1.0);
let opacity_out = f32::clamp((1.0 - data.pos) * FADE_SPEED, 0.0, 1.0);
let opacity = f32::min(opacity_in, opacity_out);
btn.set_text_color(
common,
WguiColor::Named(WguiNamedColor::with_alpha(WguiColorName::OnBackgroundVariant, opacity)),
);
// first iter
if data.pos == 0.0 {
let translation_key = match rand::random::<u8>() {
0..=15 => "DONATE.BROUGHT_TO_YOU_VARIANTS_VERY_RARE",
16..=70 => "DONATE.BROUGHT_TO_YOU_VARIANTS_RARE",
71..=u8::MAX => "DONATE.BROUGHT_TO_YOU_VARIANTS_OFTEN",
};
let translated = common.globals().i18n_builtin.translate(translation_key);
let variants = translated.split('|').collect::<Vec<&str>>();
let variant = variants[rand::random_range(0..variants.len() - 1)];
btn.set_text(
common,
Translation::from_raw_text_string(variant.replace("{USER}", &username)),
);
}
// last iter
if data.pos == 1.0 {
// infinitely looped animation, re-trigger it.
tasks.push(LayoutTask::PlayAnimation(get_supporter_anim(
btn.clone(),
tasks.clone(),
supporters.clone(),
username.clone(), /* prev supporter name */
)))
}
}),
)
}
async fn config_supporters(btn: Rc<ComponentButton>, tasks: LayoutTasks) {
let Some(supporters) = cached_fetcher::request_supporters().await else {
return;
};
if supporters.supporters.len() <= 2 {
return; // Welp.
} }
let supporters = Rc::new(supporters);
tasks.push(LayoutTask::PlayAnimation(get_supporter_anim(
btn,
tasks.clone(),
supporters,
String::new(),
)));
}
fn configure_label_hello(common: &mut CallbackDataCommon, label_hello: Widget, config: &GeneralConfig) {
let username = wlx_common::locale::capitalize_string(&various::get_username());
let translated = if !config.hide_username { let translated = if !config.hide_username {
common.i18n().translate_and_replace("HELLO_USER", ("{USER}", &username)) common.i18n().translate_and_replace("HELLO_USER", ("{USER}", &username))
} else { } else {
@ -66,6 +156,8 @@ impl<T> TabHome<T> {
frontend.interface.general_config(data), frontend.interface.general_config(data),
); );
let btn_supporter = state.fetch_component_as::<ComponentButton>("btn_supporter")?;
let btn_apps = state.fetch_component_as::<ComponentButton>("btn_apps")?; let btn_apps = state.fetch_component_as::<ComponentButton>("btn_apps")?;
let btn_games = state.fetch_component_as::<ComponentButton>("btn_games")?; let btn_games = state.fetch_component_as::<ComponentButton>("btn_games")?;
let btn_monado = state.fetch_component_as::<ComponentButton>("btn_monado")?; let btn_monado = state.fetch_component_as::<ComponentButton>("btn_monado")?;
@ -74,14 +166,20 @@ impl<T> TabHome<T> {
let btn_donate = state.fetch_component_as::<ComponentButton>("btn_donate")?; let btn_donate = state.fetch_component_as::<ComponentButton>("btn_donate")?;
let btn_website = state.fetch_component_as::<ComponentButton>("btn_website")?; let btn_website = state.fetch_component_as::<ComponentButton>("btn_website")?;
let tasks = &mut frontend.tasks; let f_tasks = &mut frontend.tasks;
tasks.handle_button(&btn_apps, FrontendTask::SetTab(TabType::Apps)); f_tasks.handle_button(&btn_apps, FrontendTask::SetTab(TabType::Apps));
tasks.handle_button(&btn_games, FrontendTask::SetTab(TabType::Games)); f_tasks.handle_button(&btn_games, FrontendTask::SetTab(TabType::Games));
tasks.handle_button(&btn_monado, FrontendTask::SetTab(TabType::Monado)); f_tasks.handle_button(&btn_monado, FrontendTask::SetTab(TabType::Monado));
tasks.handle_button(&btn_settings, FrontendTask::SetTab(TabType::Settings)); f_tasks.handle_button(&btn_settings, FrontendTask::SetTab(TabType::Settings));
tasks.handle_button(&btn_welcome_screen, FrontendTask::SetTab(TabType::Welcome)); f_tasks.handle_button(&btn_welcome_screen, FrontendTask::SetTab(TabType::Welcome));
tasks.handle_button(&btn_donate, FrontendTask::SetTab(TabType::Donate)); f_tasks.handle_button(&btn_donate, FrontendTask::SetTab(TabType::Donate));
tasks.handle_button(&btn_website, FrontendTask::OpenURL("https://wayvr.org".into())); f_tasks.handle_button(&btn_supporter, FrontendTask::SetTab(TabType::Donate));
f_tasks.handle_button(&btn_website, FrontendTask::OpenURL("https://wayvr.org".into()));
frontend
.executor
.spawn(config_supporters(btn_supporter, frontend.layout.tasks.clone()))
.detach();
Ok(Self { Ok(Self {
state, state,

View File

@ -24,7 +24,7 @@ pub enum TabType {
impl TabType { impl TabType {
pub fn get_preferred_padding(&self) -> f32 { pub fn get_preferred_padding(&self) -> f32 {
match self { match self {
TabType::Welcome | TabType::Donate => 0.0, TabType::Welcome => 0.0,
_ => 16.0, _ => 16.0,
} }
} }

View File

@ -51,7 +51,7 @@ enum Task {
// `ProcessList` tab // `ProcessList` tab
ProcessListRefresh, ProcessListRefresh,
ProcessListFocusClient(String), ProcessListFocusClient(i64),
// `DebugTimings` tab // `DebugTimings` tab
DebugTimingsRefreshSessionList, DebugTimingsRefreshSessionList,
@ -157,9 +157,9 @@ impl<T> Tab<T> for TabMonado<T> {
process_list.refresh(frontend, data, &self.tasks)?; process_list.refresh(frontend, data, &self.tasks)?;
} }
} }
Task::ProcessListFocusClient(client_name) => { Task::ProcessListFocusClient(client_id) => {
if let Subtab::ProcessList(process_list) = &mut self.subtab { if let Subtab::ProcessList(process_list) = &mut self.subtab {
process_list.focus_client(frontend, data, client_name, &self.tasks)?; process_list.focus_client(frontend, data, client_id, &self.tasks)?;
} }
} }
Task::DebugTimingsRefreshSessionList => { Task::DebugTimingsRefreshSessionList => {
@ -676,10 +676,10 @@ impl SubtabProcessList {
let checkbox = state_cell.fetch_component_as::<ComponentCheckbox>("checkbox")?; let checkbox = state_cell.fetch_component_as::<ComponentCheckbox>("checkbox")?;
checkbox.on_toggle({ checkbox.on_toggle({
let tasks = tasks.clone(); let tasks = tasks.clone();
let client_name = client.name.clone(); let client_id = client.id;
Box::new(move |_common, e| { Box::new(move |_common, e| {
if e.checked { if e.checked {
tasks.push(Task::ProcessListFocusClient(client_name.clone())); tasks.push(Task::ProcessListFocusClient(client_id));
} }
Ok(()) Ok(())
}) })
@ -694,10 +694,10 @@ impl SubtabProcessList {
&mut self, &mut self,
frontend: &mut Frontend<T>, frontend: &mut Frontend<T>,
data: &mut T, data: &mut T,
name: String, client_id: i64,
tasks: &Tasks<Task>, tasks: &Tasks<Task>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
frontend.interface.monado_client_focus(data, &name)?; frontend.interface.monado_client_focus(data, client_id)?;
tasks.push(Task::ProcessListRefresh); tasks.push(Task::ProcessListRefresh);
Ok(()) Ok(())
} }

View File

@ -13,7 +13,7 @@ use wgui::{
widget::label::WidgetLabel, widget::label::WidgetLabel,
windowing::context_menu, windowing::context_menu,
}; };
use wlx_common::config::GeneralConfig; use wlx_common::{DesktopBackend, XrBackend, config::GeneralConfig, dash_interface::InterfaceFeats};
pub fn options_category( pub fn options_category(
mp: &mut MacroParams, mp: &mut MacroParams,
@ -272,6 +272,7 @@ where
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?; let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
btn.on_click(Rc::new({ btn.on_click(Rc::new({
let feats = mp.feats;
let tasks = mp.tasks.clone(); let tasks = mp.tasks.clone();
move |_common, e: ButtonClickEvent| { move |_common, e: ButtonClickEvent| {
tasks.push(Task::OpenContextMenu( tasks.push(Task::OpenContextMenu(
@ -282,6 +283,18 @@ where
if item.get_bool("Hidden").unwrap_or(false) { if item.get_bool("Hidden").unwrap_or(false) {
return None; return None;
} }
if item
.get_str("Backend")
.is_some_and(|x| XrBackend::try_from(x).unwrap() != feats.xr_backend)
{
return None;
}
if item
.get_str("Desktop")
.is_some_and(|x| DesktopBackend::try_from(x).unwrap() != feats.desktop_backend)
{
return None;
}
let value = item.as_ref(); let value = item.as_ref();
let title = SettingType::get_enum_title_inner(*item); let title = SettingType::get_enum_title_inner(*item);
@ -336,6 +349,36 @@ pub fn options_danger_button(
Ok(()) Ok(())
} }
pub fn options_button(
mp: &mut MacroParams,
parent: WidgetID,
translation: &str,
icon: &str,
task: Task,
) -> anyhow::Result<()> {
let id = mp.idx.to_string();
mp.idx += 1;
let mut params = TemplateParams::new();
params.insert("id", &id);
params.insert("translation", translation);
params.insert("icon", icon);
mp.parser_state
.instantiate_template(mp.doc_params, "ButtonText", mp.layout, parent, params)?;
let btn = mp.parser_state.fetch_component_as::<ComponentButton>(&id)?;
btn.on_click(Rc::new({
let tasks = mp.tasks.clone();
move |_common, _e| {
tasks.push(task.clone());
Ok(())
}
}));
Ok(())
}
pub fn options_autostart_app( pub fn options_autostart_app(
mp: &mut MacroParams, mp: &mut MacroParams,
parent: WidgetID, parent: WidgetID,
@ -374,4 +417,5 @@ pub struct MacroParams<'a> {
pub config: &'a mut GeneralConfig, pub config: &'a mut GeneralConfig,
pub tasks: Tasks<settings::Task>, pub tasks: Tasks<settings::Task>,
pub idx: usize, pub idx: usize,
pub feats: InterfaceFeats,
} }

View File

@ -23,7 +23,7 @@ use wgui::{
use wlx_common::{ use wlx_common::{
config::GeneralConfig, config::GeneralConfig,
config_io::ConfigRoot, config_io::ConfigRoot,
dash_interface::{ConfigChangeKind, InterfaceFeats, RecenterMode}, dash_interface::{ConfigChangeKind, DashPlayspaceTask, InterfaceFeats},
}; };
use crate::{ use crate::{
@ -78,7 +78,9 @@ pub(crate) enum Task {
OpenContextMenu(Vec2, Vec<context_menu::Cell>), OpenContextMenu(Vec2, Vec<context_menu::Cell>),
RemoveAutostartApp(Rc<str>), RemoveAutostartApp(Rc<str>),
ResetPlayspace, ResetPlayspace,
ResetPlayspaceCenter,
RestartSoftware, RestartSoftware,
SavePlayspaceCenter,
SetTab(TabNameEnum), SetTab(TabNameEnum),
SettingUpdated(SettingType), SettingUpdated(SettingType),
UpdateBool(SettingType, bool), UpdateBool(SettingType, bool),
@ -200,8 +202,18 @@ impl<T> Tab<T> for TabSettings<T> {
std::fs::remove_dir_all(&path)?; std::fs::remove_dir_all(&path)?;
std::fs::create_dir(&path)?; std::fs::create_dir(&path)?;
} }
Task::SavePlayspaceCenter => {
frontend.interface.playspace_task(data, DashPlayspaceTask::SaveCenter)?;
return Ok(());
}
Task::ResetPlayspaceCenter => {
frontend
.interface
.playspace_task(data, DashPlayspaceTask::ResetCenter)?;
return Ok(());
}
Task::ResetPlayspace => { Task::ResetPlayspace => {
frontend.interface.recenter_playspace(data, RecenterMode::Reset)?; frontend.interface.playspace_task(data, DashPlayspaceTask::Reset)?;
return Ok(()); return Ok(());
} }
Task::RestartSoftware => { Task::RestartSoftware => {
@ -299,12 +311,19 @@ pub(crate) enum SettingType {
CaptureMethod, CaptureMethod,
ClickFreezeTimeMs, ClickFreezeTimeMs,
Clock12h, Clock12h,
DefaultCurvature,
DefaultOpacity,
DefaultOverlayScale,
DefaultPositioning,
DoubleCursorFix, DoubleCursorFix,
EnableWatch,
FocusFollowsMouseMode, FocusFollowsMouseMode,
GridOpacity, GridOpacity,
HandsfreeAltTab,
HandsfreePointer, HandsfreePointer,
HideGrabHelp, HideGrabHelp,
HideUsername, HideUsername,
InputCaptureMethod,
InputEmulationMethod, InputEmulationMethod,
InvertScrollDirectionX, InvertScrollDirectionX,
InvertScrollDirectionY, InvertScrollDirectionY,
@ -315,14 +334,15 @@ pub(crate) enum SettingType {
LongPressDuration, LongPressDuration,
NotificationsEnabled, NotificationsEnabled,
NotificationsSoundEnabled, NotificationsSoundEnabled,
DefaultOverlayScale,
OpaqueBackground, OpaqueBackground,
MouseAcceleration,
PointerLerpFactor, PointerLerpFactor,
MouseSpeed,
ScreenRenderDown, ScreenRenderDown,
ScrollSpeed, ScrollSpeed,
SnapAngleDeg, SnapAngleDeg,
EnableWatch,
SetsOnWatch, SetsOnWatch,
SpaceDragAffectsWorld,
SpaceDragMultiplier, SpaceDragMultiplier,
SpaceDragUnlocked, SpaceDragUnlocked,
SpaceGravityDamping, SpaceGravityDamping,
@ -346,6 +366,7 @@ pub(crate) enum SettingType {
impl SettingType { impl SettingType {
pub fn change_kind(self) -> ConfigChangeKind { pub fn change_kind(self) -> ConfigChangeKind {
match self { match self {
Self::MouseAcceleration | Self::MouseSpeed => ConfigChangeKind::WvrServerConfig,
Self::UseSkybox | Self::UsePassthrough => ConfigChangeKind::EnvironmentBlend, Self::UseSkybox | Self::UsePassthrough => ConfigChangeKind::EnvironmentBlend,
_ => ConfigChangeKind::OverlayConfig, _ => ConfigChangeKind::OverlayConfig,
} }
@ -370,8 +391,10 @@ impl SettingType {
Self::NotificationsEnabled => &mut config.notifications_enabled, Self::NotificationsEnabled => &mut config.notifications_enabled,
Self::NotificationsSoundEnabled => &mut config.notifications_sound_enabled, Self::NotificationsSoundEnabled => &mut config.notifications_sound_enabled,
Self::OpaqueBackground => &mut config.opaque_background, Self::OpaqueBackground => &mut config.opaque_background,
Self::MouseAcceleration => &mut config.wvr_mouse_acceleration,
Self::ScreenRenderDown => &mut config.screen_render_down, Self::ScreenRenderDown => &mut config.screen_render_down,
Self::SetsOnWatch => &mut config.sets_on_watch, Self::SetsOnWatch => &mut config.sets_on_watch,
Self::SpaceDragAffectsWorld => &mut config.space_drag_affects_world,
Self::SpaceDragUnlocked => &mut config.space_drag_unlocked, Self::SpaceDragUnlocked => &mut config.space_drag_unlocked,
Self::SpaceGravityEnabled => &mut config.space_gravity_enabled, Self::SpaceGravityEnabled => &mut config.space_gravity_enabled,
Self::SpaceRotateUnlocked => &mut config.space_rotate_unlocked, Self::SpaceRotateUnlocked => &mut config.space_rotate_unlocked,
@ -385,10 +408,13 @@ impl SettingType {
pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 { pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 {
match self { match self {
Self::DefaultCurvature => &mut config.default_curvature,
Self::DefaultOpacity => &mut config.default_opacity,
Self::DefaultOverlayScale => &mut config.default_overlay_scale, Self::DefaultOverlayScale => &mut config.default_overlay_scale,
Self::GridOpacity => &mut config.grid_opacity, Self::GridOpacity => &mut config.grid_opacity,
Self::LongPressDuration => &mut config.long_press_duration, Self::LongPressDuration => &mut config.long_press_duration,
Self::PointerLerpFactor => &mut config.pointer_lerp_factor, Self::PointerLerpFactor => &mut config.pointer_lerp_factor,
Self::MouseSpeed => &mut config.wvr_mouse_speed,
Self::ScrollSpeed => &mut config.scroll_speed, Self::ScrollSpeed => &mut config.scroll_speed,
Self::SnapAngleDeg => &mut config.snap_angle_deg, Self::SnapAngleDeg => &mut config.snap_angle_deg,
Self::SpaceDragMultiplier => &mut config.space_drag_multiplier, Self::SpaceDragMultiplier => &mut config.space_drag_multiplier,
@ -418,6 +444,13 @@ impl SettingType {
Self::CaptureMethod => { Self::CaptureMethod => {
config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!") config.capture_method = wlx_common::config::CaptureMethod::from_str(value).expect("Invalid enum value!")
} }
Self::DefaultPositioning => {
config.default_positioning =
wlx_common::config::DefaultPositioning::from_str(value).expect("Invalid enum value!")
}
Self::InputCaptureMethod => {
config.wvr_input_capture = wlx_common::config::InputCaptureMethod::from_str(value).expect("Invalid enum value!")
}
Self::InputEmulationMethod => { Self::InputEmulationMethod => {
config.input_emulation_method = config.input_emulation_method =
wlx_common::config::InputEmulationMethod::from_str(value).expect("Invalid enum value!") wlx_common::config::InputEmulationMethod::from_str(value).expect("Invalid enum value!")
@ -426,6 +459,9 @@ impl SettingType {
config.keyboard_middle_click_mode = config.keyboard_middle_click_mode =
wlx_common::config::AltModifier::from_str(value).expect("Invalid enum value!") wlx_common::config::AltModifier::from_str(value).expect("Invalid enum value!")
} }
Self::HandsfreeAltTab => {
config.handsfree_alt_tab = wlx_common::config::HandsfreeAltTab::from_str(value).expect("Invalid enum value!")
}
Self::HandsfreePointer => { Self::HandsfreePointer => {
config.handsfree_pointer = wlx_common::config::HandsfreePointer::from_str(value).expect("Invalid enum value!") config.handsfree_pointer = wlx_common::config::HandsfreePointer::from_str(value).expect("Invalid enum value!")
} }
@ -439,9 +475,12 @@ impl SettingType {
fn get_enum_title(self, config: &mut GeneralConfig) -> Translation { fn get_enum_title(self, config: &mut GeneralConfig) -> Translation {
match self { match self {
Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method), Self::CaptureMethod => Self::get_enum_title_inner(config.capture_method),
Self::DefaultPositioning => Self::get_enum_title_inner(config.default_positioning),
Self::InputCaptureMethod => Self::get_enum_title_inner(config.wvr_input_capture),
Self::InputEmulationMethod => Self::get_enum_title_inner(config.input_emulation_method), Self::InputEmulationMethod => Self::get_enum_title_inner(config.input_emulation_method),
Self::KeyboardMiddleClick => Self::get_enum_title_inner(config.keyboard_middle_click_mode), Self::KeyboardMiddleClick => Self::get_enum_title_inner(config.keyboard_middle_click_mode),
Self::HandsfreePointer => Self::get_enum_title_inner(config.handsfree_pointer), Self::HandsfreePointer => Self::get_enum_title_inner(config.handsfree_pointer),
Self::HandsfreeAltTab => Self::get_enum_title_inner(config.handsfree_alt_tab),
Self::Language => match &config.language { Self::Language => match &config.language {
Some(lang) => Self::get_enum_title_inner(*lang), Some(lang) => Self::get_enum_title_inner(*lang),
None => Translation::from_translation_key("APP_SETTINGS.OPTION.AUTO"), None => Translation::from_translation_key("APP_SETTINGS.OPTION.AUTO"),
@ -479,13 +518,18 @@ impl SettingType {
Self::CaptureMethod => Ok("APP_SETTINGS.CAPTURE_METHOD"), Self::CaptureMethod => Ok("APP_SETTINGS.CAPTURE_METHOD"),
Self::ClickFreezeTimeMs => Ok("APP_SETTINGS.CLICK_FREEZE_TIME_MS"), Self::ClickFreezeTimeMs => Ok("APP_SETTINGS.CLICK_FREEZE_TIME_MS"),
Self::Clock12h => Ok("APP_SETTINGS.CLOCK_12H"), Self::Clock12h => Ok("APP_SETTINGS.CLOCK_12H"),
Self::DefaultCurvature => Ok("APP_SETTINGS.DEFAULT_CURVATURE"),
Self::DefaultOpacity => Ok("APP_SETTINGS.DEFAULT_OPACITY"),
Self::DefaultOverlayScale => Ok("APP_SETTINGS.DEFAULT_OVERLAY_SCALE"), Self::DefaultOverlayScale => Ok("APP_SETTINGS.DEFAULT_OVERLAY_SCALE"),
Self::DefaultPositioning => Ok("APP_SETTINGS.DEFAULT_POSITIONING"),
Self::DoubleCursorFix => Ok("APP_SETTINGS.DOUBLE_CURSOR_FIX"), Self::DoubleCursorFix => Ok("APP_SETTINGS.DOUBLE_CURSOR_FIX"),
Self::FocusFollowsMouseMode => Ok("APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE"), Self::FocusFollowsMouseMode => Ok("APP_SETTINGS.FOCUS_FOLLOWS_MOUSE_MODE"),
Self::GridOpacity => Ok("APP_SETTINGS.GRID_OPACITY"), Self::GridOpacity => Ok("APP_SETTINGS.GRID_OPACITY"),
Self::HandsfreeAltTab => Ok("APP_SETTINGS.HANDSFREE_ALT_TAB"),
Self::HandsfreePointer => Ok("APP_SETTINGS.HANDSFREE_POINTER"), Self::HandsfreePointer => Ok("APP_SETTINGS.HANDSFREE_POINTER"),
Self::HideGrabHelp => Ok("APP_SETTINGS.HIDE_GRAB_HELP"), Self::HideGrabHelp => Ok("APP_SETTINGS.HIDE_GRAB_HELP"),
Self::HideUsername => Ok("APP_SETTINGS.HIDE_USERNAME"), Self::HideUsername => Ok("APP_SETTINGS.HIDE_USERNAME"),
Self::InputCaptureMethod => Ok("APP_SETTINGS.INPUT_CAPTURE_METHOD"),
Self::InputEmulationMethod => Ok("APP_SETTINGS.INPUT_EMULATION_METHOD"), Self::InputEmulationMethod => Ok("APP_SETTINGS.INPUT_EMULATION_METHOD"),
Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"), Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"),
Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"), Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"),
@ -497,12 +541,15 @@ impl SettingType {
Self::NotificationsEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_ENABLED"), Self::NotificationsEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_ENABLED"),
Self::NotificationsSoundEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED"), Self::NotificationsSoundEnabled => Ok("APP_SETTINGS.NOTIFICATIONS_SOUND_ENABLED"),
Self::OpaqueBackground => Ok("APP_SETTINGS.OPAQUE_BACKGROUND"), Self::OpaqueBackground => Ok("APP_SETTINGS.OPAQUE_BACKGROUND"),
Self::MouseSpeed => Ok("APP_SETTINGS.POINTER_SPEED"),
Self::MouseAcceleration => Ok("APP_SETTINGS.POINTER_ACCELERATION"),
Self::PointerLerpFactor => Ok("APP_SETTINGS.POINTER_LERP_FACTOR"), Self::PointerLerpFactor => Ok("APP_SETTINGS.POINTER_LERP_FACTOR"),
Self::ScreenRenderDown => Ok("APP_SETTINGS.SCREEN_RENDER_DOWN"), Self::ScreenRenderDown => Ok("APP_SETTINGS.SCREEN_RENDER_DOWN"),
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"), Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
Self::EnableWatch => Ok("APP_SETTINGS.ENABLE_WATCH"), Self::EnableWatch => Ok("APP_SETTINGS.ENABLE_WATCH"),
Self::SetsOnWatch => Ok("APP_SETTINGS.SETS_ON_WATCH"), Self::SetsOnWatch => Ok("APP_SETTINGS.SETS_ON_WATCH"),
Self::SnapAngleDeg => Ok("APP_SETTINGS.SNAP_ANGLE_DEG"), Self::SnapAngleDeg => Ok("APP_SETTINGS.SNAP_ANGLE_DEG"),
Self::SpaceDragAffectsWorld => Ok("APP_SETTINGS.SPACE_DRAG_AFFECTS_WORLD"),
Self::SpaceDragMultiplier => Ok("APP_SETTINGS.SPACE_DRAG_MULTIPLIER"), Self::SpaceDragMultiplier => Ok("APP_SETTINGS.SPACE_DRAG_MULTIPLIER"),
Self::SpaceDragUnlocked => Ok("APP_SETTINGS.SPACE_DRAG_UNLOCKED"), Self::SpaceDragUnlocked => Ok("APP_SETTINGS.SPACE_DRAG_UNLOCKED"),
Self::SpaceGravityDamping => Ok("APP_SETTINGS.SPACE_GRAVITY_DAMPING"), Self::SpaceGravityDamping => Ok("APP_SETTINGS.SPACE_GRAVITY_DAMPING"),
@ -531,13 +578,19 @@ impl SettingType {
Self::BlockGameInputIgnoreWatch => Some("APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH_HELP"), Self::BlockGameInputIgnoreWatch => Some("APP_SETTINGS.BLOCK_GAME_INPUT_IGNORE_WATCH_HELP"),
Self::BlockPosesOnKbdInteraction => Some("APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION_HELP"), Self::BlockPosesOnKbdInteraction => Some("APP_SETTINGS.BLOCK_POSES_ON_KBD_INTERACTION_HELP"),
Self::CaptureMethod => Some("APP_SETTINGS.CAPTURE_METHOD_HELP"), Self::CaptureMethod => Some("APP_SETTINGS.CAPTURE_METHOD_HELP"),
Self::DefaultCurvature => Some("APP_SETTINGS.OVERLAY_DEFAULTS_HELP"),
Self::DefaultOpacity => Some("APP_SETTINGS.OVERLAY_DEFAULTS_HELP"),
Self::DefaultOverlayScale => Some("APP_SETTINGS.DEFAULT_OVERLAY_SCALE_HELP"), Self::DefaultOverlayScale => Some("APP_SETTINGS.DEFAULT_OVERLAY_SCALE_HELP"),
Self::DefaultPositioning => Some("APP_SETTINGS.OVERLAY_DEFAULTS_HELP"),
Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"), Self::DoubleCursorFix => Some("APP_SETTINGS.DOUBLE_CURSOR_FIX_HELP"),
Self::GridOpacity => Some("APP_SETTINGS.GRID_OPACITY_HELP"), Self::GridOpacity => Some("APP_SETTINGS.GRID_OPACITY_HELP"),
Self::HandsfreeAltTab => Some("APP_SETTINGS.HANDSFREE_ALT_TAB_HELP"),
Self::HandsfreePointer => Some("APP_SETTINGS.HANDSFREE_POINTER_HELP"), Self::HandsfreePointer => Some("APP_SETTINGS.HANDSFREE_POINTER_HELP"),
Self::InputCaptureMethod => Some("APP_SETTINGS.INPUT_CAPTURE_METHOD_HELP"),
Self::InputEmulationMethod => Some("APP_SETTINGS.INPUT_EMULATION_METHOD_HELP"), Self::InputEmulationMethod => Some("APP_SETTINGS.INPUT_EMULATION_METHOD_HELP"),
Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"), Self::KeyboardMiddleClick => Some("APP_SETTINGS.KEYBOARD_MIDDLE_CLICK_HELP"),
Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"), Self::LeftHandedMouse => Some("APP_SETTINGS.LEFT_HANDED_MOUSE_HELP"),
Self::MouseAcceleration => Some("APP_SETTINGS.POINTER_ACCELERATION_HELP"),
Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"), Self::ScreenRenderDown => Some("APP_SETTINGS.SCREEN_RENDER_DOWN_HELP"),
Self::SnapAngleDeg => Some("APP_SETTINGS.SNAP_ANGLE_DEG_HELP"), Self::SnapAngleDeg => Some("APP_SETTINGS.SNAP_ANGLE_DEG_HELP"),
Self::SpaceGravityDamping => Some("APP_SETTINGS.SPACE_GRAVITY_DAMPING_HELP"), Self::SpaceGravityDamping => Some("APP_SETTINGS.SPACE_GRAVITY_DAMPING_HELP"),
@ -585,7 +638,7 @@ pub fn horiz_cell(layout: &mut Layout, parent: WidgetID) -> anyhow::Result<Widge
taffy::Style { taffy::Style {
flex_direction: taffy::FlexDirection::Row, flex_direction: taffy::FlexDirection::Row,
align_items: Some(taffy::AlignItems::CENTER), align_items: Some(taffy::AlignItems::CENTER),
gap: length(8.0), gap: length(8.0_f32),
..Default::default() ..Default::default()
}, },
)?; )?;
@ -643,6 +696,7 @@ impl<T> TabSettings<T> {
config: frontend.interface.general_config(data), config: frontend.interface.general_config(data),
tasks: self.tasks.clone(), tasks: self.tasks.clone(),
idx: 9001, idx: 9001,
feats,
}; };
let settings_mount_params = SettingsMountParams { let settings_mount_params = SettingsMountParams {
@ -696,7 +750,7 @@ impl<T> TabSettings<T> {
let tasks = Tasks::default(); let tasks = Tasks::default();
let tabs = parser_state.fetch_component_as::<ComponentTabs>("tabs")?; let tabs = parser_state.fetch_component_as::<ComponentTabs>("tabs")?;
if !frontend.interface.get_feats(data).openxr { if !frontend.interface.get_feats(data).xr_backend.is_open_xr() {
let skybox_btn = tabs.get_tab_button("skybox").unwrap(); let skybox_btn = tabs.get_tab_button("skybox").unwrap();
frontend frontend
.layout .layout

View File

@ -92,11 +92,12 @@ impl State {
"APP_SETTINGS.CONTROLS", "APP_SETTINGS.CONTROLS",
"dashboard/controller.svg", "dashboard/controller.svg",
)?; )?;
if par.feats.openxr { if par.feats.xr_backend.is_open_xr() {
create_input_profiles_button(par.mp, c, tasks.clone(), &popup)?; create_input_profiles_button(par.mp, c, tasks.clone(), &popup)?;
} }
options_dropdown::<wlx_common::config::AltModifier>(par.mp, c, &SettingType::KeyboardMiddleClick)?; options_dropdown::<wlx_common::config::AltModifier>(par.mp, c, &SettingType::KeyboardMiddleClick)?;
options_dropdown::<wlx_common::config::HandsfreePointer>(par.mp, c, &SettingType::HandsfreePointer)?; options_dropdown::<wlx_common::config::HandsfreePointer>(par.mp, c, &SettingType::HandsfreePointer)?;
options_dropdown::<wlx_common::config::HandsfreeAltTab>(par.mp, c, &SettingType::HandsfreeAltTab)?;
options_checkbox(par.mp, c, SettingType::FocusFollowsMouseMode)?; options_checkbox(par.mp, c, SettingType::FocusFollowsMouseMode)?;
options_checkbox(par.mp, c, SettingType::LeftHandedMouse)?; options_checkbox(par.mp, c, SettingType::LeftHandedMouse)?;
options_checkbox(par.mp, c, SettingType::AllowSliding)?; options_checkbox(par.mp, c, SettingType::AllowSliding)?;
@ -106,12 +107,15 @@ impl State {
options_slider_f32(par.mp, c, SettingType::LongPressDuration, 0.1, 2.0, 0.1)?; options_slider_f32(par.mp, c, SettingType::LongPressDuration, 0.1, 2.0, 0.1)?;
options_slider_f32(par.mp, c, SettingType::SnapAngleDeg, 0., 45., 5.)?; options_slider_f32(par.mp, c, SettingType::SnapAngleDeg, 0., 45., 5.)?;
if par.feats.openxr { if par.feats.xr_backend.is_open_xr() {
options_slider_f32(par.mp, c, SettingType::PointerLerpFactor, 0.1, 1.0, 0.1)?; options_slider_f32(par.mp, c, SettingType::PointerLerpFactor, 0.1, 1.0, 0.1)?;
} }
options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?; options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?;
options_slider_f32(par.mp, c, SettingType::MouseSpeed, -1., 1., 0.05)?;
options_checkbox(par.mp, c, SettingType::MouseAcceleration)?;
Ok(State { Ok(State {
popup_input_profiles: popup, popup_input_profiles: popup,
frontend_tasks: par.frontend_tasks.clone(), frontend_tasks: par.frontend_tasks.clone(),

View File

@ -57,14 +57,14 @@ impl SettingsTab for State {
for task in self.tasks.drain() { for task in self.tasks.drain() {
match task { match task {
Task::WhisperDownloadClosed => { Task::WhisperDownloadClosed => {
if let Some(model) = self.pending_download.take() { if let Some(model) = self.pending_download.take()
if !whisper_model_path(model.file_name).exists() { && !whisper_model_path(model.file_name).exists()
// download failed, set to selection to none {
par.general_config.whisper_model = "".into(); // download failed, set to selection to none
par.config_change_kind.replace(ConfigChangeKind::Other); par.general_config.whisper_model = "".into();
// reload the tab par.config_change_kind.replace(ConfigChangeKind::Other);
self.parent_tasks.push(ParentTask::SetTab(TabNameEnum::Features)); // reload the tab
} self.parent_tasks.push(ParentTask::SetTab(TabNameEnum::Features));
} }
} }
Task::WhisperRemoveUnused => { Task::WhisperRemoveUnused => {
@ -152,7 +152,7 @@ impl State {
options_checkbox(par.mp, c, SettingType::NotificationsEnabled)?; options_checkbox(par.mp, c, SettingType::NotificationsEnabled)?;
options_checkbox(par.mp, c, SettingType::NotificationsSoundEnabled)?; options_checkbox(par.mp, c, SettingType::NotificationsSoundEnabled)?;
options_checkbox(par.mp, c, SettingType::KeyboardSoundEnabled)?; options_checkbox(par.mp, c, SettingType::KeyboardSoundEnabled)?;
if !par.feats.openxr || par.feats.monado { if par.feats.xr_backend.is_open_vr() || par.feats.monado {
// monado or openvr // monado or openvr
options_checkbox(par.mp, c, SettingType::BlockGameInput)?; options_checkbox(par.mp, c, SettingType::BlockGameInput)?;
options_checkbox(par.mp, c, SettingType::BlockGameInputIgnoreWatch)?; options_checkbox(par.mp, c, SettingType::BlockGameInputIgnoreWatch)?;
@ -303,8 +303,8 @@ fn whisper_models_dropdown(mp: &mut MacroParams, parent: WidgetID) -> anyhow::Re
let mut params = TemplateParams::new(); let mut params = TemplateParams::new();
params.insert("id", &id); params.insert("id", &id);
params.insert("translation", "APP_SETTINGS.WHISPER_MODEL".into()); params.insert("translation", "APP_SETTINGS.WHISPER_MODEL");
params.insert("tooltip", "APP_SETTINGS.WHISPER_MODEL_HELP".into()); params.insert("tooltip", "APP_SETTINGS.WHISPER_MODEL_HELP");
mp.parser_state mp.parser_state
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?; .instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;

View File

@ -11,7 +11,7 @@ use wgui::{
use crate::{ use crate::{
frontend::FrontendTasks, frontend::FrontendTasks,
tab::settings::{ tab::settings::{
SettingType, SettingsMountParams, SettingsTab, Task as SettingsTask, horiz_cell, SettingType, SettingsMountParams, SettingsTab, horiz_cell,
macros::{options_category, options_checkbox, options_dropdown, options_slider_f32}, macros::{options_category, options_checkbox, options_dropdown, options_slider_f32},
mount_requires_restart, mount_requires_restart,
}, },
@ -29,7 +29,6 @@ pub struct State {
frontend_tasks: FrontendTasks, frontend_tasks: FrontendTasks,
globals: WguiGlobals, globals: WguiGlobals,
tasks: Tasks<Task>, tasks: Tasks<Task>,
settings_tasks: Tasks<SettingsTask>,
} }
impl SettingsTab for State { impl SettingsTab for State {
@ -43,7 +42,6 @@ impl SettingsTab for State {
self.frontend_tasks.clone(), self.frontend_tasks.clone(),
self.globals.clone(), self.globals.clone(),
self.popup_color_palettes.clone(), self.popup_color_palettes.clone(),
self.settings_tasks.clone(),
par.general_config.color_palette.clone(), par.general_config.color_palette.clone(),
); );
} }
@ -69,7 +67,10 @@ impl State {
options_checkbox(par.mp, c, SettingType::OpaqueBackground)?; options_checkbox(par.mp, c, SettingType::OpaqueBackground)?;
options_checkbox(par.mp, c, SettingType::HideUsername)?; options_checkbox(par.mp, c, SettingType::HideUsername)?;
options_checkbox(par.mp, c, SettingType::HideGrabHelp)?; options_checkbox(par.mp, c, SettingType::HideGrabHelp)?;
options_slider_f32(par.mp, c, SettingType::DefaultCurvature, 0.0, 0.5, 0.05)?; // min, max, step
options_slider_f32(par.mp, c, SettingType::DefaultOpacity, 0.05, 1.0, 0.05)?; // min, max, step
options_slider_f32(par.mp, c, SettingType::DefaultOverlayScale, 0.7, 1.5, 0.05)?; // min, max, step options_slider_f32(par.mp, c, SettingType::DefaultOverlayScale, 0.7, 1.5, 0.05)?; // min, max, step
options_dropdown::<wlx_common::config::DefaultPositioning>(par.mp, c, &SettingType::DefaultPositioning)?;
options_slider_f32(par.mp, c, SettingType::UiAnimationSpeed, 0.5, 5.0, 0.1)?; // min, max, step options_slider_f32(par.mp, c, SettingType::UiAnimationSpeed, 0.5, 5.0, 0.1)?; // min, max, step
options_slider_f32(par.mp, c, SettingType::UiGradientIntensity, 0.0, 1.0, 0.05)?; // min, max, step options_slider_f32(par.mp, c, SettingType::UiGradientIntensity, 0.0, 1.0, 0.05)?; // min, max, step
options_slider_f32(par.mp, c, SettingType::UiRoundMultiplier, 0.1, 5.0, 0.1)?; options_slider_f32(par.mp, c, SettingType::UiRoundMultiplier, 0.1, 5.0, 0.1)?;
@ -81,7 +82,6 @@ impl State {
frontend_tasks: par.frontend_tasks.clone(), frontend_tasks: par.frontend_tasks.clone(),
globals: par.mp.doc_params.globals.clone(), globals: par.mp.doc_params.globals.clone(),
tasks, tasks,
settings_tasks: par.mp.tasks.clone(),
}) })
} }
} }

View File

@ -11,6 +11,7 @@ impl State {
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> { pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.MISC", "dashboard/blocks.svg")?; let c = options_category(par.mp, par.id_parent, "APP_SETTINGS.MISC", "dashboard/blocks.svg")?;
options_dropdown::<wlx_common::config::InputEmulationMethod>(par.mp, c, &SettingType::InputEmulationMethod)?; options_dropdown::<wlx_common::config::InputEmulationMethod>(par.mp, c, &SettingType::InputEmulationMethod)?;
options_dropdown::<wlx_common::config::InputCaptureMethod>(par.mp, c, &SettingType::InputCaptureMethod)?;
options_dropdown::<wlx_common::config::CaptureMethod>(par.mp, c, &SettingType::CaptureMethod)?; options_dropdown::<wlx_common::config::CaptureMethod>(par.mp, c, &SettingType::CaptureMethod)?;
options_checkbox(par.mp, c, SettingType::XwaylandByDefault)?; options_checkbox(par.mp, c, SettingType::XwaylandByDefault)?;
options_checkbox(par.mp, c, SettingType::UprightScreenFix)?; options_checkbox(par.mp, c, SettingType::UprightScreenFix)?;

View File

@ -8,7 +8,7 @@ use wgui::{
use crate::{ use crate::{
tab::settings::{ tab::settings::{
SettingType, SettingsMountParams, SettingsTab, SettingType, SettingsMountParams, SettingsTab,
macros::{options_category, options_checkbox, options_slider_f32}, macros::{options_button, options_category, options_checkbox, options_slider_f32},
}, },
util::wgui_simple, util::wgui_simple,
}; };
@ -54,10 +54,37 @@ impl State {
let id_gravity_enabled_parent = tab_state.get_widget_id("gravity_enabled_parent")?; let id_gravity_enabled_parent = tab_state.get_widget_id("gravity_enabled_parent")?;
let id_space_gravity_parent = tab_state.get_widget_id("space_gravity_parent")?; let id_space_gravity_parent = tab_state.get_widget_id("space_gravity_parent")?;
if !par.feats.openxr || par.feats.monado { if par.feats.xr_backend.is_open_vr() || par.feats.monado {
// monado or openvr // monado or openvr
options_button(
par.mp,
c,
"APP_SETTINGS.RESET_PLAYSPACE",
"dashboard/refresh.svg",
super::Task::ResetPlayspace,
)?;
options_button(
par.mp,
c,
"APP_SETTINGS.SAVE_PLAYSPACE_CENTER",
"dashboard/recenter.svg",
super::Task::SavePlayspaceCenter,
)?;
options_button(
par.mp,
c,
"APP_SETTINGS.RESET_PLAYSPACE_CENTER",
"dashboard/trash.svg",
super::Task::ResetPlayspaceCenter,
)?;
options_checkbox(par.mp, id_common_options_parent, SettingType::SpaceDragUnlocked)?; options_checkbox(par.mp, id_common_options_parent, SettingType::SpaceDragUnlocked)?;
options_checkbox(par.mp, id_common_options_parent, SettingType::SpaceDragAffectsWorld)?;
options_slider_f32( options_slider_f32(
par.mp, par.mp,
id_common_options_parent, id_common_options_parent,

View File

@ -15,13 +15,6 @@ impl State {
"APP_SETTINGS.TROUBLESHOOTING", "APP_SETTINGS.TROUBLESHOOTING",
"dashboard/cpu.svg", "dashboard/cpu.svg",
)?; )?;
options_danger_button(
par.mp,
c,
"APP_SETTINGS.RESET_PLAYSPACE",
"dashboard/recenter.svg",
Task::ResetPlayspace,
)?;
options_danger_button( options_danger_button(
par.mp, par.mp,
c, c,

104
dash-frontend/src/test.rs Normal file
View File

@ -0,0 +1,104 @@
#[cfg(test)]
mod tests {
use crate::assets::Asset;
#[test]
fn lang_json_files_are_valid() {
for file in Asset::iter() {
if file.ends_with(".json") {
let data = Asset::get(&file).unwrap_or_else(|| panic!("embedded file {file} not found"));
let text =
String::from_utf8(data.data.to_vec()).unwrap_or_else(|e| panic!("file {file} is not valid UTF-8: {e}"));
serde_json::from_str::<serde_json::Value>(&text)
.unwrap_or_else(|e| panic!("file {file} is not valid JSON: {e}"));
}
}
}
fn parse_csv_keys(data: &[u8]) -> Vec<String> {
let text = std::str::from_utf8(data).expect("en.csv is not valid UTF-8");
let mut keys = Vec::new();
let mut chars = text.chars().peekable();
while chars.peek().is_some() {
let key = read_csv_field(&mut chars);
// skip comma separator
if chars.peek() == Some(&',') {
chars.next();
}
// skip value field
read_csv_field(&mut chars);
// skip comma separator
if chars.peek() == Some(&',') {
chars.next();
}
// skip description field (may contain newlines via quotes)
read_csv_field(&mut chars);
// skip newline
if chars.peek() == Some(&'\n') {
chars.next();
}
keys.push(key);
}
keys
}
fn read_csv_field(chars: &mut std::iter::Peekable<std::str::Chars>) -> String {
let mut field = String::new();
if chars.peek() == Some(&'"') {
// quoted field
chars.next(); // consume opening quote
loop {
match chars.next() {
Some('"') => {
if chars.peek() == Some(&'"') {
field.push('"'); // escaped quote
chars.next();
} else {
break; // closing quote
}
}
Some(c) => field.push(c),
None => break,
}
}
} else {
// unquoted field
for c in chars.by_ref() {
if c == ',' || c == '\n' {
break;
}
field.push(c);
}
}
field
}
fn get_nested<'a>(value: &'a serde_json::Value, key: &str) -> Option<&'a serde_json::Value> {
let mut current = value;
for segment in key.split('.') {
current = current.get(segment)?;
}
Some(current)
}
#[test]
fn lang_json_files_contain_all_keys() {
let en_data = Asset::get("lang/en.csv").expect("en.csv not found");
let expected_keys = parse_csv_keys(&en_data.data);
for file in Asset::iter() {
if !file.ends_with(".json") {
continue;
}
let data = Asset::get(&file).unwrap_or_else(|| panic!("embedded file {file} not found"));
let text =
String::from_utf8(data.data.to_vec()).unwrap_or_else(|e| panic!("file {file} is not valid UTF-8: {e}"));
let json: serde_json::Value =
serde_json::from_str(&text).unwrap_or_else(|e| panic!("file {file} is not valid JSON: {e}"));
for key in &expected_keys {
assert!(get_nested(&json, key).is_some(), "missing key {key} in {file}");
}
}
}
}

View File

@ -1,14 +1,113 @@
use std::time::{SystemTime, UNIX_EPOCH};
use crate::util::{networking::http_client, steam_utils::AppID}; use crate::util::{networking::http_client, steam_utils::AppID};
use anyhow::Context; use anyhow::Context;
use serde::Deserialize; use serde::{Deserialize, Serialize};
use strum::AsRefStr;
use wlx_common::cache_dir; use wlx_common::cache_dir;
fn get_unix_timestamp() -> u64 {
SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs()
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, AsRefStr)]
#[serde(rename_all = "snake_case")]
pub enum SupporterTier {
Platinum,
Gold,
Silver,
Bronze,
}
impl SupporterTier {
pub fn pretty_str(self) -> String {
format!("{self:?} Tier")
}
pub const fn color_str(self) -> &'static str {
match self {
Self::Platinum => "#aaffff",
Self::Gold => "#ffffaa",
Self::Silver => "#cccccc",
Self::Bronze => "#ffaa66",
}
}
pub const fn tickets(self) -> u32 {
match self {
Self::Platinum => 20,
Self::Gold => 10,
Self::Silver => 5,
Self::Bronze => 1,
}
}
}
#[derive(Serialize, Deserialize)]
pub struct Supporter {
pub username: String,
pub date: String,
pub tier: SupporterTier,
pub contribution_count: u32,
}
impl Supporter {
pub const fn tickets(&self) -> u32 {
self.tier.tickets()
}
}
#[derive(Serialize, Deserialize)]
pub struct Supporters {
pub time_window_days: u32,
pub supporters: Vec<Supporter>,
}
#[derive(Serialize, Deserialize)]
struct SupportersFile {
fetch_timestamp: u64,
supporters: Option<Supporters>, // empty in case of server/network failure
}
pub async fn request_supporters() -> Option<Supporters> {
let cache_file_path = "supporters_v1.json";
const CACHE_DURATION_SECS: u64 = 7200;
let current_timestamp = get_unix_timestamp();
if let Some(data) = cache_dir::get_data(cache_file_path).await
&& let Ok(string) = str::from_utf8(&data)
&& let Ok(file) = serde_json::from_str::<SupportersFile>(string)
&& file.fetch_timestamp + CACHE_DURATION_SECS > current_timestamp
{
return file.supporters;
}
// perform request
let mut supporters_file = SupportersFile {
fetch_timestamp: current_timestamp,
supporters: None,
};
let url = "https://wayvr.org/files/supporters_v1.json";
if let Ok(res) = http_client::get_simple(url).await
&& let Ok(supporters) = res.into_json::<Supporters>()
{
supporters_file.supporters = Some(supporters);
}
let json = serde_json::to_string_pretty(&supporters_file).unwrap() /* safe */;
cache_dir::set_data(cache_file_path, json.as_bytes()).await.ok()?;
supporters_file.supporters
}
pub struct CoverArt { pub struct CoverArt {
// can be empty in case if data couldn't be fetched (use a fallback image then) // can be empty in case if data couldn't be fetched (use a fallback image then)
pub compressed_image_data: Vec<u8>, pub compressed_image_data: Vec<u8>,
} }
pub async fn request_image(app_id: AppID) -> anyhow::Result<CoverArt> { pub async fn request_cover_art(app_id: AppID) -> anyhow::Result<CoverArt> {
let cache_file_path = format!("cover_arts/{}.bin", app_id); let cache_file_path = format!("cover_arts/{}.bin", app_id);
// check if file already exists in cache directory // check if file already exists in cache directory

View File

@ -1,13 +1,9 @@
use anyhow::Context as _; use anyhow::Context as _;
use smol::{ use smol::{channel::bounded, io::AsyncWriteExt as _};
Task,
channel::{Receiver, bounded},
io::AsyncWriteExt as _,
};
use std::{io::Read as _, path::Path, str, sync::OnceLock}; use std::{io::Read as _, path::Path, str, sync::OnceLock};
const IO_BUFFER_SIZE: usize = 256 * 1024; const IO_BUFFER_SIZE: usize = 256 * 1024;
const CHANNEL_CAPACITY: usize = 4; const CHANNEL_CAPACITY: usize = 8;
const MAX_INITIAL_ALLOCATION: usize = 8 * 1024 * 1024; const MAX_INITIAL_ALLOCATION: usize = 8 * 1024 * 1024;
pub struct HttpClientResponse { pub struct HttpClientResponse {
@ -37,10 +33,15 @@ pub struct GetParams<'a> {
pub on_progress: Option<ProgressFunc<'a>>, pub on_progress: Option<ProgressFunc<'a>>,
} }
enum HttpClientData {
FileSize(u64),
Chunk(Vec<u8>),
Ended(anyhow::Result<()>),
}
struct DownloadStream { struct DownloadStream {
file_size: u64, file_size: u64,
chunks: Receiver<Vec<u8>>, receiver: smol::channel::Receiver<HttpClientData>,
worker: Task<anyhow::Result<()>>,
} }
static HTTP_AGENT: OnceLock<ureq::Agent> = OnceLock::new(); static HTTP_AGENT: OnceLock<ureq::Agent> = OnceLock::new();
@ -55,119 +56,117 @@ fn http_agent() -> &'static ureq::Agent {
}) })
} }
/// Starts a blocking HTTP request and streams its body through a bounded fn thread_http_client(
/// asynchronous channel. url: &str,
/// allow_missing_content_length: bool,
sender: smol::channel::Sender<HttpClientData>,
) -> anyhow::Result<()> {
log::info!("fetching URL \"{}\"", url);
let agent = http_agent().clone();
let response = agent
.get(url)
.header("Accept-Encoding", "identity")
.call()
.with_context(|| format!("failed to fetch URL \"{url}\""))?;
if !response.status().is_success() {
anyhow::bail!("non-200 HTTP response: {}", response.status().as_u16(),);
}
let file_size = match response.body().content_length() {
Some(file_size) => file_size,
None if allow_missing_content_length => 0,
None => {
anyhow::bail!("HTTP response has no Content-Length header");
}
};
sender.send_blocking(HttpClientData::FileSize(file_size))?;
let mut reader = response.into_body().into_reader();
let mut buffer = [0_u8; IO_BUFFER_SIZE];
loop {
let count = reader.read(&mut buffer).with_context(|| {
format!(
"failed while reading HTTP response body \
from \"{url}\""
)
})?;
if count == 0 {
break;
}
sender.send_blocking(HttpClientData::Chunk(buffer[..count].to_vec()))?;
}
Ok(())
}
/// Starts a HTTP request in a separate thread and streams its body through an async channel
/// The request, TLS operations, and all BodyReader reads remain inside one /// The request, TLS operations, and all BodyReader reads remain inside one
/// blocking worker. Only owned byte chunks cross back to the async task. /// blocking worker. Only owned byte chunks cross back to the async task.
async fn start_download(url: &str, allow_missing_content_length: bool) -> anyhow::Result<DownloadStream> { async fn start_download(url: &str, allow_missing_content_length: bool) -> anyhow::Result<DownloadStream> {
let url = url.to_owned(); let url = url.to_owned();
let agent = http_agent().clone();
let (metadata_tx, metadata_rx) = bounded::<u64>(1); let (sender, receiver) = bounded::<HttpClientData>(CHANNEL_CAPACITY);
std::thread::spawn(move || {
let (chunk_tx, chunk_rx) = bounded::<Vec<u8>>(CHANNEL_CAPACITY); let res = thread_http_client(&url, allow_missing_content_length, sender.clone());
let _ = sender.send_blocking(HttpClientData::Ended(res));
let worker = smol::unblock(move || -> anyhow::Result<()> { log::debug!("thread_http_client exiting");
log::info!("fetching URL \"{}\"", url);
let response = agent
.get(&url)
.header("Accept-Encoding", "identity")
.call()
.with_context(|| format!("failed to fetch URL \"{url}\""))?;
if !response.status().is_success() {
anyhow::bail!("non-200 HTTP response: {}", response.status().as_u16(),);
}
let file_size = match response.body().content_length() {
Some(file_size) => file_size,
None if allow_missing_content_length => 0,
None => {
anyhow::bail!("HTTP response has no Content-Length header");
}
};
if metadata_tx.send_blocking(file_size).is_err() {
return Ok(());
}
drop(metadata_tx);
let mut reader = response.into_body().into_reader();
let mut buffer = [0_u8; IO_BUFFER_SIZE];
loop {
let count = reader.read(&mut buffer).with_context(|| {
format!(
"failed while reading HTTP response body \
from \"{url}\""
)
})?;
if count == 0 {
break;
}
let chunk = buffer[..count].to_vec();
if chunk_tx.send_blocking(chunk).is_err() {
return Ok(());
}
}
Ok(())
}); });
let file_size = match metadata_rx.recv().await { let file_size = match receiver.recv().await? {
Ok(file_size) => file_size, HttpClientData::Ended(res) => match res {
Ok(_) => anyhow::bail!("HTTP worker failure"),
Err(_) => { Err(e) => return Err(anyhow::anyhow!(e)),
worker.await?; },
HttpClientData::FileSize(file_size) => file_size,
anyhow::bail!("HTTP worker stopped before providing response metadata"); _ => {
anyhow::bail!("HTTP worker failure")
} }
}; };
Ok(DownloadStream { Ok(DownloadStream { file_size, receiver })
file_size,
chunks: chunk_rx,
worker,
})
} }
/// Downloads a response into memory. /// Downloads a response into memory.
/// ///
/// This fails if the server does not provide a Content-Length header. /// This fails if the server does not provide a Content-Length header.
pub async fn get(mut params: GetParams<'_>) -> anyhow::Result<HttpClientResponse> { pub async fn get(mut params: GetParams<'_>) -> anyhow::Result<HttpClientResponse> {
let DownloadStream { let DownloadStream { file_size, receiver } = start_download(params.url, false).await?;
file_size,
chunks,
worker,
} = start_download(params.url, false).await?;
let initial_capacity = usize::try_from(file_size).unwrap_or(0).min(MAX_INITIAL_ALLOCATION); let initial_capacity = usize::try_from(file_size).unwrap_or(0).min(MAX_INITIAL_ALLOCATION);
let mut data = Vec::with_capacity(initial_capacity); let mut data = Vec::with_capacity(initial_capacity);
let mut bytes_downloaded = 0_u64; let mut bytes_downloaded = 0_u64;
while let Ok(chunk) = chunks.recv().await { while let Ok(msg) = receiver.recv().await {
bytes_downloaded += chunk.len() as u64; match msg {
data.extend_from_slice(&chunk); HttpClientData::FileSize(_) => unreachable!(),
HttpClientData::Ended(e) => {
if let Err(e) = e {
anyhow::bail!("HTTP request failed: {}", e);
}
}
HttpClientData::Chunk(chunk) => {
bytes_downloaded += chunk.len() as u64;
data.extend_from_slice(&chunk);
if let Some(on_progress) = params.on_progress.as_mut() { if let Some(on_progress) = params.on_progress.as_mut() {
on_progress(ProgressFuncData { on_progress(ProgressFuncData {
bytes_downloaded, bytes_downloaded,
file_size, file_size,
}); });
}
}
} }
} }
worker.await?;
if bytes_downloaded != file_size { if bytes_downloaded != file_size {
anyhow::bail!( anyhow::bail!(
"HTTP response size mismatch: expected {} bytes, received {}", "HTTP response size mismatch: expected {} bytes, received {}",
@ -179,6 +178,20 @@ pub async fn get(mut params: GetParams<'_>) -> anyhow::Result<HttpClientResponse
Ok(HttpClientResponse { data }) Ok(HttpClientResponse { data })
} }
struct FileCancelGuard {
path: std::path::PathBuf,
should_delete: bool,
}
impl Drop for FileCancelGuard {
fn drop(&mut self) {
if self.should_delete {
log::warn!("Removing partially downloaded file {:?}", self.path);
let _ = std::fs::remove_file(&self.path);
}
}
}
/// Downloads a response directly to a file. /// Downloads a response directly to a file.
/// ///
/// Unlike `get`, this permits responses without a Content-Length header. In /// Unlike `get`, this permits responses without a Content-Length header. In
@ -189,36 +202,45 @@ pub async fn get(mut params: GetParams<'_>) -> anyhow::Result<HttpClientResponse
pub async fn download_to_file(mut params: GetParams<'_>, path: impl AsRef<Path>) -> anyhow::Result<()> { pub async fn download_to_file(mut params: GetParams<'_>, path: impl AsRef<Path>) -> anyhow::Result<()> {
let path = path.as_ref().to_owned(); let path = path.as_ref().to_owned();
let DownloadStream { let DownloadStream { file_size, receiver } = start_download(params.url, true).await?;
file_size,
chunks, let mut file_cancel_guard = FileCancelGuard {
worker, path: path.clone(),
} = start_download(params.url, true).await?; should_delete: true,
};
let mut file = smol::fs::File::create(&path) let mut file = smol::fs::File::create(&path)
.await .await
.with_context(|| format!("failed to create download file {:?}", path,))?; .with_context(|| format!("failed to create download file {:?}", path))?;
let mut bytes_downloaded = 0_u64; let mut bytes_downloaded = 0_u64;
while let Ok(chunk) = chunks.recv().await { while let Ok(msg) = receiver.recv().await {
file match msg {
.write_all(&chunk) HttpClientData::FileSize(_) => unreachable!(),
.await HttpClientData::Ended(e) => {
.with_context(|| format!("failed to write download file {:?}", path,))?; if let Err(e) = e {
anyhow::bail!("HTTP request failed: {}", e);
}
}
HttpClientData::Chunk(chunk) => {
file
.write_all(&chunk)
.await
.with_context(|| format!("failed to write download file {:?}", path,))?;
bytes_downloaded += chunk.len() as u64; bytes_downloaded += chunk.len() as u64;
if let Some(on_progress) = params.on_progress.as_mut() { if let Some(on_progress) = params.on_progress.as_mut() {
on_progress(ProgressFuncData { on_progress(ProgressFuncData {
bytes_downloaded, bytes_downloaded,
file_size, file_size,
}); });
}
}
} }
} }
worker.await?;
file file
.flush() .flush()
.await .await
@ -232,6 +254,8 @@ pub async fn download_to_file(mut params: GetParams<'_>, path: impl AsRef<Path>)
); );
} }
file_cancel_guard.should_delete = false; // we're good!
Ok(()) Ok(())
} }

View File

@ -46,14 +46,7 @@ impl BindingsDropdown for XrInputSubpathKind {
self self
.get_str("Translation") .get_str("Translation")
.map(Translation::from_translation_key) .map(Translation::from_translation_key)
.unwrap_or_else(|| { .unwrap_or_else(|| Translation::from_raw_text(&wlx_common::locale::capitalize_string(self.as_ref())))
let mut chars = self.as_ref().chars();
let capitalized = match chars.next() {
None => String::new(),
Some(first) => first.to_ascii_uppercase().to_string() + chars.as_str(),
};
Translation::from_raw_text(&capitalized)
})
} }
fn action_str(&self, action: &str, side: XrInputSide) -> Rc<str> { fn action_str(&self, action: &str, side: XrInputSide) -> Rc<str> {
let value = self.as_ref(); let value = self.as_ref();

View File

@ -285,8 +285,8 @@ impl PopupManager {
let id_content = state.get_widget_id("content")?; let id_content = state.get_widget_id("content")?;
let padding = match popup_padding { let padding = match popup_padding {
PopupPadding::Normal => 16.0, PopupPadding::Normal => 16.0_f32,
PopupPadding::None => 0.0, PopupPadding::None => 0.0_f32,
}; };
layout.tasks.push(LayoutTask::SetWidgetStyle( layout.tasks.push(LayoutTask::SetWidgetStyle(

View File

@ -249,7 +249,7 @@ impl SteamUtils {
PathBuf::from(&app_entry.root_path).join(format!("steamapps/appmanifest_{}.acf", app_entry.app_id)); PathBuf::from(&app_entry.root_path).join(format!("steamapps/appmanifest_{}.acf", app_entry.app_id));
let vdf_data = std::fs::read_to_string(manifest_path)?; let vdf_data = std::fs::read_to_string(manifest_path)?;
let vdf_root = keyvalues_parser::Vdf::parse(&vdf_data)?; let vdf_root = keyvalues_parser::parse(&vdf_data)?.into_vdf();
let Some(manifest) = vdf_parse_appstate(app_entry.app_id.clone(), &vdf_root) else { let Some(manifest) = vdf_parse_appstate(app_entry.app_id.clone(), &vdf_root) else {
anyhow::bail!("Failed to parse AppState"); anyhow::bail!("Failed to parse AppState");
@ -262,7 +262,7 @@ impl SteamUtils {
let path = self.get_dir_steamapps().join("libraryfolders.vdf"); let path = self.get_dir_steamapps().join("libraryfolders.vdf");
let vdf_data = std::fs::read_to_string(path)?; let vdf_data = std::fs::read_to_string(path)?;
let vdf_root = keyvalues_parser::Vdf::parse(&vdf_data)?; let vdf_root = keyvalues_parser::parse(&vdf_data)?.into_vdf();
let Some(apps) = vdf_parse_libraryfolders(&vdf_root) else { let Some(apps) = vdf_parse_libraryfolders(&vdf_root) else {
anyhow::bail!("Failed to fetch installed Steam apps"); anyhow::bail!("Failed to fetch installed Steam apps");

View File

@ -65,8 +65,8 @@ impl ToastManager {
taffy::Style { taffy::Style {
position: taffy::Position::Absolute, position: taffy::Position::Absolute,
size: taffy::Size { size: taffy::Size {
width: percent(1.0), width: percent(1.0_f32),
height: percent(0.8), height: percent(0.8_f32),
}, },
align_items: Some(taffy::AlignItems::END), align_items: Some(taffy::AlignItems::END),
justify_content: Some(taffy::JustifyContent::CENTER), justify_content: Some(taffy::JustifyContent::CENTER),
@ -85,15 +85,15 @@ impl ToastManager {
}), }),
taffy::Style { taffy::Style {
position: taffy::Position::Relative, position: taffy::Position::Relative,
gap: length(4.0), gap: length(4.0_f32),
padding: taffy::Rect { padding: taffy::Rect {
left: length(16.0), left: length(16.0_f32),
right: length(16.0), right: length(16.0_f32),
top: length(8.0), top: length(8.0_f32),
bottom: length(8.0), bottom: length(8.0_f32),
}, },
max_size: taffy::Size { max_size: taffy::Size {
width: length(400.0), width: length(400.0_f32),
height: auto(), height: auto(),
}, },
..Default::default() ..Default::default()

View File

@ -298,12 +298,8 @@ impl View {
} }
pub fn update<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) -> anyhow::Result<()> { pub fn update<T>(&mut self, interface: &mut BoxDashInterface<T>, data: &mut T) -> anyhow::Result<()> {
loop { while !self.tasks.is_empty() {
let tasks = self.tasks.drain(); for task in self.tasks.drain() {
if tasks.is_empty() {
break;
}
for task in tasks {
match task { match task {
Task::SetCompositor(mode) => self.compositor_mode = mode, Task::SetCompositor(mode) => self.compositor_mode = mode,
Task::SetRes(mode) => self.res_mode = mode, Task::SetRes(mode) => self.res_mode = mode,

View File

@ -384,13 +384,15 @@ fn input_controls_for_action(
input_controls_for_hand( input_controls_for_hand(
mp, mp,
parent, InputControlsForHandParams {
current_left, parent,
XrInputSide::Left, current: current_left,
action.clone(), side: XrInputSide::Left,
click_type, action: &action,
profile, click_type,
current.threshold_left, profile,
threshold: current.threshold_left,
},
)?; )?;
let current_right = current.right.as_ref().map(|x| match x { let current_right = current.right.as_ref().map(|x| match x {
@ -400,33 +402,40 @@ fn input_controls_for_action(
input_controls_for_hand( input_controls_for_hand(
mp, mp,
parent, InputControlsForHandParams {
current_right, parent,
XrInputSide::Right, current: current_right,
action, side: XrInputSide::Right,
click_type, action: &action,
profile, click_type,
current.threshold_right, profile,
) threshold: current.threshold_right,
},
)?;
Ok(())
} }
fn input_controls_for_hand( struct InputControlsForHandParams<'a> {
mp: &mut MacroParams,
parent: WidgetID, parent: WidgetID,
current: Option<&str>, current: Option<&'a str>,
side: XrInputSide, side: XrInputSide,
action: Rc<str>, action: &'a Rc<str>,
click_type: ClickType, click_type: ClickType,
profile: &XrControllerProfile, profile: &'a XrControllerProfile,
threshold: Option<[f32; 2]>, threshold: Option<[f32; 2]>,
) -> anyhow::Result<()> { }
let Some(user_path) = profile.find_userpath(side) else {
fn input_controls_for_hand(mp: &mut MacroParams, par: InputControlsForHandParams) -> anyhow::Result<()> {
let Some(user_path) = par.profile.find_userpath(par.side) else {
return Ok(()); // this hand is not available return Ok(()); // this hand is not available
}; };
let current = current.and_then(|cur| ParsedOpenXrInputPath::try_from(cur).log_warn(cur).ok()); let current = par
.current
.and_then(|cur| ParsedOpenXrInputPath::try_from(cur).log_warn(cur).ok());
let parent = horiz_cell(mp.layout, parent)?; let parent = horiz_cell(mp.layout, par.parent)?;
let available_components: Rc<[XrInputComponent]> = current let available_components: Rc<[XrInputComponent]> = current
.as_ref() .as_ref()
@ -445,8 +454,8 @@ fn input_controls_for_hand(
subpath_dropdown( subpath_dropdown(
mp, mp,
parent, parent,
action.clone(), par.action.clone(),
side, par.side,
available_subpaths, available_subpaths,
current.as_ref().map(|x| x.subpath), current.as_ref().map(|x| x.subpath),
)?; )?;
@ -454,22 +463,22 @@ fn input_controls_for_hand(
if !component_dropdown( if !component_dropdown(
mp, mp,
parent, parent,
action.clone(), par.action.clone(),
side, par.side,
available_components, available_components,
current.as_ref().map(|x| x.component), current.as_ref().map(|x| x.component),
)? { )? {
return Ok(()); return Ok(());
} }
clicks_dropdown(mp, parent, action.clone(), click_type)?; clicks_dropdown(mp, parent, par.action.clone(), par.click_type)?;
if let Some(component) = current.as_ref().map(|x| x.component) if let Some(component) = current.as_ref().map(|x| x.component)
&& component.is_analog() && component.is_analog()
&& &*action != "scroll" && &**par.action != "scroll"
// hax // hax
{ {
threshold_slider(mp, parent, action, side, threshold)?; threshold_slider(mp, parent, par.action.clone(), par.side, par.threshold)?;
} }
Ok(()) Ok(())

View File

@ -1,11 +1,17 @@
use crate::{
frontend::{FrontendTask, FrontendTasks},
tab::TabType,
util::popup_manager::{MountPopupOnceParams, PopupHolder},
views::{ViewTrait, ViewUpdateParams},
};
use std::{rc::Rc, sync::Arc}; use std::{rc::Rc, sync::Arc};
use wgui::color::WguiColorName;
use wgui::{ use wgui::{
assets::AssetPath, assets::AssetPath,
color::WguiColorName,
components::button::ComponentButton, components::button::ComponentButton,
globals::WguiGlobals, globals::WguiGlobals,
i18n::Translation, i18n::Translation,
layout::{Layout, WidgetID}, layout::{Layout, LayoutTask, WidgetID},
log::LogErr, log::LogErr,
palette::PALETTES, palette::PALETTES,
parser::{Fetchable, ParseDocumentParams, TemplateParams}, parser::{Fetchable, ParseDocumentParams, TemplateParams},
@ -16,19 +22,10 @@ use wlx_common::{
palette::{list_palette_files, load_custom_palette}, palette::{list_palette_files, load_custom_palette},
}; };
use crate::{
frontend::{FrontendTask, FrontendTasks},
tab::settings::Task as SettingsTask,
util::popup_manager::{MountPopupOnceParams, PopupHolder},
views::{self, ViewTrait, ViewUpdateParams},
};
#[derive(Clone)] #[derive(Clone)]
enum Task { enum Task {
SelectPalette(String), SelectPalette(String),
CustomPaletteUrl, CustomPaletteUrl,
Restart,
Cancel,
} }
pub struct Params<'a> { pub struct Params<'a> {
@ -36,40 +33,32 @@ pub struct Params<'a> {
pub layout: &'a mut Layout, pub layout: &'a mut Layout,
pub parent_id: WidgetID, pub parent_id: WidgetID,
pub frontend_tasks: &'a FrontendTasks, pub frontend_tasks: &'a FrontendTasks,
pub settings_tasks: Tasks<SettingsTask>, pub on_close_request: Box<dyn FnOnce()>,
pub current_palette: Arc<str>, pub current_palette: Arc<str>,
} }
pub struct View { pub struct View {
tasks: Tasks<Task>, tasks: Tasks<Task>,
frontend_tasks: FrontendTasks, frontend_tasks: FrontendTasks,
globals: WguiGlobals, on_close_request: Option<Box<dyn FnOnce()>>,
popup_dialog: PopupHolder<views::dialog_box::View>,
settings_tasks: Tasks<SettingsTask>,
chosen_palette: Option<Arc<str>>,
} }
impl ViewTrait for View { impl ViewTrait for View {
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> { fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
self.popup_dialog.update(par)?;
for task in self.tasks.drain() { for task in self.tasks.drain() {
match task { match task {
Task::SelectPalette(profile) => { Task::SelectPalette(profile) => {
self.chosen_palette = Some(profile.into()); let mut globals = par.layout.state.globals.get();
self.show_restart_dialog_box()?; let new_palette = wlx_common::palette::load_palette(&profile);
} globals.palette = new_palette;
Task::Cancel => { par.general_config.color_palette = profile.into();
let close_dialog = self.popup_dialog.get_close_callback(par.layout); par.layout.tasks.push(LayoutTask::RefreshPalette);
close_dialog(); // this works because LookAndFeel is the first tab
} self.frontend_tasks.push(FrontendTask::SetTab(TabType::Settings));
Task::Restart => { par.config_change_kind.replace(ConfigChangeKind::WguiColorPaletteChange);
if let Some(palette) = self.chosen_palette.take() { if let Some(c) = self.on_close_request.take() {
par.general_config.color_palette = palette; c();
par.config_change_kind.replace(ConfigChangeKind::WguiThemeChange);
} }
self.settings_tasks.push(SettingsTask::RestartSoftware);
} }
Task::CustomPaletteUrl => { Task::CustomPaletteUrl => {
self.frontend_tasks.push(FrontendTask::OpenURL( self.frontend_tasks.push(FrontendTask::OpenURL(
@ -113,7 +102,6 @@ impl View {
let list_parent = parser_state.fetch_widget(&params.layout.state, "list_parent")?.id; let list_parent = parser_state.fetch_widget(&params.layout.state, "list_parent")?.id;
let tasks = Tasks::new(); let tasks = Tasks::new();
let popup_dialog = PopupHolder::<views::dialog_box::View>::default();
for (idx, name) in list_palette_files().into_iter().enumerate() { for (idx, name) in list_palette_files().into_iter().enumerate() {
let Ok(palette) = load_custom_palette(&name).log_warn("Could not load custom color palette") else { let Ok(palette) = load_custom_palette(&name).log_warn("Could not load custom color palette") else {
@ -246,58 +234,15 @@ impl View {
Ok(Self { Ok(Self {
tasks, tasks,
frontend_tasks: params.frontend_tasks.clone(), frontend_tasks: params.frontend_tasks.clone(),
globals: params.globals.clone(), on_close_request: Some(params.on_close_request),
popup_dialog,
settings_tasks: params.settings_tasks,
chosen_palette: None,
}) })
} }
fn show_restart_dialog_box(&mut self) -> anyhow::Result<()> {
const ACTION_RESTART: &str = "restart";
const ACTION_CANCEL: &str = "cancel";
let tasks = self.tasks.clone();
views::dialog_box::mount_popup(
self.popup_dialog.clone(),
self.frontend_tasks.clone(),
views::dialog_box::Params {
globals: self.globals.clone(),
message: Translation::from_translation_key("APP_SETTINGS.APPLY_CHANGES_RESTART"),
entries: vec![
views::dialog_box::ButtonEntry {
content: Translation::from_translation_key("APP_SETTINGS.CANCEL"),
icon: "dashboard/close.svg",
action: ACTION_CANCEL,
},
views::dialog_box::ButtonEntry {
content: Translation::from_translation_key("APP_SETTINGS.RESTART_SOFTWARE"),
icon: "dashboard/refresh.svg",
action: ACTION_RESTART,
},
],
on_action_click: Box::new(move |action| match action {
ACTION_RESTART => {
tasks.push(Task::Restart);
}
ACTION_CANCEL => {
tasks.push(Task::Cancel);
}
_ => unreachable!(),
}),
},
);
Ok(())
}
} }
pub fn mount_popup( pub fn mount_popup(
frontend_tasks: FrontendTasks, frontend_tasks: FrontendTasks,
globals: WguiGlobals, globals: WguiGlobals,
popup: PopupHolder<View>, popup: PopupHolder<View>,
settings_tasks: Tasks<SettingsTask>,
current_palette: Arc<str>, current_palette: Arc<str>,
) { ) {
frontend_tasks frontend_tasks
@ -305,13 +250,14 @@ pub fn mount_popup(
.push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new( .push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new(
Translation::from_translation_key("APP_SETTINGS.COLOR_PALETTES"), Translation::from_translation_key("APP_SETTINGS.COLOR_PALETTES"),
Box::new(move |data| { Box::new(move |data| {
let on_close_request = popup.get_close_callback(data.layout);
let view = View::new(Params { let view = View::new(Params {
globals: globals.clone(), globals: globals.clone(),
layout: data.layout, layout: data.layout,
parent_id: data.id_content, parent_id: data.id_content,
frontend_tasks: &frontend_tasks, frontend_tasks: &frontend_tasks,
settings_tasks,
current_palette, current_palette,
on_close_request,
})?; })?;
popup.set_view(data.handle, view, None); popup.set_view(data.handle, view, None);

View File

@ -51,6 +51,9 @@ pub struct View {
id_content: WidgetID, id_content: WidgetID,
on_close_request: Option<Box<dyn FnOnce()>>, on_close_request: Option<Box<dyn FnOnce()>>,
on_downloaded: Option<Box<dyn FnOnce()>>, on_downloaded: Option<Box<dyn FnOnce()>>,
// will cancel on Drop
task_downloader: Option<smol::Task<Option<()>>>,
} }
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> { fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
@ -63,61 +66,66 @@ fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
impl ViewTrait for View { impl ViewTrait for View {
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> { fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
for task in self.tasks.drain() { while !self.tasks.is_empty() {
match task { for task in self.tasks.drain() {
Task::StartDownload(url, path) => { match task {
if let Some(on_downloaded) = self.on_downloaded.take() { Task::StartDownload(url, path) => {
self if let Some(on_downloaded) = self.on_downloaded.take() {
.executor self.task_downloader = Some(self.executor.spawn(View::download(
.spawn(View::download(self.tasks.clone(), url, path, on_downloaded)) self.tasks.clone(),
.detach(); url,
path,
on_downloaded,
)));
}
} }
} Task::SetStatusText(text) => {
Task::SetStatusText(text) => { let widgets = &mut par.layout.state.widgets;
let widgets = &mut par.layout.state.widgets; widgets
widgets .fetch(self.id_label_status)?
.fetch(self.id_label_status)? .cast::<WidgetLabel>()?
.cast::<WidgetLabel>()? .set_text(&mut par.layout.common(), Translation::from_raw_text_string(text));
.set_text(&mut par.layout.common(), Translation::from_raw_text_string(text)); }
} Task::ShowIconSuccess => {
Task::ShowIconSuccess => { par.layout.remove_children(self.id_loading_parent);
par.layout.remove_children(self.id_loading_parent); wgui_simple::create_icon(
wgui_simple::create_icon(
par.layout,
self.id_loading_parent,
Vec2::splat(32.0),
AssetPath::BuiltIn("dashboard/check.svg"),
)?;
// "Close window" button
self
.parser_state
.realize_template(
&doc_params(&self.globals),
"btn_close",
par.layout, par.layout,
self.id_content, self.id_loading_parent,
Default::default(), Vec2::splat(32.0),
)? AssetPath::BuiltIn("dashboard/check.svg"),
.fetch_component_as::<ComponentButton>("btn")? )?;
.on_click(self.tasks.get_button_click_callback(Task::Close));
} // "Close window" button
Task::ShowIconError => { self
par.layout.remove_children(self.id_loading_parent); .parser_state
wgui_simple::create_icon( .realize_template(
par.layout, &doc_params(&self.globals),
self.id_loading_parent, "btn_close",
Vec2::splat(32.0), par.layout,
AssetPath::BuiltIn("dashboard/error.svg"), self.id_content,
)?; Default::default(),
} )?
Task::Close => { .fetch_component_as::<ComponentButton>("btn")?
if let Some(on_close) = self.on_close_request.take() { .on_click(self.tasks.get_button_click_callback(Task::Close));
on_close(); }
Task::ShowIconError => {
par.layout.remove_children(self.id_loading_parent);
wgui_simple::create_icon(
par.layout,
self.id_loading_parent,
Vec2::splat(32.0),
AssetPath::BuiltIn("dashboard/error.svg"),
)?;
}
Task::Close => {
if let Some(on_close) = self.on_close_request.take() {
on_close();
}
} }
} }
} }
} }
Ok(()) Ok(())
} }
} }
@ -178,6 +186,7 @@ impl View {
id_content, id_content,
on_close_request: Some(on_close_request), on_close_request: Some(on_close_request),
on_downloaded: Some(par.on_downloaded), on_downloaded: Some(par.on_downloaded),
task_downloader: None,
}) })
} }
@ -208,12 +217,14 @@ impl View {
on_progress: Some(Box::new({ on_progress: Some(Box::new({
let tasks = tasks.clone(); let tasks = tasks.clone();
move |data: ProgressFuncData| { move |data: ProgressFuncData| {
tasks.push(Task::SetStatusText(format!( if tasks.len() < 100 {
"{}/{} MiB ({}%)", tasks.push(Task::SetStatusText(format!(
data.bytes_downloaded / 1024 / 1024, "{}/{} MiB ({}%)",
data.file_size / 1024 / 1024, data.bytes_downloaded / 1024 / 1024,
(data.bytes_downloaded as f32 / data.file_size as f32 * 100.0).round() data.file_size / 1024 / 1024,
))) (data.bytes_downloaded as f32 / data.file_size as f32 * 100.0).round()
)))
}
} }
})), })),
}, },

View File

@ -62,7 +62,7 @@ const GAME_COVER_SIZE_Y: f32 = 210.0;
impl View { impl View {
async fn request_cover_image(manifest: steam_utils::AppManifest, on_loaded: Box<dyn FnOnce(CoverArt)>) { async fn request_cover_image(manifest: steam_utils::AppManifest, on_loaded: Box<dyn FnOnce(CoverArt)>) {
let cover_art = match cached_fetcher::request_image(manifest.app_id.clone()).await { let cover_art = match cached_fetcher::request_cover_art(manifest.app_id.clone()).await {
Ok(cover_art) => cover_art, Ok(cover_art) => cover_art,
Err(e) => { Err(e) => {
log::error!("request_cover_image failed: {:?}", e); log::error!("request_cover_image failed: {:?}", e);
@ -75,7 +75,7 @@ impl View {
fn mount_image(&self, layout: &mut Layout, glyph: &CustomGlyphData) -> anyhow::Result<()> { fn mount_image(&self, layout: &mut Layout, glyph: &CustomGlyphData) -> anyhow::Result<()> {
let image = WidgetImage::create(WidgetImageParams { let image = WidgetImage::create(WidgetImageParams {
round: WLength::Units(10.0), round: WLength::Units(6.0),
glyph_data: Some(glyph.clone()), glyph_data: Some(glyph.clone()),
..Default::default() ..Default::default()
}); });
@ -85,8 +85,8 @@ impl View {
image, image,
taffy::Style { taffy::Style {
size: taffy::Size { size: taffy::Size {
width: percent(1.0), width: percent(1.0_f32),
height: percent(1.0), height: percent(1.0_f32),
}, },
..Default::default() ..Default::default()
}, },
@ -125,7 +125,7 @@ impl View {
align_self: Some(AlignSelf::BASELINE), align_self: Some(AlignSelf::BASELINE),
justify_self: Some(JustifySelf::CENTER), justify_self: Some(JustifySelf::CENTER),
margin: taffy::Rect { margin: taffy::Rect {
top: length(32.0), top: length(32.0_f32),
bottom: auto(), bottom: auto(),
left: auto(), left: auto(),
right: auto(), right: auto(),
@ -173,7 +173,7 @@ impl View {
color: Some(drawing::Color::new(1.0, 1.0, 1.0, 0.0).into()), color: Some(drawing::Color::new(1.0, 1.0, 1.0, 0.0).into()),
border_color: Some(BORDER_COLOR_DEFAULT.into()), border_color: Some(BORDER_COLOR_DEFAULT.into()),
hover_border_color: Some(BORDER_COLOR_HOVERED.into()), hover_border_color: Some(BORDER_COLOR_HOVERED.into()),
round: WLength::Units(12.0), round: WLength::Units(8.0),
border: 2.0, border: 2.0,
tooltip: Some(TooltipInfo { tooltip: Some(TooltipInfo {
side: TooltipSide::Bottom, side: TooltipSide::Bottom,
@ -199,21 +199,21 @@ impl View {
taffy::Style { taffy::Style {
position: taffy::Position::Absolute, position: taffy::Position::Absolute,
size: taffy::Size { size: taffy::Size {
width: percent(1.0), width: percent(1.0_f32),
height: percent(1.0), height: percent(1.0_f32),
}, },
padding: taffy::Rect::length(2.0), padding: taffy::Rect::length(2.0_f32),
align_items: Some(AlignItems::CENTER), align_items: Some(AlignItems::CENTER),
justify_content: Some(JustifyContent::CENTER), justify_content: Some(JustifyContent::CENTER),
..Default::default() ..Default::default()
}, },
)?; )?;
let rect_gradient = |color: drawing::Color, color2: drawing::Color| { let rect_gradient = |color: drawing::Color, color2: drawing::Color, round: f32| {
rectangle::WidgetRectangle::create(rectangle::WidgetRectangleParams { rectangle::WidgetRectangle::create(rectangle::WidgetRectangleParams {
color: color.into(), color: color.into(),
color2: color2.into(), color2: color2.into(),
round: WLength::Units(12.0), round: WLength::Units(round),
gradient: GradientMode::Vertical, gradient: GradientMode::Vertical,
..Default::default() ..Default::default()
}) })
@ -223,7 +223,7 @@ impl View {
position: taffy::Position::Absolute, position: taffy::Position::Absolute,
align_self: Some(align_self), align_self: Some(align_self),
size: taffy::Size { size: taffy::Size {
width: percent(1.0), width: percent(1.0_f32),
height: percent(height), height: percent(height),
}, },
..Default::default() ..Default::default()
@ -234,7 +234,8 @@ impl View {
widget_button.id, widget_button.id,
rect_gradient( rect_gradient(
drawing::Color::new(1.0, 1.0, 1.0, 0.2), drawing::Color::new(1.0, 1.0, 1.0, 0.2),
drawing::Color::new(1.0, 1.0, 1.0, 0.02), drawing::Color::new(1.0, 1.0, 1.0, 0.01),
8.0,
), ),
rect_gradient_style(taffy::AlignSelf::BASELINE, 0.05), rect_gradient_style(taffy::AlignSelf::BASELINE, 0.05),
)?; )?;
@ -248,6 +249,7 @@ impl View {
rect_gradient( rect_gradient(
drawing::Color::new(1.0, 1.0, 1.0, 0.15), drawing::Color::new(1.0, 1.0, 1.0, 0.15),
drawing::Color::new(1.0, 1.0, 1.0, 0.0), drawing::Color::new(1.0, 1.0, 1.0, 0.0),
8.0,
), ),
rect_gradient_style(taffy::AlignSelf::BASELINE, 0.5), rect_gradient_style(taffy::AlignSelf::BASELINE, 0.5),
)?; )?;
@ -258,6 +260,7 @@ impl View {
rect_gradient( rect_gradient(
drawing::Color::new(0.0, 0.0, 0.0, 0.0), drawing::Color::new(0.0, 0.0, 0.0, 0.0),
drawing::Color::new(0.0, 0.0, 0.0, 0.25), drawing::Color::new(0.0, 0.0, 0.0, 0.25),
8.0,
), ),
rect_gradient_style(taffy::AlignSelf::END, 0.5), rect_gradient_style(taffy::AlignSelf::END, 0.5),
)?; )?;
@ -268,6 +271,7 @@ impl View {
rect_gradient( rect_gradient(
drawing::Color::new(0.0, 0.0, 0.0, 0.1), drawing::Color::new(0.0, 0.0, 0.0, 0.1),
drawing::Color::new(0.0, 0.0, 0.0, 0.9), drawing::Color::new(0.0, 0.0, 0.0, 0.9),
8.0,
), ),
rect_gradient_style(taffy::AlignSelf::END, 0.05), rect_gradient_style(taffy::AlignSelf::END, 0.05),
)?; )?;

View File

@ -52,12 +52,8 @@ pub struct View {
impl ViewTrait for View { impl ViewTrait for View {
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> { fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
loop { while !self.tasks.is_empty() {
let tasks = self.tasks.drain(); for task in self.tasks.drain() {
if tasks.is_empty() {
break;
}
for task in tasks {
match task { match task {
Task::FillAppDetails(details) => self.action_fill_app_details(par.layout, details)?, Task::FillAppDetails(details) => self.action_fill_app_details(par.layout, details)?,
Task::Launch => self.action_launch(), Task::Launch => self.action_launch(),

View File

@ -70,12 +70,8 @@ pub struct View {
impl ViewTrait for View { impl ViewTrait for View {
fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> { fn update(&mut self, par: &mut ViewUpdateParams) -> anyhow::Result<()> {
loop { while !self.tasks.is_empty() {
let tasks = self.tasks.drain(); for task in self.tasks.drain() {
if tasks.is_empty() {
break;
}
for task in tasks {
match task { match task {
Task::LoadManifests => self.load_manifests(), Task::LoadManifests => self.load_manifests(),
Task::FillPage(page_idx) => self.fill_page(par.layout, par.executor, page_idx)?, Task::FillPage(page_idx) => self.fill_page(par.layout, par.executor, page_idx)?,

View File

@ -77,13 +77,8 @@ impl View {
} }
pub fn update(&mut self, layout: &mut Layout, time_ms: u32) -> anyhow::Result<()> { pub fn update(&mut self, layout: &mut Layout, time_ms: u32) -> anyhow::Result<()> {
loop { while !self.tasks.is_empty() {
let tasks = self.tasks.drain(); for task in self.tasks.drain() {
if tasks.is_empty() {
break;
}
for task in tasks {
match task { match task {
Task::Refresh => self.refresh(layout)?, Task::Refresh => self.refresh(layout)?,
Task::StopGame(app_id, kill) => self.stop_game(app_id, kill), Task::StopGame(app_id, kill) => self.stop_game(app_id, kill),

View File

@ -58,12 +58,8 @@ impl ViewTrait for View {
self.popup_remote_skymap_list.update(par)?; self.popup_remote_skymap_list.update(par)?;
self.popup_dialog_box.update(par)?; self.popup_dialog_box.update(par)?;
loop { while !self.tasks.is_empty() {
let tasks = self.tasks.drain(); for task in self.tasks.drain() {
if tasks.is_empty() {
break;
}
for task in tasks {
match task { match task {
Task::DownloadSkymaps => { Task::DownloadSkymaps => {
self.download_skymaps(par.executor)?; self.download_skymaps(par.executor)?;

View File

@ -20,4 +20,6 @@ Glossary:
End of glossary. End of glossary.
Style: These are UI elements in a software, so keep the translations cocise and with an appropriate tone. Don't use polite/formal language. Make sure it sounds natural.
You will be given the input in the code blocks which needs to be translated to {TARGET_LANG} language. Write only the result in codeblocks, do not explain. Keep any newlines and other important formatting-required identifiers as-is, in the same state. You will be given the input in the code blocks which needs to be translated to {TARGET_LANG} language. Write only the result in codeblocks, do not explain. Keep any newlines and other important formatting-required identifiers as-is, in the same state.

View File

@ -97,44 +97,141 @@ interface Template {
examples: Example[]; examples: Example[];
} }
interface CsvEntry {
key: string;
english: string;
context: string;
}
function parse_csv_line(line: string): [string, string, string] {
const result: string[] = [];
let current = "";
let inQuotes = false;
for (let i = 0; i < line.length; i++) {
const ch = line[i]!;
if (ch === '"') {
inQuotes = !inQuotes;
} else if (ch === "," && !inQuotes) {
result.push(current.trim());
current = "";
} else {
current += ch;
}
}
result.push(current.trim());
return [result[0]!, result[1]!, result[2] ?? ""];
}
function parse_csv(text: string): CsvEntry[] {
const lines: string[] = [];
let current = "";
let inQuotes = false;
for (const line of text.split("\n")) {
const wasInQuotes = inQuotes;
for (const ch of line) {
if (ch === '"') {
inQuotes = !inQuotes;
}
}
if (wasInQuotes) {
current += line + "\n";
} else {
if (current) lines.push(current);
current = line + "\n";
}
}
if (current) lines.push(current);
return lines
.filter((l) => l.trim())
.map(parse_csv_line)
.map(([key, english, context]) => ({
key,
english,
context,
}));
}
function csv_to_json(entries: CsvEntry[]): any {
const result: any = {};
for (const entry of entries) {
set_i18n_key(result, entry.key, entry.english);
}
return result;
}
function get_nested_value(obj: any, key: string): string | undefined {
const parts = key.split(".");
let level = obj;
for (const part of parts) {
if (!level || typeof level !== "object") {
return undefined;
}
level = level[part];
}
return level;
}
function resolve_variables(
text: string,
translated_json: any,
all_entries: CsvEntry[],
): string {
return text.replace(/\$\{([^}]+)\}/g, (_, key) => {
const val = get_nested_value(translated_json, key);
if (val !== undefined) {
return val;
}
const entry = all_entries.find((e) => e.key === key);
if (entry !== undefined) {
return entry.english;
}
return `${key}`;
});
}
function gen_prompt( function gen_prompt(
description: string, description: string,
template: Template, template: Template,
key: string, key: string,
english_translation: string, english_translation: string,
context: string,
) { ) {
let num = 1; for (let num = 1; num <= template.examples.length; num++) {
for (const example of template.examples) { const example = template.examples[num - 1]!;
description += "\nExample " + num + ":\n\n";
description += description +=
"Translate key `" + `\nExample ${num}:\n\n` +
example.key + `Translate key \`${example.key}\` from English to ${template.full_name}:\n\n` +
"` from English to " + "```\n" +
template.full_name + example.en +
":\n\n"; "\n```\n\n" +
description += "```\n"; "Result:\n\n```\n" +
description += example.en + "\n"; example.translated +
description += "```\n\n"; "\n```\n";
description += "Result:\n\n";
description += "```\n";
description += example.translated + "\n";
description += "```\n";
num += 1;
} }
description += "\nEnd of examples.\n\n";
description += description +=
"Translate key `" + `\nEnd of examples.\n\n` +
key + `Context: ${context}\n\n` +
"` from English to " + `Translate key \`${key}\` from English to ${template.full_name}:\n\n` +
template.full_name + "```\n" +
":\n\n"; english_translation +
description += "```\n"; "\n```\n";
description += english_translation + "\n";
description += "```\n";
return description; return description;
} }
async function run() { async function run() {
const csv_text = (await fsp.readFile(lang_path + "/en.csv", "utf-8")) as any;
const csv_entries = parse_csv(csv_text);
const orig_english_json = csv_to_json(csv_entries);
if (template_name === "en") {
await fsp.writeFile(
lang_path + "/en.json",
JSON.stringify(orig_english_json, undefined, "\t"),
);
console.log("Translation en copied");
return;
}
const template = JSON.parse( const template = JSON.parse(
await fsp.readFile(templates_path + "/" + template_name + ".json", "utf-8"), await fsp.readFile(templates_path + "/" + template_name + ".json", "utf-8"),
) as Template; ) as Template;
@ -148,60 +245,49 @@ async function run() {
template.full_name, template.full_name,
); );
const orig_english_json = JSON.parse( let llm_translated_json: any = {};
(await fsp.readFile(lang_path + "/en.json")) as any,
);
let orig_translated_json = {};
try {
orig_translated_json = JSON.parse(
(
await fsp.readFile(lang_path + "/" + template_name + ".json")
).toString(),
);
} catch (_e) {}
let llm_translated_json = {};
const translated_json_path = lang_path + "/" + template_name + ".json"; const translated_json_path = lang_path + "/" + template_name + ".json";
if (await fsp.exists(translated_json_path)) { try {
console.log("Loading file", translated_json_path); console.log("Loading file", translated_json_path);
llm_translated_json = JSON.parse( llm_translated_json = JSON.parse(
(await fsp.readFile(translated_json_path)).toString(), (await fsp.readFile(translated_json_path)).toString(),
); );
} } catch (_e) {}
let total_count = 0;
await loop_object(orig_english_json, "", async () => {
total_count += 1;
});
await loop_object(llm_translated_json, "", async (key, _) => { await loop_object(llm_translated_json, "", async (key, _) => {
if (!key_exists(orig_english_json, key)) { if (!key_exists(orig_english_json, key)) {
console.log("Removing key", key); console.log("Removing key", key);
set_i18n_key(llm_translated_json, key, undefined); set_i18n_key(llm_translated_json, key, undefined);
fsp.writeFile( await fsp.writeFile(
translated_json_path, translated_json_path,
JSON.stringify(llm_translated_json, undefined, "\t"), JSON.stringify(llm_translated_json, undefined, "\t"),
); );
} }
}); });
await loop_object(orig_english_json, "", async (key, english_translation) => { for (const entry of csv_entries) {
if (key_exists(orig_translated_json, key)) { const key = entry.key;
return; const english_translation = entry.english;
} const context = entry.context;
if (key_exists(llm_translated_json, key)) { if (key_exists(llm_translated_json, key)) {
return; continue;
} }
console.log("Translating", key, "..."); console.log("Translating", key, "...");
const resolved_context = resolve_variables(
context,
llm_translated_json,
csv_entries,
);
const prompt = gen_prompt( const prompt = gen_prompt(
description_txt, description_txt,
template, template,
key, key,
english_translation, english_translation,
resolved_context,
); );
const response = await fetch(base_url + "/v1/chat/completions", { const response = await fetch(base_url + "/v1/chat/completions", {
@ -237,11 +323,11 @@ async function run() {
console.log(" >>>", msg); console.log(" >>>", msg);
set_i18n_key(llm_translated_json, key, msg[0]); set_i18n_key(llm_translated_json, key, msg[0]);
fsp.writeFile( await fsp.writeFile(
translated_json_path, translated_json_path,
JSON.stringify(llm_translated_json, undefined, "\t"), JSON.stringify(llm_translated_json, undefined, "\t"),
); );
}); }
console.log("Translation", template_name, "finished"); console.log("Translation", template_name, "finished");
} }

View File

@ -25,6 +25,7 @@ if [ -z "${LLAMA_BASE_URL}" ]; then
export LLAMA_BASE_URL="http://127.0.0.1:8080" export LLAMA_BASE_URL="http://127.0.0.1:8080"
fi fi
TEMPLATE="en" bun main.ts
TEMPLATE="pl" bun main.ts TEMPLATE="pl" bun main.ts
TEMPLATE="de" bun main.ts TEMPLATE="de" bun main.ts
TEMPLATE="ja" bun main.ts TEMPLATE="ja" bun main.ts

View File

@ -3,9 +3,13 @@ use std::rc::Rc;
use crate::testbed::{Testbed, TestbedUpdateParams}; use crate::testbed::{Testbed, TestbedUpdateParams};
use dash_frontend::frontend::{self, FrontendUpdateParams}; use dash_frontend::frontend::{self, FrontendUpdateParams};
use wgui::{layout::Layout, theme::WguiTheme}; use wgui::{layout::Layout, theme::WguiTheme};
use wlx_common::{dash_interface_emulated::DashInterfaceEmulated, locale::WayVRLangProvider}; use wlx_common::{
async_executor::AsyncExecutor, dash_interface_emulated::DashInterfaceEmulated,
locale::WayVRLangProvider,
};
pub struct TestbedDashboard { pub struct TestbedDashboard {
executor: AsyncExecutor,
frontend: frontend::Frontend<()>, frontend: frontend::Frontend<()>,
} }
@ -14,6 +18,7 @@ impl TestbedDashboard {
let interface = DashInterfaceEmulated::new(); let interface = DashInterfaceEmulated::new();
let lang_provider = WayVRLangProvider::default(); let lang_provider = WayVRLangProvider::default();
let palette_name = std::env::var("PALETTE").unwrap_or_else(|_| "Default".to_string()); let palette_name = std::env::var("PALETTE").unwrap_or_else(|_| "Default".to_string());
let executor = wlx_common::async_executor::create_local();
let frontend = frontend::Frontend::new(frontend::InitParams { let frontend = frontend::Frontend::new(frontend::InitParams {
interface: Box::new(interface), interface: Box::new(interface),
@ -22,8 +27,9 @@ impl TestbedDashboard {
lang_provider: &lang_provider, lang_provider: &lang_provider,
theme: Rc::new(WguiTheme::default()), theme: Rc::new(WguiTheme::default()),
color_palette: &palette_name, color_palette: &palette_name,
executor: executor.clone(),
})?; })?;
Ok(Self { frontend }) Ok(Self { frontend, executor })
} }
} }
@ -38,6 +44,8 @@ impl Testbed for TestbedDashboard {
self self
.frontend .frontend
.process_update(res, params.audio_system, params.audio_sample_player)?; .process_update(res, params.audio_system, params.audio_sample_player)?;
while self.executor.try_tick() {}
Ok(()) Ok(())
} }

View File

@ -237,8 +237,8 @@ impl TestbedGeneric {
WidgetDiv::create(), WidgetDiv::create(),
taffy::Style { taffy::Style {
size: taffy::Size { size: taffy::Size {
width: length(128.0), width: length(128.0_f32),
height: length(64.0), height: length(64.0_f32),
}, },
..Default::default() ..Default::default()
}, },

View File

@ -31,7 +31,7 @@ pub fn init_window(
let event_loop = EventLoop::new().unwrap(); // want panic let event_loop = EventLoop::new().unwrap(); // want panic
let mut vk_instance_extensions = Surface::required_extensions(&event_loop).unwrap(); let mut vk_instance_extensions = Surface::required_extensions(&event_loop).unwrap();
vk_instance_extensions.khr_get_physical_device_properties2 = true; vk_instance_extensions.khr_get_physical_device_properties2 = true;
log::debug!("Instance exts for runtime: {:?}", &vk_instance_extensions); log::debug!("Instance exts for runtime: {:?}", vk_instance_extensions);
let instance = Instance::new( let instance = Instance::new(
get_vulkan_library().clone(), get_vulkan_library().clone(),
@ -57,7 +57,7 @@ pub fn init_window(
let mut device_extensions = DeviceExtensions::empty(); let mut device_extensions = DeviceExtensions::empty();
device_extensions.khr_swapchain = true; device_extensions.khr_swapchain = true;
log::debug!("Device exts for app: {:?}", &device_extensions); log::debug!("Device exts for app: {:?}", device_extensions);
let (physical_device, mut my_extensions, queue_families) = instance let (physical_device, mut my_extensions, queue_families) = instance
.enumerate_physical_devices()? .enumerate_physical_devices()?

View File

@ -15,6 +15,7 @@ bytes.workspace = true
interprocess.workspace = true interprocess.workspace = true
log.workspace = true log.workspace = true
serde.workspace = true serde.workspace = true
slotmap.workspace = true
smallvec.workspace = true smallvec.workspace = true
# client-only deps # client-only deps

View File

@ -1,6 +1,8 @@
use bytes::BufMut; use bytes::BufMut;
use interprocess::local_socket::{self, ToNsName}; use interprocess::local_socket::{self, ToNsName};
use serde::Serialize; use serde::Serialize;
use slotmap::DenseSlotMap;
use slotmap::new_key_type;
use smallvec::SmallVec; use smallvec::SmallVec;
use smol::io::AsyncReadExt; use smol::io::AsyncReadExt;
use smol::io::AsyncWriteExt; use smol::io::AsyncWriteExt;
@ -9,7 +11,6 @@ use std::os::unix::net::UnixStream as StdUnixStream;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use crate::{ use crate::{
gen_id,
ipc::{self, Serial}, ipc::{self, Serial},
packet_client::{self, HandsfreeParams, PacketClient}, packet_client::{self, HandsfreeParams, PacketClient},
packet_server::{self, PacketServer}, packet_server::{self, PacketServer},
@ -22,28 +23,22 @@ pub struct QueuedPacket {
packet: Option<PacketServer>, packet: Option<PacketServer>,
} }
gen_id!( new_key_type! {
QueuedPacketVec, pub struct QueuedPacketHandle;
QueuedPacket, }
QueuedPacketCell,
QueuedPacketHandle
);
#[derive(Debug, Serialize, Clone)] #[derive(Debug, Serialize, Clone)]
pub struct AuthInfo { pub struct AuthInfo {
pub runtime: String, pub runtime: String,
} }
type SignalFunc = Box<dyn FnMut(&packet_server::PacketServer) -> bool + Send>;
pub struct WayVRClient { pub struct WayVRClient {
receiver: ReceiverMutex, receiver: ReceiverMutex,
sender: SenderMutex, sender: SenderMutex,
cancel_tx: async_channel::Sender<()>, cancel_tx: async_channel::Sender<()>,
exiting: bool, exiting: bool,
queued_packets: QueuedPacketVec, queued_packets: DenseSlotMap<QueuedPacketHandle, QueuedPacket>,
pub auth: Option<AuthInfo>, pub auth: Option<AuthInfo>,
pub on_signal: Option<SignalFunc>,
} }
pub async fn send_packet(sender: &SenderMutex, data: &[u8]) -> anyhow::Result<()> { pub async fn send_packet(sender: &SenderMutex, data: &[u8]) -> anyhow::Result<()> {
@ -130,10 +125,6 @@ macro_rules! send_only {
} }
impl WayVRClient { impl WayVRClient {
pub fn set_signal_handler(&mut self, on_signal: SignalFunc) {
self.on_signal = Some(on_signal);
}
pub async fn new(client_name: &str) -> anyhow::Result<WayVRClientMutex> { pub async fn new(client_name: &str) -> anyhow::Result<WayVRClientMutex> {
let printname = "/tmp/wayvr_ipc.sock"; let printname = "/tmp/wayvr_ipc.sock";
@ -156,9 +147,8 @@ impl WayVRClient {
sender: sender.clone(), sender: sender.clone(),
cancel_tx, cancel_tx,
exiting: false, exiting: false,
queued_packets: QueuedPacketVec::new(), queued_packets: Default::default(),
auth: None, auth: None,
on_signal: None,
})); }));
WayVRClient::start_runner(client.clone(), cancel_rx); WayVRClient::start_runner(client.clone(), cancel_rx);
@ -253,22 +243,9 @@ impl WayVRClient {
); );
} }
if let PacketServer::WvrStateChanged(_) = &packet
&& let Some(on_signal) = &mut client.on_signal
&& (*on_signal)(&packet)
{
// Signal consumed
return Ok(());
}
// queue packet to read if it contains a serial response // queue packet to read if it contains a serial response
if let Some(serial) = packet.serial() { if let Some(serial) = packet.serial() {
for qpacket in &mut client.queued_packets.vec { for (_, qpacket) in &mut client.queued_packets {
let Some(qpacket) = qpacket else {
continue;
};
let qpacket = &mut qpacket.obj;
if qpacket.serial != *serial { if qpacket.serial != *serial {
continue; //skip continue; //skip
} }
@ -306,7 +283,7 @@ impl WayVRClient {
// Send packet to the server // Send packet to the server
let queued_packet_handle = { let queued_packet_handle = {
let mut client = client_mtx.lock().await; let mut client = client_mtx.lock().await;
let handle = client.queued_packets.add(QueuedPacket { let handle = client.queued_packets.insert(QueuedPacket {
notifier: notifier.clone(), notifier: notifier.clone(),
packet: None, // will be filled after notify packet: None, // will be filled after notify
serial, serial,
@ -329,7 +306,7 @@ impl WayVRClient {
let cell = client let cell = client
.queued_packets .queued_packets
.get_mut(&queued_packet_handle) .get_mut(queued_packet_handle)
.ok_or(anyhow::anyhow!( .ok_or(anyhow::anyhow!(
"missing packet cell, this shouldn't happen" "missing packet cell, this shouldn't happen"
))?; ))?;
@ -338,7 +315,7 @@ impl WayVRClient {
anyhow::bail!("packet is None, this shouldn't happen"); anyhow::bail!("packet is None, this shouldn't happen");
}; };
client.queued_packets.remove(&queued_packet_handle); client.queued_packets.remove(queued_packet_handle);
Ok(packet) Ok(packet)
} }
@ -460,6 +437,11 @@ impl WayVRClient {
Ok(()) Ok(())
} }
pub async fn fn_wvr_input_capture(client: WayVRClientMutex, grab: bool) -> anyhow::Result<()> {
send_only!(client, &PacketClient::WvrInputCapture(grab));
Ok(())
}
pub async fn fn_wlx_modify_panel( pub async fn fn_wlx_modify_panel(
client: WayVRClientMutex, client: WayVRClientMutex,
params: packet_client::WlxModifyPanelParams, params: packet_client::WlxModifyPanelParams,

View File

@ -22,7 +22,7 @@ impl SerialGenerator {
} }
} }
pub const PROTOCOL_VERSION: u32 = 3; pub const PROTOCOL_VERSION: u32 = 4;
pub const CONNECTION_MAGIC: &str = "wayvr_ipc"; pub const CONNECTION_MAGIC: &str = "wayvr_ipc";
pub fn data_encode<T>(data: &T) -> Vec<u8> pub fn data_encode<T>(data: &T) -> Vec<u8>

View File

@ -90,6 +90,7 @@ pub enum PacketClient {
WvrProcessLaunch(Serial, WvrProcessLaunchParams), WvrProcessLaunch(Serial, WvrProcessLaunchParams),
WvrProcessList(Serial), WvrProcessList(Serial),
WvrProcessTerminate(packet_server::WvrProcessHandle), WvrProcessTerminate(packet_server::WvrProcessHandle),
WvrInputCapture(bool),
WlxInputState(Serial), WlxInputState(Serial),
WlxModifyPanel(WlxModifyPanelParams), WlxModifyPanel(WlxModifyPanelParams),
WlxDeviceHaptics(usize, WlxHapticsParams), WlxDeviceHaptics(usize, WlxHapticsParams),

View File

@ -21,14 +21,12 @@ pub struct Disconnect {
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct WvrProcessHandle { pub struct WvrProcessHandle {
pub idx: u32, pub user: u64,
pub generation: u64,
} }
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct WvrWindowHandle { pub struct WvrWindowHandle {
pub idx: u32, pub user: u64,
pub generation: u64,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]

View File

@ -1,171 +0,0 @@
#[macro_export]
macro_rules! gen_id {
(
$container_name:ident,
$instance_name:ident,
$cell_name:ident,
$handle_name:ident) => {
//ThingCell
pub struct $cell_name {
pub obj: $instance_name,
pub generation: u64,
}
//ThingVec
pub struct $container_name {
// Vec<Option<ThingCell>>
pub vec: Vec<Option<$cell_name>>,
cur_generation: u64,
}
//ThingHandle
#[derive(Default, Clone, Copy, PartialEq, Hash, Eq)]
pub struct $handle_name {
idx: u32,
generation: u64,
}
#[allow(dead_code)]
impl $handle_name {
pub fn reset(&mut self) {
self.generation = 0;
}
pub fn is_set(&self) -> bool {
self.generation > 0
}
pub fn id(&self) -> u32 {
self.idx
}
pub fn new(idx: u32, generation: u64) -> Self {
Self { idx, generation }
}
}
//ThingVec
#[allow(dead_code)]
impl $container_name {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self {
vec: Vec::new(),
cur_generation: 0,
}
}
pub fn iter(&self, callback: &dyn Fn($handle_name, &$instance_name)) {
for (idx, opt_cell) in self.vec.iter().enumerate() {
if let Some(cell) = opt_cell {
let handle = $container_name::get_handle(&cell, idx);
callback(handle, &cell.obj);
}
}
}
pub fn iter_mut(&mut self, callback: &mut dyn FnMut($handle_name, &mut $instance_name)) {
for (idx, opt_cell) in self.vec.iter_mut().enumerate() {
if let Some(cell) = opt_cell {
let handle = $container_name::get_handle(&cell, idx);
callback(handle, &mut cell.obj);
}
}
}
pub fn get_handle(cell: &$cell_name, idx: usize) -> $handle_name {
$handle_name {
idx: idx as u32,
generation: cell.generation,
}
}
fn find_unused_idx(&mut self) -> Option<u32> {
for (num, obj) in self.vec.iter().enumerate() {
if obj.is_none() {
return Some(num as u32);
}
}
None
}
pub fn add(&mut self, obj: $instance_name) -> $handle_name {
self.cur_generation += 1;
let generation = self.cur_generation;
let unused_idx = self.find_unused_idx();
let idx = if let Some(idx) = unused_idx {
idx
} else {
self.vec.len() as u32
};
let handle = $handle_name { idx, generation };
let cell = $cell_name { obj, generation };
if let Some(idx) = unused_idx {
self.vec[idx as usize] = Some(cell);
} else {
self.vec.push(Some(cell))
}
handle
}
pub fn remove(&mut self, handle: &$handle_name) {
// Out of bounds, ignore
if handle.idx as usize >= self.vec.len() {
return;
}
// Remove only if the generation matches
if let Some(cell) = &self.vec[handle.idx as usize] {
if cell.generation == handle.generation {
self.vec[handle.idx as usize] = None;
}
}
}
pub fn get(&self, handle: &$handle_name) -> Option<&$instance_name> {
// Out of bounds, ignore
if handle.idx as usize >= self.vec.len() {
return None;
}
if let Some(cell) = &self.vec[handle.idx as usize] {
if cell.generation == handle.generation {
return Some(&cell.obj);
}
}
None
}
pub fn get_mut(&mut self, handle: &$handle_name) -> Option<&mut $instance_name> {
// Out of bounds, ignore
if handle.idx as usize >= self.vec.len() {
return None;
}
if let Some(cell) = &mut self.vec[handle.idx as usize] {
if cell.generation == handle.generation {
return Some(&mut cell.obj);
}
}
None
}
}
};
}
/* Example usage:
gen_id!(ThingVec, ThingInstance, ThingCell, ThingHandle);
struct ThingInstance {}
impl ThingInstance {}
*/

View File

@ -1,4 +1,2 @@
pub mod handle;
#[cfg(feature = "client")] #[cfg(feature = "client")]
pub mod notifier; pub mod notifier;

View File

@ -1,6 +1,6 @@
[package] [package]
name = "wayvr" name = "wayvr"
version = "26.7.1" version = "26.8.0"
edition = "2024" edition = "2024"
license = "GPL-3.0-only" license = "GPL-3.0-only"
authors = ["galister", "oo8dev"] authors = ["galister", "oo8dev"]
@ -33,6 +33,11 @@ dbus.workspace = true
glam = { workspace = true, features = ["mint", "serde"] } glam = { workspace = true, features = ["mint", "serde"] }
idmap = { workspace = true, features = ["serde"] } idmap = { workspace = true, features = ["serde"] }
idmap-derive.workspace = true idmap-derive.workspace = true
input = {
version = "0.9.1",
default-features = false,
features = ["libinput_1_19", "udev"]
}
interprocess.workspace = true interprocess.workspace = true
libc.workspace = true libc.workspace = true
log.workspace = true log.workspace = true
@ -121,6 +126,7 @@ xkbcommon = {
calloop = { version = "0.14.4", optional = true } calloop = { version = "0.14.4", optional = true }
calloop-wayland-source = { version = "0.4.1", optional = true } calloop-wayland-source = { version = "0.4.1", optional = true }
evdev = "0.13.2"
[build-dependencies] [build-dependencies]
regex.workspace = true regex.workspace = true

View File

@ -6,14 +6,14 @@ fn main() {
match std::env::var("GITHUB_JOB").as_deref() { match std::env::var("GITHUB_JOB").as_deref() {
Ok("make_release") => { Ok("make_release") => {
wlx_build = format!("{} (Release)", &wlx_build); wlx_build = format!("{} (Release)", wlx_build);
} }
Ok("build_appimage") => { Ok("build_appimage") => {
wlx_build = format!("{} (AppImage)", &wlx_build); wlx_build = format!("{} (AppImage)", wlx_build);
} }
_ => {} _ => {}
} }
println!("cargo:rustc-env=WLX_BUILD={}", &wlx_build); println!("cargo:rustc-env=WLX_BUILD={}", wlx_build);
} }
fn get_version() -> Result<String, Box<dyn std::error::Error>> { fn get_version() -> Result<String, Box<dyn std::error::Error>> {

View File

@ -1,6 +0,0 @@
#!/bin/bash
cargo run --profile=plain -- --show --replace

View File

@ -0,0 +1,128 @@
<layout>
<elements>
<div interactable="0">
<rectangle
max_width="800"
padding="16"
flex_direction="column"
gap="8"
color="background(opacity-0.8)" border_color="outline" border="2" round="8">
<div flex_direction="column" padding="8" justify_content="space_evenly">
<label wrap="1" color="primary" weight="bold" size="20" padding_left="16" padding_right="16" translation="ALTTAB.RELEASE_TO_FOCUS" />
<!-- A simple separator -->
<rectangle width="100%" height="2" color="outline" margin="16" />
<div gap="8" flex_direction="row" >
<div width="50%" gap="8" flex_direction="column" >
<div width="100%">
<label translation="ALTTAB.WHILE_AIMING" color="primary" size="24" padding_left="16" padding_right="16" />
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="W" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div flex_direction="row" wrap="1">
<label translation="ALTTAB.CLICK" color="on_background" wrap="1" size="20" padding_left="8" />
<label text="*" color="tertiary" wrap="1" size="20" padding_left="4" padding_right="16" />
</div>
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="A" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.GRABALL" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="Q" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.GRAB" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="D" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.DASH" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="E" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.EDIT" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="T" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.KEYBOARD" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="R" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.RECENTER" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="1~4" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.SET" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
</div>
<div width="50%" gap="8" flex_direction="column" >
<div width="100%">
<label translation="ALTTAB.GENERAL_BINDS" color="primary" size="24" padding_left="16" padding_right="16" />
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="Super+Z" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.TOGGLE_CAPTURE" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="Super+X" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.FOCUS_MODE" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
<div flex_direction="row" width="100%">
<div width="90">
<label text="Alt+F4" color="secondary" size="20" padding_left="16" padding_right="8" />
</div>
<div>
<label translation="ALTTAB.CLOSE" color="on_background" wrap="1" size="20" padding_left="8" padding_right="16" />
</div>
</div>
<!-- A simple separator -->
<rectangle width="100%" height="2" color="outline" margin="16" padding_right="16" />
<div width="100%" flex_direction="row">
<label text="*" color="tertiary" wrap="1" size="20" padding_left="8" />
<label translation="ALTTAB.MOUSE" color="on_background" wrap="1" size="20" padding_left="4" padding_right="16" />
</div>
</div>
</div>
</div>
</rectangle>
</div>
</elements>
</layout>

View File

@ -5,6 +5,7 @@
<elements> <elements>
<div flex_grow="1" height="48"> <div flex_grow="1" height="48">
<rectangle <rectangle
id="rect"
flex_grow="1" height="48" flex_grow="1" height="48"
padding="8" border="2" padding="8" border="2"
round="8" round="8"
@ -13,7 +14,7 @@
color="background" color="background"
border_color="outline" border_color="outline"
> >
<label id="label_title" margin_left="8" color="on_background" size="22" weight="bold" /> <label id="title" text="~title" margin_left="8" color="on_background" size="22" weight="bold" />
<div gap="4"> <div gap="4">
<Button macro="window_button" _release="::EditToggle"> <Button macro="window_button" _release="::EditToggle">
<sprite macro="window_button_icon" src="watch/edit.svg" /> <sprite macro="window_button_icon" src="watch/edit.svg" />

View File

@ -65,11 +65,9 @@
<label translation="EDIT_MODE.INTERPOLATION" /> <label translation="EDIT_MODE.INTERPOLATION" />
<Slider id="lerp_slider" width="250" height="16" min_value="0.05" max_value="1" value="1" step="0.05" /> <Slider id="lerp_slider" width="250" height="16" min_value="0.05" max_value="1" value="1" step="0.05" />
</div> </div>
<div id="pos_align_to_hmd" >
<CheckBox id="align_box" translation="EDIT_MODE.ALIGN_TO_HMD" tooltip_side="bottom" />
</div>
<div id="pos_global" gap="16" justify_content="center" align_items="center"> <div id="pos_global" gap="16" justify_content="center" align_items="center">
<CheckBox id="global_box" translation="EDIT_MODE.GLOBAL" tooltip_side="bottom" /> <CheckBox id="global_box" translation="EDIT_MODE.GLOBAL" tooltip_side="bottom" />
<CheckBox id="align_box" translation="EDIT_MODE.ALIGN_TO_HMD" tooltip_side="bottom" />
<CheckBox id="block_input_box" translation="EDIT_MODE.BLOCK_INPUT" tooltip_side="bottom" /> <CheckBox id="block_input_box" translation="EDIT_MODE.BLOCK_INPUT" tooltip_side="bottom" />
</div> </div>
</div> </div>

View File

@ -154,7 +154,7 @@
<!-- title text="${name}" /--> <!-- title text="${name}" /-->
<cell translation="BAR.TOGGLE_VISIBILITY" _press="::OverlayToggle ${name}" /> <cell translation="BAR.TOGGLE_VISIBILITY" _press="::OverlayToggle ${name}" />
<cell translation="BAR.RESET_POSITION" _press="::OverlayReset ${name}" /> <cell translation="BAR.RESET_POSITION" _press="::OverlayReset ${name}" />
<cell translation="BAR.CLOSE_MIRROR" _press="::OverlayDrop ${name}" /> <cell translation="BAR.CLOSE_OVERLAY" _press="::OverlayDrop ${name}" />
</context_menu> </context_menu>
</blueprint> </blueprint>
@ -167,13 +167,23 @@
</Button> </Button>
</template> </template>
<!-- mirror with a different icon -->
<template name="Passthru">
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _context_name="${name}" _press_left="::ContextMenuOpen menu_mirror" _press_right="::OverlayToggle ${name}">
<sprite width="38" height="38" src_builtin="icons/landscape.svg" />
<div position="absolute" margin_top="5" margin_left="13">
<label text="${display}" size="20" weight="bold" parent_color="background" />
</div>
</Button>
</template>
<blueprint name="menu_handsfree"> <blueprint name="menu_handsfree">
<context_menu > <context_menu >
<cell translation="BAR.HANDSFREE.NONE" _press="::HandsfreeMode None" _press2="::ContextMenuClose" /> <cell translation="BAR.HANDSFREE.NONE" _press="::HandsfreeMode None" _press2="::ContextMenuClose" />
<cell translation="BAR.HANDSFREE.HMD" _press="::HandsfreeMode Hmd" _press2="::ContextMenuClose" /> <cell translation="BAR.HANDSFREE.HMD" _press="::HandsfreeMode Hmd" _press2="::ContextMenuClose" />
<cell translation="BAR.HANDSFREE.HMD_ONLY" _press="::HandsfreeMode HmdOnly" _press2="::ContextMenuClose" /> <cell translation="BAR.HANDSFREE.HMD_ONLY" _press="::HandsfreeMode HmdOnly" _press2="::ContextMenuClose" />
<cell translation="BAR.HANDSFREE.EYE_TRACKING" _press="::HandsfreeMode EyeTracking" _press2="::ContextMenuClose" /> <cell translation="BAR.HANDSFREE.EYE_TRACKING" _press="::HandsfreeMode EyeTracking" _press2="::ContextMenuClose" skip="${openvr}" />
<cell translation="BAR.HANDSFREE.EYE_ONLY" _press="::HandsfreeMode EyeTrackingOnly" _press2="::ContextMenuClose" /> <cell translation="BAR.HANDSFREE.EYE_ONLY" _press="::HandsfreeMode EyeTrackingOnly" _press2="::ContextMenuClose" skip="${openvr}" />
</context_menu> </context_menu>
</blueprint> </blueprint>
@ -181,7 +191,8 @@
<context_menu > <context_menu >
<cell translation="BAR.EDIT_MODE_TOGGLE" _press="::EditToggle" _press2="::ContextMenuClose" /> <cell translation="BAR.EDIT_MODE_TOGGLE" _press="::EditToggle" _press2="::ContextMenuClose" />
<cell translation="BAR.HANDSFREE.TITLE" _press="::ContextMenuOpen menu_handsfree" /> <cell translation="BAR.HANDSFREE.TITLE" _press="::ContextMenuOpen menu_handsfree" />
<cell translation="BAR.ADD_MIRROR" _press="::NewMirror" /> <cell translation="BAR.ADD_MIRROR" _press="::NewMirror" skip="${not_wayland}" />
<cell translation="BAR.ADD_PASSTHRU" _press="::NewPassthru" skip="${not_passthru}" />
<cell translation="BAR.ADD_NEW_SET" _press="::AddSet" /> <cell translation="BAR.ADD_NEW_SET" _press="::AddSet" />
<cell translation="BAR.DELETE_CURRENT_SET" _press="::DeleteSet" /> <cell translation="BAR.DELETE_CURRENT_SET" _press="::DeleteSet" />
</context_menu> </context_menu>
@ -215,7 +226,7 @@
<div id="panels_root" gap="6"> <div id="panels_root" gap="6">
</div> </div>
<VerticalSeparator /> <VerticalSeparator />
<div id="apps_root" gap="6"> <div id="apps_root" gap="6" skip="${openvr}">
</div> </div>
</div> </div>
<div id="tray_root" flex_direction="row" gap="10"> <div id="tray_root" flex_direction="row" gap="10">

View File

@ -54,6 +54,14 @@
</div> </div>
</Button> </Button>
</template> </template>
<template name="Passthru">
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::OverlayToggle ${name}">
<sprite width="38" height="38" src_builtin="icons/landscape.svg" />
<div position="absolute" margin_top="5" margin_left="13">
<label text="${display}" size="20" weight="bold" parent_color="background" />
</div>
</Button>
</template>
<template name="App"> <template name="App">
<Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::OverlayToggle ${name}"> <Button macro="button_style" id="overlay_${idx}" tooltip_str="${name}" _press="::OverlayToggle ${name}">
<sprite width="38" height="38" src_ext="${icon}" /> <sprite width="38" height="38" src_ext="${icon}" />

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="white" d="m1.15 20l3.45-6.9q.25-.5.713-.8T6.35 12q.6 0 1.1.312t.725.888l.675 1.65q.05.15.225.137t.225-.162l2.15-7.175q.35-1.2 1.338-1.925T15.025 5q1.225 0 2.188.712t1.337 1.863L22.875 20zM6 10q-1.25 0-2.125-.888T3 7q0-1.25.875-2.125T6 4t2.125.875T9 7q0 1.225-.875 2.113T6 10"/></svg>

After

Width:  |  Height:  |  Size: 494 B

View File

@ -1,62 +1,5 @@
{ {
"ANCHOR": {
"CENTER": "Zentrum"
},
"BAR": {
"ADD_MIRROR": "Neuen Spiegel-Overlay hinzufügen",
"EDIT_MODE_TOGGLE": "Bearbeitungsmodus umschalten",
"ADD_NEW_SET": "Neues Set hinzufügen",
"DELETE_CURRENT_SET": "Aktuelles Set löschen",
"TOGGLE_VISIBILITY": "Sichtbarkeit umschalten",
"RESET_POSITION": "Position zurücksetzen",
"RELOAD_FROM_DISK": "XML-Datei von der Festplatte neu laden",
"CLOSE_MIRROR": "Spiegel schließen",
"CLOSE_APP": "App schließen",
"FORCE_CLOSE_APP": "App zwangsweise schließen",
"HANDSFREE": {
"TITLE": "Freihändig-Modus",
"NONE": "Aus",
"HMD": "HMD + Kneifen",
"EYE_TRACKING": "Auge + Kneifen",
"HMD_ONLY": "Nur HMD",
"EYE_ONLY": "Nur Augen"
}
},
"WATCH": {
"RECENTER": "Spielbereich neu zentrieren",
"FIX_FLOOR": "Bodenhöhe korrigieren",
"EDIT_MODE_EXPLANATION": "Overlays können nun einzeln verschoben und angepasst werden.\nOverlays für den aktuellen Satz umschalten:",
"DASHBOARD": "Dashboard",
"EDIT_MODE": "Bearbeitungsmodus",
"ADD_NEW_SET": "Neuen Satz hinzufügen",
"SWITCH_TO_SET": "Zum Satz wechseln",
"TOGGLE_FOR_CURRENT_SET": "Sichtbarkeit im aktuellen Satz umschalten",
"LONG_PRESS_TO_DELETE_SET": "Lange drücken, um Satz zu löschen",
"CLEANUP_MIRRORS": "Spiegel entfernen, die\nderzeit nicht sichtbar sind"
},
"EDIT_MODE": { "EDIT_MODE": {
"ADJUST_CURVATURE": "Krümmung anpassen",
"ALPHA_BLEND_MODE": "Alpha-Mischmodus",
"BLENDING_ADDITIVE": "Additiv",
"CURVATURE": "Krümmung",
"DELETE": "Löschen",
"HINT_POINT_WINDOW": "Zeigen Sie auf ein Fenster, um seine Parameter zu ändern.\nWenn Sie fertig sind, verlassen Sie den Bearbeitungsmodus mit der Schaltfläche auf der rechten Seite.",
"LEAVE": "Bearbeitungsmodus verlassen",
"LOCK_INTERACTION": "Interaktion sperren",
"DISABLE_GRAB": "Greifen deaktivieren",
"MOVE_PRESS_AND_DRAG": "Verschieben (drücken & ziehen)",
"OPACITY": "Undurchsichtigkeit",
"POSITIONING": "Positionierung",
"RESIZE_PRESS_AND_DRAG": "Größe ändern (gedrückt halten & ziehen)",
"POS_STATIC": "Statisch: Bleibt an Ort und Stelle und wird niemals neu zentriert.",
"POS_ANCHORED": "Verankert: Bewegt sich zusammen mit dem Rest des Sets. Standard.",
"POS_FLOATING": "Schwebend: Bleibt an Ort und Stelle, wird beim Anzeigen neu zentriert.",
"POS_HMD": "Folge dem Headset.",
"POS_HAND_L": "Folge der linken Hand.",
"POS_HAND_R": "Folge der rechten Hand.",
"INTERPOLATION": "Interpolation",
"KEYBOARD": "Tastatur",
"STEREO_3D_MODE_A": {},
"STEREO_3D_MODE": { "STEREO_3D_MODE": {
"TITLE": "3D Stereo-Modus", "TITLE": "3D Stereo-Modus",
"SPLIT_LEFT_RIGHT": "LINKS→RECHTS", "SPLIT_LEFT_RIGHT": "LINKS→RECHTS",
@ -69,8 +12,6 @@
"FULL_FRAME_BAT": "Full-BAT", "FULL_FRAME_BAT": "Full-BAT",
"ADJUST_MOUSE": "Maus anpassen" "ADJUST_MOUSE": "Maus anpassen"
}, },
"STEREO_3D_MODE_": {},
"ALIGN_TO_HMD": "An HMD ausrichten",
"MOUSE": { "MOUSE": {
"TITLE": "Mauskorrekturen", "TITLE": "Mauskorrekturen",
"WRONG_SCREEN_SELECTION_HELP": "Wenn der Cursor auf einem völlig anderen Bildschirm verschwindet,\nwurden die Bildschirme wahrscheinlich falsch ausgewählt. Siehe Lesezeichen.", "WRONG_SCREEN_SELECTION_HELP": "Wenn der Cursor auf einem völlig anderen Bildschirm verschwindet,\nwurden die Bildschirme wahrscheinlich falsch ausgewählt. Siehe Lesezeichen.",
@ -83,57 +24,157 @@
"ROTATE180": "180° gedreht", "ROTATE180": "180° gedreht",
"ROTATE270": "270° gedreht" "ROTATE270": "270° gedreht"
}, },
"ADJUST_CURVATURE": "Krümmung anpassen",
"ALIGN_TO_HMD": "An HMD ausrichten",
"ALPHA_BLEND_MODE": "Alpha-Blend-Modus",
"ANGLE_FADE": "Winkelverblassung",
"ANGLE_FADE_HELP": "Ausblenden, wenn nicht zum HMD ausgerichtet",
"BLENDING_ADDITIVE": "Additives Blending",
"BLOCK_INPUT": "Game-Input blockieren",
"CURVATURE": "Krümmung",
"DELETE": "Lang drücken, um aus dem aktuellen Set zu entfernen",
"DISABLE_GRAB": "Greifen deaktivieren",
"GLOBAL": "Immer sichtbar", "GLOBAL": "Immer sichtbar",
"ANGLE_FADE": "Winkelübergang", "HINT_POINT_WINDOW": "Zeige auf ein Fenster, um dessen Parameter zu ändern.\nVerlasse danach den Bearbeitungsmodus über die Schaltfläche rechts.",
"ANGLE_FADE_HELP": "Ausblenden, wenn nicht auf das Headset gerichtet", "INTERPOLATION": "Interpolation",
"BLOCK_INPUT": "Blockiere Spieleingabe", "KEYBOARD": "Tastatur",
"RESIZE_CORNER": "Zum Ändern der Größe ziehen" "LEAVE": "Bearbeitungsmodus verlassen",
"LOCK_INTERACTION": "Interaktion sperren",
"MOVE_PRESS_AND_DRAG": "Bewegen (drücken & ziehen)",
"OPACITY": "Undurchsichtigkeit",
"POS_ANCHORED": "Verankert: Bewegt sich gemeinsam mit dem Set. Standard.",
"POS_FLOATING": "Schwebend: Bewegt sich unabhängig, zentriert sich beim Anzeigen neu.",
"POS_HAND_L": "Folgt der linken Hand.",
"POS_HAND_R": "Rechter Hand folgen.",
"POS_HMD": "Folgt dem HMD.",
"POS_STATIC": "Statisch: Nicht Teil eines Sets, kein Recenter.",
"POSITIONING": "Positionierung",
"RESIZE_PRESS_AND_DRAG": "Größe ändern (drücken & ziehen)",
"RESIZE_CORNER": "Zum Vergrößern ziehen"
},
"DEFINITIONS": {
"ANCHORED": "Verankert",
"FLOATING": "Schwebend",
"STATIC": "Statisch",
"SET": "Set",
"WATCH": "Handgelenk-Uhr",
"DASHBOARD": "Dashboard",
"EDIT_MODE": "Bearbeitungsmodus",
"MIRROR": "Spiegelung",
"SETTINGS": "Einstellungen",
"KEYBOARD": "Tastatur",
"TASKBAR": "Taskleiste",
"FEATURES": "Features",
"OVERLAY": "Overlay"
},
"ANCHOR": {
"CENTER": "Zentrum"
},
"BAR": {
"ADD_MIRROR": "Neues Spiegel-Overlay hinzufügen",
"ADD_NEW_SET": "Neues Set hinzufügen",
"CLOSE_APP": "App schließen",
"CLOSE_OVERLAY": "Overlay schließen",
"DELETE_CURRENT_SET": "Aktuelles Set löschen",
"EDIT_MODE_TOGGLE": "Bearbeitungsmodus umschalten",
"FORCE_CLOSE_APP": "App zwangsbeenden",
"HANDSFREE": {
"EYE_ONLY": "Augenlaser",
"EYE_TRACKING": "Blick + Pinch",
"HMD": "HMD + Pinzgriff",
"HMD_ONLY": "HMD-Laser",
"NONE": "Aus",
"TITLE": "Freihandmodus"
},
"RELOAD_FROM_DISK": "XML von Festplatte neu laden",
"RESET_POSITION": "Position zurücksetzen",
"TOGGLE_VISIBILITY": "Sichtbarkeit umschalten",
"ADD_PASSTHRU": "Neues Passthrough-Fenster hinzufügen"
}, },
"DISABLED": "Deaktiviert",
"DEFAULT": "Standard", "DEFAULT": "Standard",
"DISABLED": "Deaktiviert",
"DONE": "Fertig",
"ALTTAB": {
"RELEASE_TO_FOCUS": "Ziele auf eine App und lass die Super-Taste los, um diese zu fokussieren.",
"WHILE_AIMING": "Während des Zielens",
"CLICK": "VR-Zeigerklick",
"GRABALL": "Gesamtes Set bewegen",
"GRAB": "Einzelnes Overlay verschieben",
"DASH": "Dashboard umschalten",
"EDIT": "Bearbeitungsmodus umschalten",
"SET": "Set wechseln",
"RECENTER": "Einblenden/Ausblenden/Zentrieren",
"GENERAL_BINDS": "Allgemeine Belegung",
"TOGGLE_CAPTURE": "Kontrolle an Desktop zurückgeben",
"FOCUS_MODE": "Fokus-Modus (Super halten)",
"CLOSE": "Fokussierte App schließen",
"MOUSE": "Echte Mausklicks & Scrollen wirken ebenfalls als VR-Pointer"
},
"GRAB": { "GRAB": {
"ADJUST_DISTANCE": "Entfernung anpassen", "ADJUST_DISTANCE": "Entfernung anpassen",
"ADJUST_SIZE": "Größe anpassen", "ADJUST_SIZE": "Größe anpassen",
"UNRESTRICTED_MOVEMENT": "Unbeschränkte Bewegung", "GRABBING_ANCHORED": "Verankerte Overlays bewegen sich mit dem Set. Trenne ein einzelnes Fenster, indem du es mit der anderen Hand greifst, während du das Set weiterhin festhältst.",
"GRABBING_WATCH": "Um die Hände zu vertauschen, bewegen Sie die Uhr vor sich und greifen Sie sie mit der anderen Hand.", "GRABBING_ANCHORED_EDIT": "Dieses Overlay bleibt am Zentrumsmarker verankert.",
"GRABBING_STATIC": "Dieses Overlay ist statisch und bleibt an Ort und Stelle, ignoriert die Neu-Zentrierung.", "GRABBING_FLOATING": "Dieses Overlay schwebt und bleibt an seiner Position, sofern es nicht neu zentriert wird.",
"GRABBING_ANCHORED": "Festgelegte Overlays bewegen sich alle zusammen. Trennen Sie ein einzelnes Fenster, indem Sie es mit der anderen Hand greifen, während Sie den Anker weiterhin greifen.", "GRABBING_FOLLOW": "Dieses Overlay folgt dem Gerät, an dem es befestigt ist.",
"GRABBING_ANCHORED_EDIT": "Diese Overlay-Darstellung bleibt an der Mittelmarkierung verankert.", "GRABBING_STATIC": "Dieses Overlay ist statisch und bleibt an seinem Platz, unabhängig vom Recentern.",
"GRABBING_FLOATING": "Diese Overlay-Darstellung ist frei schwebend und bleibt an Ort und Stelle, es sei denn, sie wird neu zentriert.", "GRABBING_WATCH": "Um die Seite zu wechseln, bewege die Uhr nach vorne und greife sie mit der anderen Hand.",
"GRABBING_FOLLOW": "Dieses Overlay wird dem Gerät folgen, an das es angehängt ist." "UNRESTRICTED_MOVEMENT": "Uneingeschränkte Bewegung"
},
"TOAST": {
"DEFAULT_TITLE": "Benachrichtigung",
"ERROR": "Fehler",
"CANNOT_REMOVE_SET": "Satz kann nicht entfernt werden!",
"NO_SET_SELECTED": "Kein Set ausgewählt.",
"LAST_EXISTING_SET": "Dies ist das letzte vorhandene Set.",
"EMPTY_SET": "Leeres Set!",
"ONE_CONTROLLER_ON_FLOOR": "Lege einen Controller auf den Boden!",
"CANNOT_ADD_SET": "Satz kann nicht hinzugefügt werden!",
"MAXIMUM_SETS_REACHED": "Maximale Anzahl an Sets erreicht.",
"FIXING_FLOOR_IN_X_SECS": "Boden wird in {SECONDS} Sekunde(n) repariert...",
"TITLE_SCREENCAST_FAIL": "Bildschirmübertragungsquelle konnte nicht gestartet werden!",
"LETS_ADD_OVERLAYS": "Lass uns einige Overlays aus der Taskleiste hinzufügen!"
},
"DONE": "Erledigt",
"WHISPER": {
"TRANSCRIBE": "Zum Transkribieren von Text gedrückt halten",
"PASTE": "Transkription in die Zwischenablage kopieren",
"PASTE_AND_GO": "Transkription kopieren und Ctrl-V an die fokussierte App senden",
"SEND_OSC": "Transkription an OSC-Chatbox senden",
"UNLOAD_AND_CLOSE": "Modell entladen und schließen",
"MODEL_NOT_DOWNLOADED": "Spracherkennung nicht eingerichtet!",
"DOWNLOAD_GUIDANCE": "Richten Sie die Spracherkennung unter Einstellungen -> Features ein!",
"INITIAL_TEXT": "Halten Sie die Mikrofontaste gedrückt, um mit der Transkription zu beginnen...",
"INIT_ERROR": "Fehler beim Starten der Whisper-Engine",
"ENTER_KEY": "Enter-Taste"
}, },
"SCREENCAST": { "SCREENCAST": {
"PENDING": "Bitte warten...", "PENDING": "Bitte warten...",
"QUEUED": "Warten auf die Bestätigung des Screen-Cast-Pop-ups eines anderen Overlays.", "QUEUED": "Warten auf die Bestätigung des Screen-Cast-Pop-ups eines anderen Overlays.",
"WAITING_FOR_USER_DESC": "Überprüfen Sie Ihren Desktop auf ein Pop-up zur Bildschirmübertragung.\nWählen Sie Folgendes aus:", "WAITING_FOR_USER_DESC": "Prüfe deinen Desktop auf ein Pop-up für die Bildschirmübertragung.\nWähle Folgendes aus:",
"WAITING_FOR_USER": "Überprüfen Sie Ihren Desktop auf ein Pop-up zur Bildschirmübertragung.", "WAITING_FOR_USER": "Prüfe deinen Desktop auf ein Pop-up zur Bildschirmübertragung.",
"FAIL": "Bildschirmübertragungsquelle konnte nicht initialisiert werden." "FAIL": "Bildschirmübertragung konnte nicht initialisiert werden."
},
"TOAST": {
"TITLE_SCREENCAST_FAIL": "Bildschirmübertragung konnte nicht gestartet werden!",
"CANNOT_ADD_SET": "Set konnte nicht hinzugefügt werden!",
"CANNOT_REMOVE_SET": "Set konnte nicht entfernt werden!",
"DEFAULT_TITLE": "Benachrichtigung",
"EMPTY_SET": "Leeres Set!",
"ERROR": "Fehler",
"FIXING_FLOOR_IN_X_SECS": "Boden wird in {SECONDS} Sekunde(n) angepasst...",
"LAST_EXISTING_SET": "Dies ist das letzte bestehende Set.",
"LETS_ADD_OVERLAYS": "Füge ein paar Overlays über die Taskleiste hinzu!",
"MAXIMUM_SETS_REACHED": "Maximale Anzahl an Sets erreicht.",
"NO_SET_SELECTED": "Kein Set ausgewählt.",
"ONE_CONTROLLER_ON_FLOOR": "Einen Controller auf den Boden legen!",
"NO_KEYMAPS_CONFIGURED": "Keine Tastaturbelegungen konfiguriert",
"NO_KEYMAPS_CONFIGURED_HELP": "Besuch wayvr.org, um zu erfahren, wie du deine Tastaturlayouts einrichtest!"
},
"WATCH": {
"ADD_NEW_SET": "Neues Set hinzufügen",
"CLEANUP_MIRRORS": "Nicht sichtbare\nSpiegelungen entfernen",
"DASHBOARD": "Dashboard",
"EDIT_MODE": "Bearbeitungsmodus",
"FIX_FLOOR": "Bodenhöhe fixieren",
"LONG_PRESS_TO_DELETE_SET": "Zum Löschen gedrückt halten",
"RECENTER": "Playspace zentrieren",
"SWITCH_TO_SET": "Zum Set wechseln",
"TOGGLE_FOR_CURRENT_SET": "Aktuelles Set umschalten"
},
"WHISPER": {
"TRANSCRIBE": "Zum Transkribieren gedrückt halten",
"PASTE": "Transkription in die Zwischenablage kopieren",
"PASTE_AND_GO": "Transkript kopieren und Ctrl-V an fokussierte App senden",
"SEND_OSC": "Transkription an OSC-Chatbox senden",
"UNLOAD_AND_CLOSE": "Modell entladen und schließen",
"MODEL_NOT_DOWNLOADED": "Spracherkennung nicht eingerichtet!",
"DOWNLOAD_GUIDANCE": "Spracherkennung unter Einstellungen > Features einrichten!",
"INITIAL_TEXT": "Mic-Taste gedrückt halten, um die Transkription zu starten...",
"INIT_ERROR": "Fehler beim Starten der Whisper-Engine",
"ENTER_KEY": "Enter-Taste"
},
"NOTIFICATION": {
"NOT_RUNNING_XR_VR": "Stelle sicher, dass Monado, WiVRn oder SteamVR läuft.",
"NOT_RUNNING_VR": "Stelle sicher, dass Monado, WiVRn oder SteamVR läuft.",
"NOT_RUNNING_XR": "Stelle sicher, dass Monado oder WiVRn läuft.",
"INVALID_ARGS": "Prüfe deine Startargumente.",
"COUD_NOT_CONNECT_TO_VR_RUNTIME": "Verbindung zum VR-Runtime fehlgeschlagen.",
"SELECT_SCREEN_CAST_FOR": "Screen-Cast für Display {DISPLAY} auswählen",
"CANNOT_CAPTURE_KBD_MOUSE": "Tastatur/Maus-Erfassung konnte nicht initialisiert werden!\nPrüfe, ob dein Benutzer in der Gruppe 'input' ist.",
"WE_ARE_GRABBING": "WayVR steuert jetzt deine Tastatur und Maus!\nDrücke Super+Z, um die Steuerung freizugeben."
} }
} }

View File

@ -0,0 +1,156 @@
DEFINITIONS.ANCHORED,Anchored,A movement option that makes this window move together with the rest of the workspace. Emphasize the “moving together” part as opposed to “not moving at all”.
DEFINITIONS.FLOATING,Floating,A movement option that lets this window float freely.
DEFINITIONS.STATIC,Static,"A movement option that keeps this window in place relative to the world origin. Emphasize the “not moving at all” part, as opposed to the “moving together” option which was previously translated as ${DEFINITIONS.ANCHORED}."
DEFINITIONS.SET,Set,A desktop workspace consisting of multiple windows.
DEFINITIONS.WATCH,Watch,Name of the small utility window that hovers around the users wrist.
DEFINITIONS.DASHBOARD,Dashboard,Name of the window that acts as the main menu / control panel of the application.
DEFINITIONS.EDIT_MODE,Edit Mode,Name of the mode that allows the user to make various tweaks to the current workspace and its windows.
DEFINITIONS.MIRROR,Mirror,A type of virtual window that displays a desktop window using screen mirroring.
DEFINITIONS.SETTINGS,Settings,The title of the settings panel.
DEFINITIONS.KEYBOARD,Keyboard,Name of the virtual keyboard
DEFINITIONS.TASKBAR,Taskbar,"A long panel showing currently active programs & windows, workspaces and a clock."
DEFINITIONS.FEATURES,Features,The section title of the section panel that deals with software features.
DEFINITIONS.OVERLAY,Overlay,"An overlay window inside VR, similar to a “desktop window”. Consider it a technical term."
ANCHOR.CENTER,Center,A marker on the floor describing where the center of the area is
BAR.ADD_MIRROR,Add a new mirror overlay,"Button to add a mirror overlay window. “Mirror” was previously translated as “${DEFINITIONS.MIRROR}”, “Overlay” was previously translated as “${DEFINITIONS.OVERLAY}”"
BAR.ADD_NEW_SET,Add new set,Button to add a new set. “Set” was previously translated as “${DEFINITIONS.SET}”
BAR.ADD_PASSTHRU,Add new pass-through cutout,Button to add a new window that lets the user see into their real-life environment using camera pass-through.
BAR.CLOSE_APP,Close app,Button to quit the app
BAR.CLOSE_OVERLAY,Close overlay,Button to close an overlay window. “Overlay” was previously translated as “{$DEFINITIONS.OVERLAY}”
BAR.DELETE_CURRENT_SET,Delete current set,Button to delete the currently selected set. “Set” was previously translated as “${DEFINITIONS.SET}”
BAR.EDIT_MODE_TOGGLE,Toggle edit mode,Button to toggle Edit mode. “Edit mode” was previously translated as “${DEFINITIONS.EDIT_MODE}”
BAR.FORCE_CLOSE_APP,Force close app,Button to terminate an application from the process manager
BAR.HANDSFREE.EYE_ONLY,Eye laser,Option to aim with the users eye gaze (eye tracking)
BAR.HANDSFREE.EYE_TRACKING,Eye + pinch,Option to aim with the users eye gaze (eye tracking) and input using pinch gestures
BAR.HANDSFREE.HMD,HMD + pinch,Option to aim with the HMD and input using pinch gestures
BAR.HANDSFREE.HMD_ONLY,HMD laser,Option to aim with the HMD
BAR.HANDSFREE.NONE,Off,Option to not use this feature at all
BAR.HANDSFREE.TITLE,Hands-free mode,"Title of a mode that lets the user interact with the software without controllers, keyboard or mouse."
BAR.RELOAD_FROM_DISK,Reload XML from disk,Button to reload the XML configuration file from disk
BAR.RESET_POSITION,Reset position,Button to reset the selected object to its default position and orientation
BAR.TOGGLE_VISIBILITY,Toggle visibility,Button to toggle the visibility of this object
DEFAULT,Default,Default value used when no custom setting is applied
DISABLED,Disabled,Feature or setting is turned off
DONE,Done,Title of a pop-up dialog explaining that the requested action has completed successfully.
EDIT_MODE.ADJUST_CURVATURE,Adjust curvature,Tooltip on a settings page to adjust screen panel curvature
EDIT_MODE.ALIGN_TO_HMD,Align to HMD,Checkbox for a window to always rotate (billboard) towards the viewer
EDIT_MODE.ALPHA_BLEND_MODE,Alpha blend mode,Blending mode for window transparency
EDIT_MODE.ANGLE_FADE,Angle fade,Fade based on viewing angle
EDIT_MODE.ANGLE_FADE_HELP,Fade when not facing HMD,Automatically fades the window when it is not facing the HMD
EDIT_MODE.BLENDING_ADDITIVE,Additive blending,Additive blending mode for overlays
EDIT_MODE.BLOCK_INPUT,Block game input,Block games form receiving controller input while pointing at the window
EDIT_MODE.CURVATURE,Curvature,Adjust the curvature of the window panel
EDIT_MODE.DELETE,Long press to remove from current set,Button tooltip to remove this window from the current set. “Set” was previously translated as “${DEFINITIONS.SET}”
EDIT_MODE.DISABLE_GRAB,Disable grab,Tooltip on a button that disable grabbing/movement on this this window
EDIT_MODE.GLOBAL,Always visible,Tooltip on a checkbox that makes this window always visible regardless of the active set/workspace
EDIT_MODE.HINT_POINT_WINDOW,"Point at a window to change its parameters.
Once done, leave edit mode using the button on the right.",Instructions displayed to the user. “Edit mode” was previously translated as “${DEFINITIONS.EDIT_MODE}”
EDIT_MODE.INTERPOLATION,Interpolation,Option for smoothing window movement
EDIT_MODE.KEYBOARD,Keyboard,Button to toggle the keyboard. “Keyboard” was previously translated as “${DEFINITIONS.KEYBOARD}”
EDIT_MODE.LEAVE,Leave edit mode,Option to exit edit mode. “Edit mode” was previously translated as “${DEFINITIONS.EDIT_MODE}”
EDIT_MODE.LOCK_INTERACTION,Lock interaction,Option to disable pointer input on this window. The pointer laser will pass through the window completely.
EDIT_MODE.MOUSE.FLIP180,Flipped 180°,Option to mirror the mouse movement horizontally and rotate 180 degrees. Emphasize the part about mirroring / flipping (not just rotation). Keep the translation as short as possible.
EDIT_MODE.MOUSE.FLIP270,Flipped 270°,Option to mirror the mouse movement horizontally and rotate 270 degrees. Emphasize the part about mirroring / flipping (not just rotation). Keep the translation as short as possible.
EDIT_MODE.MOUSE.FLIP90,Flipped 90°,Option to mirror the mouse movement horizontally and rotate 90 degrees. Emphasize the part about mirroring / flipping (not just rotation). Keep the translation as short as possible.
EDIT_MODE.MOUSE.FLIPPED,Flipped,Option to mirror the mouse movement horizontally. Keep the translation as short as possible.
EDIT_MODE.MOUSE.NORMAL,Normal,Option to select default mouse movement behavior. Keep the translation as short as possible.
EDIT_MODE.MOUSE.ROTATE180,Rotated 180°,Option to rotate mouse movement by 180 degrees. Emphasize the part about rotation (no mirroring or flipping). Keep the translation as short as possible.
EDIT_MODE.MOUSE.ROTATE270,Rotated 270°,Option to rotate mouse movement by 270 degrees. Emphasize the part about rotation (no mirroring or flipping). Keep the translation as short as possible.
EDIT_MODE.MOUSE.ROTATE90,Rotated 90°,Option to rotate mouse movement by 90 degrees. Emphasize the part about rotation (no mirroring or flipping). Keep the translation as short as possible.
EDIT_MODE.MOUSE.TITLE,Mouse fixes,Title to adjust quirks in order to get desired mouse movement behavior
EDIT_MODE.MOUSE.WRONG_SCREEN_SELECTION_HELP,"If the cursor moves on a completely different screen,
the screens were likely selected wrong. See readme.",Tooltip to explain possible user error.
EDIT_MODE.MOVE_PRESS_AND_DRAG,Move (press & drag),Tooltip hinting to move the window by pressing and dragging with the pointer
EDIT_MODE.OPACITY,Opacity,Title. Adjust transparency of the window
EDIT_MODE.POS_ANCHORED,Anchored: Moves together with set. Default.,"Tooltip for a an option that changes movement/positioning behavior. “Anchored” was previously translated as “${DEFINITIONS.ANCHORED}”, “Set” was previously translated as “${DEFINITIONS.SET}”"
EDIT_MODE.POS_FLOATING,"Floating: Moves independently, recenters when shown.",Tooltip for a an option that changes movement/positioning behavior. “Floating” was previously translated as “${DEFINITIONS.FLOATING}”
EDIT_MODE.POS_HAND_L,Follow the left hand.,Tooltip for a an option that changes movement/positioning behavior.
EDIT_MODE.POS_HAND_R,Follow the right hand.,Tooltip for a an option that changes movement/positioning behavior.
EDIT_MODE.POS_HMD,Follow the HMD.,Tooltip for a an option that changes movement/positioning behavior.
EDIT_MODE.POS_STATIC,"Static: Not part of any set, no recenter.","Tooltip for a an option that changes movement/positioning behavior. “Static” was previously translated as “${DEFINITIONS.STATIC}”, “Set” was previously translated as “${DEFINITIONS.SET}”"
EDIT_MODE.POSITIONING,Positioning,Title for positioning modes for the window
EDIT_MODE.RESIZE_PRESS_AND_DRAG,Resize (press & drag),Tooltip on the resize button; resize overlay by pressing and dragging
EDIT_MODE.RESIZE_CORNER,Drag to resize,Tooltip when user is hovering the resize grip of a window
EDIT_MODE.STEREO_3D_MODE.ADJUST_MOUSE,Adjust mouse,Checkbox to adjust mouse movement for 3D mode
EDIT_MODE.STEREO_3D_MODE.FULL_FRAME,Full 3D,Checkbox to use full 3D frame
EDIT_MODE.STEREO_3D_MODE.FULL_FRAME_BAT,Full-BAT,Checkbox to use full frame BAT (bottom-left / top-right) 3D format
EDIT_MODE.STEREO_3D_MODE.FULL_FRAME_SBS,Full-SBS,Checkbox to use full frame SBS (side-by-side) 3D format
EDIT_MODE.STEREO_3D_MODE.FULL_FRAME_TAB,Full-TAB,Checkbox to use full frame TAB (top-bottom / left-right) 3D format
EDIT_MODE.STEREO_3D_MODE.SPLIT_BOTTOM_TOP,BOTTOM→TOP,"Side-by-side 3D mode selection. Bottom half shows to left eye, top half to right eye"
EDIT_MODE.STEREO_3D_MODE.SPLIT_LEFT_RIGHT,LEFT→RIGHT,"Side-by-side 3D mode selection. Left half shows to left eye, right half to right eye"
EDIT_MODE.STEREO_3D_MODE.SPLIT_RIGHT_LEFT,RIGHT→LEFT,"Side-by-side 3D mode selection. Right half shows to left eye, left half to right eye"
EDIT_MODE.STEREO_3D_MODE.SPLIT_TOP_BOTTOM,TOP→BOTTOM,"Side-by-side 3D mode selection. Top half shows to left eye, bottom half to right eye"
EDIT_MODE.STEREO_3D_MODE.TITLE,3D Stereo Mode,Title for “Stereo 3D display mode” section
ALTTAB.RELEASE_TO_FOCUS,Aim at an app and release Super to focus that app.,Instructions on how to control the task switcher.
ALTTAB.WHILE_AIMING,While aiming,Title of a section of key bindings that can be activated while aiming the laser.
ALTTAB.CLICK,VR pointer click,Key binding action that mimics a click with the VR laser pointer.
ALTTAB.GRABALL,Move entire set,Key binding action to grab and move the entire set. “Set” was previously translated as “${DEFINITIONS.SET}”
ALTTAB.GRAB,Move individual overlay,Key binding action to grab and move a single overlay. “Overlay” was previously translated as “{$DEFINITIONS.OVERLAY}”
ALTTAB.DASH,Toggle dashboard,Key binding action that toggles the dashboard. “Dashboard” was previously translated as “${DEFINITIONS.DASHBOARD}”
ALTTAB.EDIT,Toggle edit mode,Key binding action that toggles edit mode. “Edit mode” was previously translated as “${DEFINITIONS.EDIT_MODE}”
ALTTAB.SET,Switch set,Key binding action to switch between sets. “Set” was previously translated as “${DEFINITIONS.SET}”
ALTTAB.RECENTER,Show/hide/recenter,"Key binding action to show, hide, or recenter the current set. “Set” was previously translated as “${DEFINITIONS.SET}”"
ALTTAB.GENERAL_BINDS,General bindings,Title for key bindings that dont need any specific criteria
ALTTAB.TOGGLE_CAPTURE,Give control back to desktop,Key binding action that releases exclusive input capture
ALTTAB.FOCUS_MODE,Focus mode (hold Super),"Key binding action to enter into a task-switcher kind of mode, like Alt-Tab."
ALTTAB.CLOSE,Close focused app,Key binding action to close the application that is being aimed at.
ALTTAB.MOUSE,Real mouse clicks & scroll also translate to VR pointer,Help text explaining to the user that clicks and scroll with their real (physical) mouse will act as if it was done using a VR controller.
GRAB.ADJUST_DISTANCE,Adjust distance,Key binding action to adjust distance of the window in 3D space (in a push/pull motion)
GRAB.ADJUST_SIZE,Adjust size,Key binding action to adjust size of the window
GRAB.GRABBING_ANCHORED,Anchored overlays move with the set. Separate a single window by grabbing it with the other hand while still grabbing the set.,"Help explanation. “Anchored” was previously translated as “${DEFINITIONS.ANCHORED}”, “Set” was previously translated as “${DEFINITIONS.SET}”"
GRAB.GRABBING_ANCHORED_EDIT,This overlay will stay anchored to the center marker.,Help text to explain the movement behavior of this window. “Center” was previously translated as “${ANCHOR.CENTER}”
GRAB.GRABBING_FLOATING,"This overlay is Floating and will stay in place, unless recentered.",Help text to explain the movement behavior of this window. “Floating” was previously translated as “${DEFINITIONS.FLOATING}”
GRAB.GRABBING_FOLLOW,This overlay will follow the device it is attached to.,Help text to explain the movement behavior of this window.
GRAB.GRABBING_STATIC,"This overlay is Static and will stay in place, ignoring recenter.",Help text to explain the movement behavior of this window. “Static” was previously translated as “${DEFINITIONS.STATIC}”
GRAB.GRABBING_WATCH,"To swap hands, move the watch in front and grab it with the other hand.",Help text to explain the user how to switch which hand the watch is on. “Watch” was previously translated as “${DEFINITIONS.WATCH}”
GRAB.UNRESTRICTED_MOVEMENT,Unrestricted movement,"Option that allows the user to move and rotate this window freely, in a raw manner, without assistance such as angle snapping."
SCREENCAST.PENDING,Please wait...,Title saying that the operation is not yet completed.
SCREENCAST.QUEUED,Waiting for a different overlay's screen cast pop-up to be approved.,Instructions asking the user to pay attention to a different screen cast pop-up. “Overlay” was previously translated as “${DEFINITIONS.OVERLAY}”
SCREENCAST.WAITING_FOR_USER_DESC,"Check your desktop for a screen cast pop-up.
Select the following:",Instructions to the user.
SCREENCAST.WAITING_FOR_USER,Check your desktop for a screen cast pop-up.,Instructions to the user.
SCREENCAST.FAIL,Could not initialize screen cast source.,Error message on a window that normally displays screen casts.
TOAST.TITLE_SCREENCAST_FAIL,Could not start screen cast source!,Error message on a window that normally displays screen casts.
TOAST.CANNOT_ADD_SET,Cannot add set!,Error message telling the user the set could not be added. “Set” was previously translated as “${DEFINITIONS.SET}”
TOAST.CANNOT_REMOVE_SET,Cannot remove set!,Error message telling the user the set could not be removed. “Set” was previously translated as “${DEFINITIONS.SET}”
TOAST.DEFAULT_TITLE,Notification,Default title of notifications
TOAST.EMPTY_SET,Empty set!,Title of a pop-up when the user switches to an empty set. “Set” was previously translated as “${DEFINITIONS.SET}”
TOAST.ERROR,Error,Default title for error pop-ups
TOAST.FIXING_FLOOR_IN_X_SECS,Fixing floor in {SECONDS} second(s)...,A countdown pop-up for automatically adjusting floor height. Keep the {SECONDS} part intact as its a parameter.
TOAST.LAST_EXISTING_SET,This is the last existing set.,Notification body explaining that the set cannot be removed because this is the last existing set. “Set” was previously translated as “${DEFINITIONS.SET}”
TOAST.LETS_ADD_OVERLAYS,Let's add some overlays from the taskbar!,"Instructions prompting the user to add overlays. “Taskbar” was previously translated as “${DEFINITIONS.TASKBAR}”, “Overlay” was previously translated as “${DEFINITIONS.OVERLAY}”"
TOAST.MAXIMUM_SETS_REACHED,Maximum number of sets reached.,Notification body explaining that a new set could not be added because were already at the limit. “Set” was previously translated as “${DEFINITIONS.SET}”
TOAST.NO_KEYMAPS_CONFIGURED,No keyboard layouts configured,Title of notification
TOAST.NO_KEYMAPS_CONFIGURED_HELP,Check the wayvr.org on how to set up your keyboard layouts!,Body of notification
TOAST.NO_SET_SELECTED,No set is selected.,Notification body explaining that the operation could not be executed because the user has not selected a set. “Set” was previously translated as “${DEFINITIONS.SET}”
TOAST.ONE_CONTROLLER_ON_FLOOR,Place one controller on the floor!,Instructions to the user for automated floor calibration.
WATCH.ADD_NEW_SET,Add a new set,Button to add a new set. “Set” was previously translated as “${DEFINITIONS.SET}”
WATCH.CLEANUP_MIRRORS,"Remove mirrors that are
not currently visible",Button to remove mirrors. “Mirror” was previously translated as “${DEFINITIONS.MIRROR}”
WATCH.DASHBOARD,Dashboard,Button to toggle “${DEFINITIONS.DASHBOARD}”
WATCH.EDIT_MODE,Edit Mode,Button to toggle “${DEFINITIONS.EDIT_MODE}”
WATCH.FIX_FLOOR,Fix floor level,Tooltip for a button that adjusts the height of the VR environment based on the floor level.
WATCH.LONG_PRESS_TO_DELETE_SET,Hold to delete,Tooltip for a button that deletes a set. “Set” was previously translated as “${DEFINITIONS.SET}”
WATCH.RECENTER,Recenter playspace,Tooltip for a button that recenters the VR environment around the player.
WATCH.SWITCH_TO_SET,Switch to set,Tooltip for a button that switches to a different set. “Set” was previously translated as “${DEFINITIONS.SET}”
WATCH.TOGGLE_FOR_CURRENT_SET,Toggle for current set,Tooltip for a button that toggles the visibility of the current window in the current workspace.
WHISPER.TRANSCRIBE,Press and hold to transcribe text,Tooltip for a button that needs to be held while transcribing text.
WHISPER.PASTE,Copy transcription to clipboard,Tooltip for a button that copies the transcribed text to clipboard.
WHISPER.PASTE_AND_GO,Copy transcription and send Ctrl-V to focused app,Tooltip for a button that copies the transcribed text to clipboard and pastes it to the focused app using an emulated Ctrl-V sequence.
WHISPER.SEND_OSC,Send transcription to OSC chatbox,Tooltip for a button that sends the transcribed text via OSC.
WHISPER.UNLOAD_AND_CLOSE,Unload model and close,Unload AI model from VRAM and close the transcription window
WHISPER.MODEL_NOT_DOWNLOADED,Speech-to-text not set up!,Error message warning the user about an incomplete setup.
WHISPER.DOWNLOAD_GUIDANCE,"Set up speech-to-text under settings, features!",Help message prompting the user to finish setup in the ${DEFINITIONS.FEATURES} tab of ${DEFINITIONS.SETTINGS}
WHISPER.INITIAL_TEXT,Press and hold the mic button to start transcribing...,Help message prompting the user to hold down the button with the microphone icon.
WHISPER.INIT_ERROR,Error while starting Whisper engine,Error message.
WHISPER.ENTER_KEY,Enter key,Button to send an Enter key on the emulated keyboard
NOTIFICATION.COUD_NOT_CONNECT_TO_VR_RUNTIME,"Could not connect to VR runtime.",A system notification which shows up on initialization failure.
NOTIFICATION.NOT_RUNNING_XR_VR,"Make sure that Monado, WiVRn or SteamVR is running.",A system notification which shows up on initialization failure.
NOTIFICATION.NOT_RUNNING_VR,"Make sure that Monado, WiVRn or SteamVR is running.",A system notification which shows up on initialization failure.
NOTIFICATION.NOT_RUNNING_XR,"Make sure that Monado or WiVRn is running.",A system notification which shows up on initialization failure.
NOTIFICATION.INVALID_ARGS,"Check your launch arguments.",A system notification which shows up on initialization failure.
NOTIFICATION.SELECT_SCREEN_CAST_FOR,"Select screen cast for display {DISPLAY}",A system notification which shows up on monitor selection request. DISPLAY is the monitor name.
NOTIFICATION.CANNOT_CAPTURE_KBD_MOUSE,"Could not initialize keyboard/mouse capture!
Check that your user is in the 'input' group.",A system notification which shows up in case if we can't control the computer via keyboard or mouse. Leave `input` key as-is - it's a linux group name.
NOTIFICATION.WE_ARE_GRABBING,"WayVR has your keyboard and mouse!
Press Super+Z to release.",A system notification which shows up in case if WayVR starts capturing physical keyboard and mouse events. The user consciously chose this option - it's just a message for him how to exit the mode later. Emphasis on user discretion
1 DEFINITIONS.ANCHORED Anchored A movement option that makes this window move together with the rest of the workspace. Emphasize the “moving together” part as opposed to “not moving at all”.
2 DEFINITIONS.FLOATING Floating A movement option that lets this window float freely.
3 DEFINITIONS.STATIC Static A movement option that keeps this window in place relative to the world origin. Emphasize the “not moving at all” part, as opposed to the “moving together” option which was previously translated as ${DEFINITIONS.ANCHORED}.
4 DEFINITIONS.SET Set A desktop workspace consisting of multiple windows.
5 DEFINITIONS.WATCH Watch Name of the small utility window that hovers around the user’s wrist.
6 DEFINITIONS.DASHBOARD Dashboard Name of the window that acts as the main menu / control panel of the application.
7 DEFINITIONS.EDIT_MODE Edit Mode Name of the mode that allows the user to make various tweaks to the current workspace and its windows.
8 DEFINITIONS.MIRROR Mirror A type of virtual window that displays a desktop window using screen mirroring.
9 DEFINITIONS.SETTINGS Settings The title of the settings panel.
10 DEFINITIONS.KEYBOARD Keyboard Name of the virtual keyboard
11 DEFINITIONS.TASKBAR Taskbar A long panel showing currently active programs & windows, workspaces and a clock.
12 DEFINITIONS.FEATURES Features The section title of the section panel that deals with software features.
13 DEFINITIONS.OVERLAY Overlay An overlay window inside VR, similar to a “desktop window”. Consider it a technical term.
14 ANCHOR.CENTER Center A marker on the floor describing where the center of the area is
15 BAR.ADD_MIRROR Add a new mirror overlay Button to add a mirror overlay window. “Mirror” was previously translated as “${DEFINITIONS.MIRROR}”, “Overlay” was previously translated as “${DEFINITIONS.OVERLAY}”
16 BAR.ADD_NEW_SET Add new set Button to add a new set. “Set” was previously translated as “${DEFINITIONS.SET}”
17 BAR.ADD_PASSTHRU Add new pass-through cutout Button to add a new window that lets the user see into their real-life environment using camera pass-through.
18 BAR.CLOSE_APP Close app Button to quit the app
19 BAR.CLOSE_OVERLAY Close overlay Button to close an overlay window. “Overlay” was previously translated as “{$DEFINITIONS.OVERLAY}”
20 BAR.DELETE_CURRENT_SET Delete current set Button to delete the currently selected set. “Set” was previously translated as “${DEFINITIONS.SET}”
21 BAR.EDIT_MODE_TOGGLE Toggle edit mode Button to toggle Edit mode. “Edit mode” was previously translated as “${DEFINITIONS.EDIT_MODE}”
22 BAR.FORCE_CLOSE_APP Force close app Button to terminate an application from the process manager
23 BAR.HANDSFREE.EYE_ONLY Eye laser Option to aim with the user’s eye gaze (eye tracking)
24 BAR.HANDSFREE.EYE_TRACKING Eye + pinch Option to aim with the user’s eye gaze (eye tracking) and input using pinch gestures
25 BAR.HANDSFREE.HMD HMD + pinch Option to aim with the HMD and input using pinch gestures
26 BAR.HANDSFREE.HMD_ONLY HMD laser Option to aim with the HMD
27 BAR.HANDSFREE.NONE Off Option to not use this feature at all
28 BAR.HANDSFREE.TITLE Hands-free mode Title of a mode that lets the user interact with the software without controllers, keyboard or mouse.
29 BAR.RELOAD_FROM_DISK Reload XML from disk Button to reload the XML configuration file from disk
30 BAR.RESET_POSITION Reset position Button to reset the selected object to its default position and orientation
31 BAR.TOGGLE_VISIBILITY Toggle visibility Button to toggle the visibility of this object
32 DEFAULT Default Default value used when no custom setting is applied
33 DISABLED Disabled Feature or setting is turned off
34 DONE Done Title of a pop-up dialog explaining that the requested action has completed successfully.
35 EDIT_MODE.ADJUST_CURVATURE Adjust curvature Tooltip on a settings page to adjust screen panel curvature
36 EDIT_MODE.ALIGN_TO_HMD Align to HMD Checkbox for a window to always rotate (billboard) towards the viewer
37 EDIT_MODE.ALPHA_BLEND_MODE Alpha blend mode Blending mode for window transparency
38 EDIT_MODE.ANGLE_FADE Angle fade Fade based on viewing angle
39 EDIT_MODE.ANGLE_FADE_HELP Fade when not facing HMD Automatically fades the window when it is not facing the HMD
40 EDIT_MODE.BLENDING_ADDITIVE Additive blending Additive blending mode for overlays
41 EDIT_MODE.BLOCK_INPUT Block game input Block games form receiving controller input while pointing at the window
42 EDIT_MODE.CURVATURE Curvature Adjust the curvature of the window panel
43 EDIT_MODE.DELETE Long press to remove from current set Button tooltip to remove this window from the current set. “Set” was previously translated as “${DEFINITIONS.SET}”
44 EDIT_MODE.DISABLE_GRAB Disable grab Tooltip on a button that disable grabbing/movement on this this window
45 EDIT_MODE.GLOBAL Always visible Tooltip on a checkbox that makes this window always visible regardless of the active set/workspace
46 EDIT_MODE.HINT_POINT_WINDOW Point at a window to change its parameters. Once done, leave edit mode using the button on the right. Instructions displayed to the user. “Edit mode” was previously translated as “${DEFINITIONS.EDIT_MODE}”
47 EDIT_MODE.INTERPOLATION Interpolation Option for smoothing window movement
48 EDIT_MODE.KEYBOARD Keyboard Button to toggle the keyboard. “Keyboard” was previously translated as “${DEFINITIONS.KEYBOARD}”
49 EDIT_MODE.LEAVE Leave edit mode Option to exit edit mode. “Edit mode” was previously translated as “${DEFINITIONS.EDIT_MODE}”
50 EDIT_MODE.LOCK_INTERACTION Lock interaction Option to disable pointer input on this window. The pointer laser will pass through the window completely.
51 EDIT_MODE.MOUSE.FLIP180 Flipped 180° Option to mirror the mouse movement horizontally and rotate 180 degrees. Emphasize the part about mirroring / flipping (not just rotation). Keep the translation as short as possible.
52 EDIT_MODE.MOUSE.FLIP270 Flipped 270° Option to mirror the mouse movement horizontally and rotate 270 degrees. Emphasize the part about mirroring / flipping (not just rotation). Keep the translation as short as possible.
53 EDIT_MODE.MOUSE.FLIP90 Flipped 90° Option to mirror the mouse movement horizontally and rotate 90 degrees. Emphasize the part about mirroring / flipping (not just rotation). Keep the translation as short as possible.
54 EDIT_MODE.MOUSE.FLIPPED Flipped Option to mirror the mouse movement horizontally. Keep the translation as short as possible.
55 EDIT_MODE.MOUSE.NORMAL Normal Option to select default mouse movement behavior. Keep the translation as short as possible.
56 EDIT_MODE.MOUSE.ROTATE180 Rotated 180° Option to rotate mouse movement by 180 degrees. Emphasize the part about rotation (no mirroring or flipping). Keep the translation as short as possible.
57 EDIT_MODE.MOUSE.ROTATE270 Rotated 270° Option to rotate mouse movement by 270 degrees. Emphasize the part about rotation (no mirroring or flipping). Keep the translation as short as possible.
58 EDIT_MODE.MOUSE.ROTATE90 Rotated 90° Option to rotate mouse movement by 90 degrees. Emphasize the part about rotation (no mirroring or flipping). Keep the translation as short as possible.
59 EDIT_MODE.MOUSE.TITLE Mouse fixes Title to adjust quirks in order to get desired mouse movement behavior
60 EDIT_MODE.MOUSE.WRONG_SCREEN_SELECTION_HELP If the cursor moves on a completely different screen, the screens were likely selected wrong. See readme. Tooltip to explain possible user error.
61 EDIT_MODE.MOVE_PRESS_AND_DRAG Move (press & drag) Tooltip hinting to move the window by pressing and dragging with the pointer
62 EDIT_MODE.OPACITY Opacity Title. Adjust transparency of the window
63 EDIT_MODE.POS_ANCHORED Anchored: Moves together with set. Default. Tooltip for a an option that changes movement/positioning behavior. “Anchored” was previously translated as “${DEFINITIONS.ANCHORED}”, “Set” was previously translated as “${DEFINITIONS.SET}”
64 EDIT_MODE.POS_FLOATING Floating: Moves independently, recenters when shown. Tooltip for a an option that changes movement/positioning behavior. “Floating” was previously translated as “${DEFINITIONS.FLOATING}”
65 EDIT_MODE.POS_HAND_L Follow the left hand. Tooltip for a an option that changes movement/positioning behavior.
66 EDIT_MODE.POS_HAND_R Follow the right hand. Tooltip for a an option that changes movement/positioning behavior.
67 EDIT_MODE.POS_HMD Follow the HMD. Tooltip for a an option that changes movement/positioning behavior.
68 EDIT_MODE.POS_STATIC Static: Not part of any set, no recenter. Tooltip for a an option that changes movement/positioning behavior. “Static” was previously translated as “${DEFINITIONS.STATIC}”, “Set” was previously translated as “${DEFINITIONS.SET}”
69 EDIT_MODE.POSITIONING Positioning Title for positioning modes for the window
70 EDIT_MODE.RESIZE_PRESS_AND_DRAG Resize (press & drag) Tooltip on the resize button; resize overlay by pressing and dragging
71 EDIT_MODE.RESIZE_CORNER Drag to resize Tooltip when user is hovering the resize grip of a window
72 EDIT_MODE.STEREO_3D_MODE.ADJUST_MOUSE Adjust mouse Checkbox to adjust mouse movement for 3D mode
73 EDIT_MODE.STEREO_3D_MODE.FULL_FRAME Full 3D Checkbox to use full 3D frame
74 EDIT_MODE.STEREO_3D_MODE.FULL_FRAME_BAT Full-BAT Checkbox to use full frame BAT (bottom-left / top-right) 3D format
75 EDIT_MODE.STEREO_3D_MODE.FULL_FRAME_SBS Full-SBS Checkbox to use full frame SBS (side-by-side) 3D format
76 EDIT_MODE.STEREO_3D_MODE.FULL_FRAME_TAB Full-TAB Checkbox to use full frame TAB (top-bottom / left-right) 3D format
77 EDIT_MODE.STEREO_3D_MODE.SPLIT_BOTTOM_TOP BOTTOM→TOP Side-by-side 3D mode selection. Bottom half shows to left eye, top half to right eye
78 EDIT_MODE.STEREO_3D_MODE.SPLIT_LEFT_RIGHT LEFT→RIGHT Side-by-side 3D mode selection. Left half shows to left eye, right half to right eye
79 EDIT_MODE.STEREO_3D_MODE.SPLIT_RIGHT_LEFT RIGHT→LEFT Side-by-side 3D mode selection. Right half shows to left eye, left half to right eye
80 EDIT_MODE.STEREO_3D_MODE.SPLIT_TOP_BOTTOM TOP→BOTTOM Side-by-side 3D mode selection. Top half shows to left eye, bottom half to right eye
81 EDIT_MODE.STEREO_3D_MODE.TITLE 3D Stereo Mode Title for “Stereo 3D display mode” section
82 ALTTAB.RELEASE_TO_FOCUS Aim at an app and release Super to focus that app. Instructions on how to control the task switcher.
83 ALTTAB.WHILE_AIMING While aiming Title of a section of key bindings that can be activated while aiming the laser.
84 ALTTAB.CLICK VR pointer click Key binding action that mimics a click with the VR laser pointer.
85 ALTTAB.GRABALL Move entire set Key binding action to grab and move the entire set. “Set” was previously translated as “${DEFINITIONS.SET}”
86 ALTTAB.GRAB Move individual overlay Key binding action to grab and move a single overlay. “Overlay” was previously translated as “{$DEFINITIONS.OVERLAY}”
87 ALTTAB.DASH Toggle dashboard Key binding action that toggles the dashboard. “Dashboard” was previously translated as “${DEFINITIONS.DASHBOARD}”
88 ALTTAB.EDIT Toggle edit mode Key binding action that toggles edit mode. “Edit mode” was previously translated as “${DEFINITIONS.EDIT_MODE}”
89 ALTTAB.SET Switch set Key binding action to switch between sets. “Set” was previously translated as “${DEFINITIONS.SET}”
90 ALTTAB.RECENTER Show/hide/recenter Key binding action to show, hide, or recenter the current set. “Set” was previously translated as “${DEFINITIONS.SET}”
91 ALTTAB.GENERAL_BINDS General bindings Title for key bindings that don’t need any specific criteria
92 ALTTAB.TOGGLE_CAPTURE Give control back to desktop Key binding action that releases exclusive input capture
93 ALTTAB.FOCUS_MODE Focus mode (hold Super) Key binding action to enter into a task-switcher kind of mode, like Alt-Tab.
94 ALTTAB.CLOSE Close focused app Key binding action to close the application that is being aimed at.
95 ALTTAB.MOUSE Real mouse clicks & scroll also translate to VR pointer Help text explaining to the user that clicks and scroll with their real (physical) mouse will act as if it was done using a VR controller.
96 GRAB.ADJUST_DISTANCE Adjust distance Key binding action to adjust distance of the window in 3D space (in a push/pull motion)
97 GRAB.ADJUST_SIZE Adjust size Key binding action to adjust size of the window
98 GRAB.GRABBING_ANCHORED Anchored overlays move with the set. Separate a single window by grabbing it with the other hand while still grabbing the set. Help explanation. “Anchored” was previously translated as “${DEFINITIONS.ANCHORED}”, “Set” was previously translated as “${DEFINITIONS.SET}”
99 GRAB.GRABBING_ANCHORED_EDIT This overlay will stay anchored to the center marker. Help text to explain the movement behavior of this window. “Center” was previously translated as “${ANCHOR.CENTER}”
100 GRAB.GRABBING_FLOATING This overlay is Floating and will stay in place, unless recentered. Help text to explain the movement behavior of this window. “Floating” was previously translated as “${DEFINITIONS.FLOATING}”
101 GRAB.GRABBING_FOLLOW This overlay will follow the device it is attached to. Help text to explain the movement behavior of this window.
102 GRAB.GRABBING_STATIC This overlay is Static and will stay in place, ignoring recenter. Help text to explain the movement behavior of this window. “Static” was previously translated as “${DEFINITIONS.STATIC}”
103 GRAB.GRABBING_WATCH To swap hands, move the watch in front and grab it with the other hand. Help text to explain the user how to switch which hand the watch is on. “Watch” was previously translated as “${DEFINITIONS.WATCH}”
104 GRAB.UNRESTRICTED_MOVEMENT Unrestricted movement Option that allows the user to move and rotate this window freely, in a raw manner, without assistance such as angle snapping.
105 SCREENCAST.PENDING Please wait... Title saying that the operation is not yet completed.
106 SCREENCAST.QUEUED Waiting for a different overlay's screen cast pop-up to be approved. Instructions asking the user to pay attention to a different screen cast pop-up. “Overlay” was previously translated as “${DEFINITIONS.OVERLAY}”
107 SCREENCAST.WAITING_FOR_USER_DESC Check your desktop for a screen cast pop-up. Select the following: Instructions to the user.
108 SCREENCAST.WAITING_FOR_USER Check your desktop for a screen cast pop-up. Instructions to the user.
109 SCREENCAST.FAIL Could not initialize screen cast source. Error message on a window that normally displays screen casts.
110 TOAST.TITLE_SCREENCAST_FAIL Could not start screen cast source! Error message on a window that normally displays screen casts.
111 TOAST.CANNOT_ADD_SET Cannot add set! Error message telling the user the set could not be added. “Set” was previously translated as “${DEFINITIONS.SET}”
112 TOAST.CANNOT_REMOVE_SET Cannot remove set! Error message telling the user the set could not be removed. “Set” was previously translated as “${DEFINITIONS.SET}”
113 TOAST.DEFAULT_TITLE Notification Default title of notifications
114 TOAST.EMPTY_SET Empty set! Title of a pop-up when the user switches to an empty set. “Set” was previously translated as “${DEFINITIONS.SET}”
115 TOAST.ERROR Error Default title for error pop-ups
116 TOAST.FIXING_FLOOR_IN_X_SECS Fixing floor in {SECONDS} second(s)... A countdown pop-up for automatically adjusting floor height. Keep the {SECONDS} part intact as it’s a parameter.
117 TOAST.LAST_EXISTING_SET This is the last existing set. Notification body explaining that the set cannot be removed because this is the last existing set. “Set” was previously translated as “${DEFINITIONS.SET}”
118 TOAST.LETS_ADD_OVERLAYS Let's add some overlays from the taskbar! Instructions prompting the user to add overlays. “Taskbar” was previously translated as “${DEFINITIONS.TASKBAR}”, “Overlay” was previously translated as “${DEFINITIONS.OVERLAY}”
119 TOAST.MAXIMUM_SETS_REACHED Maximum number of sets reached. Notification body explaining that a new set could not be added because we’re already at the limit. “Set” was previously translated as “${DEFINITIONS.SET}”
120 TOAST.NO_KEYMAPS_CONFIGURED No keyboard layouts configured Title of notification
121 TOAST.NO_KEYMAPS_CONFIGURED_HELP Check the wayvr.org on how to set up your keyboard layouts! Body of notification
122 TOAST.NO_SET_SELECTED No set is selected. Notification body explaining that the operation could not be executed because the user has not selected a set. “Set” was previously translated as “${DEFINITIONS.SET}”
123 TOAST.ONE_CONTROLLER_ON_FLOOR Place one controller on the floor! Instructions to the user for automated floor calibration.
124 WATCH.ADD_NEW_SET Add a new set Button to add a new set. “Set” was previously translated as “${DEFINITIONS.SET}”
125 WATCH.CLEANUP_MIRRORS Remove mirrors that are not currently visible Button to remove mirrors. “Mirror” was previously translated as “${DEFINITIONS.MIRROR}”
126 WATCH.DASHBOARD Dashboard Button to toggle “${DEFINITIONS.DASHBOARD}”
127 WATCH.EDIT_MODE Edit Mode Button to toggle “${DEFINITIONS.EDIT_MODE}”
128 WATCH.FIX_FLOOR Fix floor level Tooltip for a button that adjusts the height of the VR environment based on the floor level.
129 WATCH.LONG_PRESS_TO_DELETE_SET Hold to delete Tooltip for a button that deletes a set. “Set” was previously translated as “${DEFINITIONS.SET}”
130 WATCH.RECENTER Recenter playspace Tooltip for a button that recenters the VR environment around the player.
131 WATCH.SWITCH_TO_SET Switch to set Tooltip for a button that switches to a different set. “Set” was previously translated as “${DEFINITIONS.SET}”
132 WATCH.TOGGLE_FOR_CURRENT_SET Toggle for current set Tooltip for a button that toggles the visibility of the current window in the current workspace.
133 WHISPER.TRANSCRIBE Press and hold to transcribe text Tooltip for a button that needs to be held while transcribing text.
134 WHISPER.PASTE Copy transcription to clipboard Tooltip for a button that copies the transcribed text to clipboard.
135 WHISPER.PASTE_AND_GO Copy transcription and send Ctrl-V to focused app Tooltip for a button that copies the transcribed text to clipboard and pastes it to the focused app using an emulated Ctrl-V sequence.
136 WHISPER.SEND_OSC Send transcription to OSC chatbox Tooltip for a button that sends the transcribed text via OSC.
137 WHISPER.UNLOAD_AND_CLOSE Unload model and close Unload AI model from VRAM and close the transcription window
138 WHISPER.MODEL_NOT_DOWNLOADED Speech-to-text not set up! Error message warning the user about an incomplete setup.
139 WHISPER.DOWNLOAD_GUIDANCE Set up speech-to-text under settings, features! Help message prompting the user to finish setup in the ${DEFINITIONS.FEATURES} tab of ${DEFINITIONS.SETTINGS}
140 WHISPER.INITIAL_TEXT Press and hold the mic button to start transcribing... Help message prompting the user to hold down the button with the microphone icon.
141 WHISPER.INIT_ERROR Error while starting Whisper engine Error message.
142 WHISPER.ENTER_KEY Enter key Button to send an Enter key on the emulated keyboard
143 NOTIFICATION.COUD_NOT_CONNECT_TO_VR_RUNTIME Could not connect to VR runtime. A system notification which shows up on initialization failure.
144 NOTIFICATION.NOT_RUNNING_XR_VR Make sure that Monado, WiVRn or SteamVR is running. A system notification which shows up on initialization failure.
145 NOTIFICATION.NOT_RUNNING_VR Make sure that Monado, WiVRn or SteamVR is running. A system notification which shows up on initialization failure.
146 NOTIFICATION.NOT_RUNNING_XR Make sure that Monado or WiVRn is running. A system notification which shows up on initialization failure.
147 NOTIFICATION.INVALID_ARGS Check your launch arguments. A system notification which shows up on initialization failure.
148 NOTIFICATION.SELECT_SCREEN_CAST_FOR Select screen cast for display {DISPLAY} A system notification which shows up on monitor selection request. DISPLAY is the monitor name.
149 NOTIFICATION.CANNOT_CAPTURE_KBD_MOUSE Could not initialize keyboard/mouse capture! Check that your user is in the 'input' group. A system notification which shows up in case if we can't control the computer via keyboard or mouse. Leave `input` key as-is - it's a linux group name.
150 NOTIFICATION.WE_ARE_GRABBING WayVR has your keyboard and mouse! Press Super+Z to release. A system notification which shows up in case if WayVR starts capturing physical keyboard and mouse events. The user consciously chose this option - it's just a message for him how to exit the mode later. Emphasis on user discretion

View File

@ -1,22 +1,38 @@
{ {
"DEFINITIONS": {
"ANCHORED": "Anchored",
"FLOATING": "Floating",
"STATIC": "Static",
"SET": "Set",
"WATCH": "Watch",
"DASHBOARD": "Dashboard",
"EDIT_MODE": "Edit Mode",
"MIRROR": "Mirror",
"SETTINGS": "Settings",
"KEYBOARD": "Keyboard",
"TASKBAR": "Taskbar",
"FEATURES": "Features",
"OVERLAY": "Overlay"
},
"ANCHOR": { "ANCHOR": {
"CENTER": "Center" "CENTER": "Center"
}, },
"BAR": { "BAR": {
"ADD_MIRROR": "Add a new mirror overlay", "ADD_MIRROR": "Add a new mirror overlay",
"ADD_NEW_SET": "Add new set", "ADD_NEW_SET": "Add new set",
"ADD_PASSTHRU": "Add new pass-through cutout",
"CLOSE_APP": "Close app", "CLOSE_APP": "Close app",
"CLOSE_MIRROR": "Close mirror", "CLOSE_OVERLAY": "Close overlay",
"DELETE_CURRENT_SET": "Delete current set", "DELETE_CURRENT_SET": "Delete current set",
"EDIT_MODE_TOGGLE": "Toggle edit mode", "EDIT_MODE_TOGGLE": "Toggle edit mode",
"FORCE_CLOSE_APP": "Force close app", "FORCE_CLOSE_APP": "Force close app",
"HANDSFREE": { "HANDSFREE": {
"EYE_ONLY": "Eye only", "EYE_ONLY": "Eye laser",
"EYE_TRACKING": "Eye + pinch", "EYE_TRACKING": "Eye + pinch",
"HMD": "HMD + pinch", "HMD": "HMD + pinch",
"HMD_ONLY": "HMD only", "HMD_ONLY": "HMD laser",
"NONE": "Off", "NONE": "Off",
"TITLE": "Handsfree mode" "TITLE": "Hands-free mode"
}, },
"RELOAD_FROM_DISK": "Reload XML from disk", "RELOAD_FROM_DISK": "Reload XML from disk",
"RESET_POSITION": "Reset position", "RESET_POSITION": "Reset position",
@ -56,7 +72,7 @@
}, },
"MOVE_PRESS_AND_DRAG": "Move (press & drag)", "MOVE_PRESS_AND_DRAG": "Move (press & drag)",
"OPACITY": "Opacity", "OPACITY": "Opacity",
"POS_ANCHORED": "Anchored: Moves with center marker. Default.", "POS_ANCHORED": "Anchored: Moves together with set. Default.",
"POS_FLOATING": "Floating: Moves independently, recenters when shown.", "POS_FLOATING": "Floating: Moves independently, recenters when shown.",
"POS_HAND_L": "Follow the left hand.", "POS_HAND_L": "Follow the left hand.",
"POS_HAND_R": "Follow the right hand.", "POS_HAND_R": "Follow the right hand.",
@ -78,10 +94,26 @@
"TITLE": "3D Stereo Mode" "TITLE": "3D Stereo Mode"
} }
}, },
"ALTTAB": {
"RELEASE_TO_FOCUS": "Aim at an app and release Super to focus that app.",
"WHILE_AIMING": "While aiming",
"CLICK": "VR pointer click",
"GRABALL": "Move entire set",
"GRAB": "Move individual overlay",
"DASH": "Toggle dashboard",
"EDIT": "Toggle edit mode",
"SET": "Switch set",
"RECENTER": "Show/hide/recenter",
"GENERAL_BINDS": "General bindings",
"TOGGLE_CAPTURE": "Give control back to desktop",
"FOCUS_MODE": "Focus mode (hold Super)",
"CLOSE": "Close focused app",
"MOUSE": "Real mouse clicks & scroll also translate to VR pointer"
},
"GRAB": { "GRAB": {
"ADJUST_DISTANCE": "Adjust distance", "ADJUST_DISTANCE": "Adjust distance",
"ADJUST_SIZE": "Adjust size", "ADJUST_SIZE": "Adjust size",
"GRABBING_ANCHORED": "Anchored overlays all move together. Separate a single window by grabbing it with the other hand while still grabbing the anchor.", "GRABBING_ANCHORED": "Anchored overlays move with the set. Separate a single window by grabbing it with the other hand while still grabbing the set.",
"GRABBING_ANCHORED_EDIT": "This overlay will stay anchored to the center marker.", "GRABBING_ANCHORED_EDIT": "This overlay will stay anchored to the center marker.",
"GRABBING_FLOATING": "This overlay is Floating and will stay in place, unless recentered.", "GRABBING_FLOATING": "This overlay is Floating and will stay in place, unless recentered.",
"GRABBING_FOLLOW": "This overlay will follow the device it is attached to.", "GRABBING_FOLLOW": "This overlay will follow the device it is attached to.",
@ -92,7 +124,7 @@
"SCREENCAST": { "SCREENCAST": {
"PENDING": "Please wait...", "PENDING": "Please wait...",
"QUEUED": "Waiting for a different overlay's screen cast pop-up to be approved.", "QUEUED": "Waiting for a different overlay's screen cast pop-up to be approved.",
"WAITING_FOR_USER_DESC": "Check your dekstop for a screen cast pop-up.\nSelect the following:", "WAITING_FOR_USER_DESC": "Check your desktop for a screen cast pop-up.\nSelect the following:",
"WAITING_FOR_USER": "Check your desktop for a screen cast pop-up.", "WAITING_FOR_USER": "Check your desktop for a screen cast pop-up.",
"FAIL": "Could not initialize screen cast source." "FAIL": "Could not initialize screen cast source."
}, },
@ -107,6 +139,8 @@
"LAST_EXISTING_SET": "This is the last existing set.", "LAST_EXISTING_SET": "This is the last existing set.",
"LETS_ADD_OVERLAYS": "Let's add some overlays from the taskbar!", "LETS_ADD_OVERLAYS": "Let's add some overlays from the taskbar!",
"MAXIMUM_SETS_REACHED": "Maximum number of sets reached.", "MAXIMUM_SETS_REACHED": "Maximum number of sets reached.",
"NO_KEYMAPS_CONFIGURED": "No keyboard layouts configured",
"NO_KEYMAPS_CONFIGURED_HELP": "Check the wayvr.org on how to set up your keyboard layouts!",
"NO_SET_SELECTED": "No set is selected.", "NO_SET_SELECTED": "No set is selected.",
"ONE_CONTROLLER_ON_FLOOR": "Place one controller on the floor!" "ONE_CONTROLLER_ON_FLOOR": "Place one controller on the floor!"
}, },
@ -115,7 +149,6 @@
"CLEANUP_MIRRORS": "Remove mirrors that are\nnot currently visible", "CLEANUP_MIRRORS": "Remove mirrors that are\nnot currently visible",
"DASHBOARD": "Dashboard", "DASHBOARD": "Dashboard",
"EDIT_MODE": "Edit Mode", "EDIT_MODE": "Edit Mode",
"EDIT_MODE_EXPLANATION": "Overlays can now be moved and tuned individually.\nControl which overlays are visible on this set:",
"FIX_FLOOR": "Fix floor level", "FIX_FLOOR": "Fix floor level",
"LONG_PRESS_TO_DELETE_SET": "Hold to delete", "LONG_PRESS_TO_DELETE_SET": "Hold to delete",
"RECENTER": "Recenter playspace", "RECENTER": "Recenter playspace",
@ -133,5 +166,15 @@
"INITIAL_TEXT": "Press and hold the mic button to start transcribing...", "INITIAL_TEXT": "Press and hold the mic button to start transcribing...",
"INIT_ERROR": "Error while starting Whisper engine", "INIT_ERROR": "Error while starting Whisper engine",
"ENTER_KEY": "Enter key" "ENTER_KEY": "Enter key"
},
"NOTIFICATION": {
"COUD_NOT_CONNECT_TO_VR_RUNTIME": "Could not connect to VR runtime.",
"NOT_RUNNING_XR_VR": "Make sure that Monado, WiVRn or SteamVR is running.",
"NOT_RUNNING_VR": "Make sure that Monado, WiVRn or SteamVR is running.",
"NOT_RUNNING_XR": "Make sure that Monado or WiVRn is running.",
"INVALID_ARGS": "Check your launch arguments.",
"SELECT_SCREEN_CAST_FOR": "Select screen cast for display {DISPLAY}",
"CANNOT_CAPTURE_KBD_MOUSE": "Could not initialize keyboard/mouse capture!\nCheck that your user is in the 'input' group.",
"WE_ARE_GRABBING": "WayVR has your keyboard and mouse!\nPress Super+Z to release."
} }
} }

View File

@ -1,62 +1,5 @@
{ {
"ANCHOR": {
"CENTER": "Centro"
},
"BAR": {
"ADD_MIRROR": "Agregar una nueva superposición de espejo",
"EDIT_MODE_TOGGLE": "Activar/desactivar el modo de edición",
"ADD_NEW_SET": "Añadir nuevo set",
"DELETE_CURRENT_SET": "Eliminar set actual",
"TOGGLE_VISIBILITY": "Alternar visibilidad",
"RESET_POSITION": "Restablecer posición",
"RELOAD_FROM_DISK": "Volver a cargar XML desde el disco",
"CLOSE_MIRROR": "Cerrar espejo",
"CLOSE_APP": "Cerrar aplicación",
"FORCE_CLOSE_APP": "Forzar cierre de la aplicación",
"HANDSFREE": {
"TITLE": "Modo manos libres",
"NONE": "Desactivado",
"HMD": "HMD + pellizco",
"EYE_TRACKING": "Ojo + pellizco",
"HMD_ONLY": "Solo HMD",
"EYE_ONLY": "Solo ojos"
}
},
"WATCH": {
"RECENTER": "Recentrar el área de juego",
"FIX_FLOOR": "Ajustar la altura del piso",
"EDIT_MODE_EXPLANATION": "Ahora las superposiciones se pueden mover y ajustar individualmente.\nAlternar superposiciones para el conjunto actual:",
"DASHBOARD": "Panel de control",
"EDIT_MODE": "Modo de edición",
"ADD_NEW_SET": "Añadir un nuevo conjunto",
"SWITCH_TO_SET": "Cambiar al conjunto",
"TOGGLE_FOR_CURRENT_SET": "Alternar visibilidad en el conjunto actual",
"LONG_PRESS_TO_DELETE_SET": "Mantén presionado para eliminar el conjunto",
"CLEANUP_MIRRORS": "Eliminar los espejos que\nno son actualmente visibles"
},
"EDIT_MODE": { "EDIT_MODE": {
"ADJUST_CURVATURE": "Ajustar curvatura",
"ALPHA_BLEND_MODE": "Modo de mezcla alfa",
"BLENDING_ADDITIVE": "Aditivo",
"CURVATURE": "Curvatura",
"DELETE": "Eliminar",
"HINT_POINT_WINDOW": "Pulsa sobre una ventana para cambiar sus parámetros.\nUna vez terminado, sal del modo de edición usando el botón de la derecha.",
"LEAVE": "Salir del modo edición",
"LOCK_INTERACTION": "Bloquear interacción",
"DISABLE_GRAB": "Desactivar agarre",
"MOVE_PRESS_AND_DRAG": "Mover (presionar y arrastrar)",
"OPACITY": "Opacidad",
"POSITIONING": "Posicionamiento",
"RESIZE_PRESS_AND_DRAG": "Redimensionar (presionar y arrastrar)",
"POS_STATIC": "Estático: Permanece en su lugar y nunca se recentra.",
"POS_ANCHORED": "Anclado: Se mueve junto con el resto del conjunto. Predeterminado.",
"POS_FLOATING": "Flotante: Permanece en su lugar, se recentra cuando se muestra.",
"POS_HMD": "Seguir el HMD.",
"POS_HAND_L": "Seguir la mano izquierda.",
"POS_HAND_R": "Seguir la mano derecha.",
"INTERPOLATION": "Interpolación",
"KEYBOARD": "Teclado",
"STEREO_3D_MODE_A": {},
"STEREO_3D_MODE": { "STEREO_3D_MODE": {
"TITLE": "Modo Estéreo 3D", "TITLE": "Modo Estéreo 3D",
"SPLIT_LEFT_RIGHT": "IZQ→DER", "SPLIT_LEFT_RIGHT": "IZQ→DER",
@ -69,8 +12,6 @@
"FULL_FRAME_BAT": "Full-BAT", "FULL_FRAME_BAT": "Full-BAT",
"ADJUST_MOUSE": "Ajustar ratón" "ADJUST_MOUSE": "Ajustar ratón"
}, },
"STEREO_3D_MODE_": {},
"ALIGN_TO_HMD": "Alinear al HMD",
"MOUSE": { "MOUSE": {
"TITLE": "Correcciones del ratón", "TITLE": "Correcciones del ratón",
"WRONG_SCREEN_SELECTION_HELP": "Si el cursor se mueve en una pantalla completamente diferente,\nes probable que las pantallas se hayan seleccionado incorrectamente. Consulta el archivo readme.", "WRONG_SCREEN_SELECTION_HELP": "Si el cursor se mueve en una pantalla completamente diferente,\nes probable que las pantallas se hayan seleccionado incorrectamente. Consulta el archivo readme.",
@ -83,57 +24,157 @@
"ROTATE180": "Rotado 180°", "ROTATE180": "Rotado 180°",
"ROTATE270": "Rotado 270°" "ROTATE270": "Rotado 270°"
}, },
"GLOBAL": "Siempre visible", "ADJUST_CURVATURE": "Ajustar curvatura",
"ANGLE_FADE": "Atenuación angular", "ALIGN_TO_HMD": "Alinear con el HMD",
"ANGLE_FADE_HELP": "Desvanecer cuando no se mira el HMD", "ALPHA_BLEND_MODE": "Modo de mezcla alfa",
"ANGLE_FADE": "Desvanecimiento por ángulo",
"ANGLE_FADE_HELP": "Desvanecer al no mirar el HMD",
"BLENDING_ADDITIVE": "Mezcla aditiva",
"BLOCK_INPUT": "Bloquear entrada del juego", "BLOCK_INPUT": "Bloquear entrada del juego",
"RESIZE_CORNER": "Arrastra para cambiar el tamaño" "CURVATURE": "Curvatura",
"DELETE": "Mantén presionado para eliminar del set actual",
"DISABLE_GRAB": "Desactivar agarre",
"GLOBAL": "Siempre visible",
"HINT_POINT_WINDOW": "Apunta a una ventana para cambiar sus parámetros.\nCuando termines, sal del modo edición usando el botón de la derecha.",
"INTERPOLATION": "Interpolación",
"KEYBOARD": "Teclado",
"LEAVE": "Salir del modo edición",
"LOCK_INTERACTION": "Bloquear interacción",
"MOVE_PRESS_AND_DRAG": "Mover (presiona y arrastra)",
"OPACITY": "Opacidad",
"POS_ANCHORED": "Anclado: Se mueve junto con el set. Por defecto.",
"POS_FLOATING": "Flotante: Se mueve independientemente, se recentra al mostrarse.",
"POS_HAND_L": "Sigue la mano izquierda.",
"POS_HAND_R": "Sigue la mano derecha.",
"POS_HMD": "Sigue el HMD.",
"POS_STATIC": "Estático: No pertenece a ningún set, sin recentrar.",
"POSITIONING": "Posicionamiento",
"RESIZE_PRESS_AND_DRAG": "Redimensionar (presiona y arrastra)",
"RESIZE_CORNER": "Arrastrar para redimensionar"
},
"DEFINITIONS": {
"ANCHORED": "Anclado",
"FLOATING": "Flotante",
"STATIC": "Estático",
"SET": "Set",
"WATCH": "Reloj",
"DASHBOARD": "Panel de control",
"EDIT_MODE": "Modo edición",
"MIRROR": "Espejo",
"SETTINGS": "Ajustes",
"KEYBOARD": "Teclado",
"TASKBAR": "Barra de tareas",
"FEATURES": "Funciones",
"OVERLAY": "Overlay"
},
"ANCHOR": {
"CENTER": "Centro"
},
"BAR": {
"ADD_MIRROR": "Añadir nuevo overlay de espejo",
"ADD_NEW_SET": "Añadir nuevo set",
"CLOSE_APP": "Cerrar aplicación",
"CLOSE_OVERLAY": "Cerrar superposición",
"DELETE_CURRENT_SET": "Eliminar set actual",
"EDIT_MODE_TOGGLE": "Alternar modo edición",
"FORCE_CLOSE_APP": "Forzar cierre de aplicación",
"HANDSFREE": {
"EYE_ONLY": "Láser ocular",
"EYE_TRACKING": "Vista + pinza",
"HMD": "HMD + pellizco",
"HMD_ONLY": "Láser del HMD",
"NONE": "Desactivado",
"TITLE": "Modo manos libres"
},
"RELOAD_FROM_DISK": "Recargar XML desde el disco",
"RESET_POSITION": "Reiniciar posición",
"TOGGLE_VISIBILITY": "Alternar visibilidad",
"ADD_PASSTHRU": "Añadir nueva ventana de passthrough"
}, },
"DISABLED": "Deshabilitado",
"DEFAULT": "Por defecto", "DEFAULT": "Por defecto",
"DISABLED": "Desactivado",
"DONE": "Listo",
"ALTTAB": {
"RELEASE_TO_FOCUS": "Apunta a una app y suelta Super para seleccionarla.",
"WHILE_AIMING": "Mientras apuntas",
"CLICK": "Clic del puntero VR",
"GRABALL": "Mover set completo",
"GRAB": "Mover {$DEFINITIONS.OVERLAY} individual",
"DASH": "Alternar panel de control",
"EDIT": "Alternar modo edición",
"SET": "Cambiar set",
"RECENTER": "Mostrar/ocultar/recentrar",
"GENERAL_BINDS": "Asignaciones generales",
"TOGGLE_CAPTURE": "Devolver el control al escritorio",
"FOCUS_MODE": "Modo enfoque (mantén Super)",
"CLOSE": "Cerrar app enfocada",
"MOUSE": "Los clics y el scroll del ratón real también actúan como el puntero de VR"
},
"GRAB": { "GRAB": {
"ADJUST_DISTANCE": "Ajustar distancia", "ADJUST_DISTANCE": "Ajustar distancia",
"ADJUST_SIZE": "Ajustar tamaño", "ADJUST_SIZE": "Ajustar tamaño",
"UNRESTRICTED_MOVEMENT": "Movimiento sin restricciones", "GRABBING_ANCHORED": "Los overlays anclados se mueven con el set. Separa una sola ventana agarrándola con la otra mano mientras sigues sujetando el set.",
"GRABBING_WATCH": "Para intercambiar las manos, mueve el reloj al frente y agrárralo con la otra mano.", "GRABBING_ANCHORED_EDIT": "Este overlay permanecerá anclado al marcador del centro.",
"GRABBING_STATIC": "Esta superposición es estática y permanecerá en su lugar, ignorando el recentrado.", "GRABBING_FLOATING": "Este overlay es flotante y permanecerá en su lugar, a menos que se recentre.",
"GRABBING_ANCHORED": "Las superposiciones ancladas se mueven todas juntas. Separa una ventana individual agarrándola con la otra mano mientras aún sujetas el ancla.", "GRABBING_FOLLOW": "Este overlay seguirá el dispositivo al que esté unido.",
"GRABBING_ANCHORED_EDIT": "Esta superposición permanecerá anclada al marcador central.", "GRABBING_STATIC": "Este overlay es estático y se mantendrá en su lugar, ignorando el recentrado.",
"GRABBING_FLOATING": "Esta superposición es flotante y permanecerá en su lugar a menos que se recentre.", "GRABBING_WATCH": "Para cambiar de mano, coloca el reloj al frente y agárralo con la otra mano.",
"GRABBING_FOLLOW": "Esta superposición seguirá el dispositivo al que está adjunta." "UNRESTRICTED_MOVEMENT": "Movimiento sin restricciones"
},
"SCREENCAST": {
"PENDING": "Por favor, espera...",
"QUEUED": "Esperando la aprobación de la ventana emergente de transmisión de pantalla de otro overlay.",
"WAITING_FOR_USER_DESC": "Revisa tu escritorio para ver la ventana emergente de transmisión de pantalla.\nSelecciona lo siguiente:",
"WAITING_FOR_USER": "Revisa tu escritorio para ver la ventana emergente de transmisión de pantalla.",
"FAIL": "No se pudo inicializar la fuente de la transmisión de pantalla."
}, },
"TOAST": { "TOAST": {
"DEFAULT_TITLE": "Notificación",
"ERROR": "Error",
"CANNOT_REMOVE_SET": "¡No se puede eliminar el conjunto!",
"NO_SET_SELECTED": "No se ha seleccionado ningún conjunto.",
"LAST_EXISTING_SET": "Este es el último conjunto existente.",
"EMPTY_SET": "¡Conjunto vacío!",
"ONE_CONTROLLER_ON_FLOOR": "¡Coloca un mando en el suelo!",
"CANNOT_ADD_SET": "¡No se puede agregar el conjunto!",
"MAXIMUM_SETS_REACHED": "Se ha alcanzado el número máximo de sets.",
"FIXING_FLOOR_IN_X_SECS": "Corrigiendo el suelo en {SECONDS} segundo(s)...",
"TITLE_SCREENCAST_FAIL": "¡No se pudo iniciar la fuente de transmisión de pantalla!", "TITLE_SCREENCAST_FAIL": "¡No se pudo iniciar la fuente de transmisión de pantalla!",
"LETS_ADD_OVERLAYS": "¡Añadamos algunas superposiciones desde la barra de tareas!" "CANNOT_ADD_SET": "¡No se pudo añadir el set!",
"CANNOT_REMOVE_SET": "¡No se puede eliminar el set!",
"DEFAULT_TITLE": "Notificación",
"EMPTY_SET": "¡Set vacío!",
"ERROR": "Error",
"FIXING_FLOOR_IN_X_SECS": "Ajustando suelo en {SECONDS} segundo(s)...",
"LAST_EXISTING_SET": "Este es el último set existente.",
"LETS_ADD_OVERLAYS": "¡Añade algunos overlays desde la barra de tareas!",
"MAXIMUM_SETS_REACHED": "Número máximo de sets alcanzado.",
"NO_SET_SELECTED": "No hay ningún set seleccionado.",
"ONE_CONTROLLER_ON_FLOOR": "¡Coloca un controlador en el suelo!",
"NO_KEYMAPS_CONFIGURED": "Sin distribuciones de teclado configuradas",
"NO_KEYMAPS_CONFIGURED_HELP": "¡Consulta wayvr.org para configurar tus diseños de teclado!"
},
"WATCH": {
"ADD_NEW_SET": "Añadir un set nuevo",
"CLEANUP_MIRRORS": "Eliminar espejos que\nno sean visibles",
"DASHBOARD": "Panel de control",
"EDIT_MODE": "Modo edición",
"FIX_FLOOR": "Ajustar nivel del suelo",
"LONG_PRESS_TO_DELETE_SET": "Mantén presionado para borrar",
"RECENTER": "Recentrar espacio de juego",
"SWITCH_TO_SET": "Cambiar a set",
"TOGGLE_FOR_CURRENT_SET": "Alternar set actual"
}, },
"DONE": "Hecho",
"WHISPER": { "WHISPER": {
"TRANSCRIBE": "Mantén presionado para transcribir texto", "TRANSCRIBE": "Mantén presionado para transcribir texto",
"PASTE": "Copiar transcripción al portapapeles", "PASTE": "Copiar transcripción al portapapeles",
"PASTE_AND_GO": "Copiar transcripción y enviar Ctrl-V a la aplicación enfocada", "PASTE_AND_GO": "Copiar transcripción y enviar Ctrl-V a la aplicación enfocada",
"SEND_OSC": "Enviar transcripción al chatbox de OSC", "SEND_OSC": "Enviar transcripción al chat OSC",
"UNLOAD_AND_CLOSE": "Descargar modelo y cerrar", "UNLOAD_AND_CLOSE": "Descargar modelo y cerrar",
"MODEL_NOT_DOWNLOADED": "¡El dictado por voz no está configurado!", "MODEL_NOT_DOWNLOADED": "¡El dictado por voz no está configurado!",
"DOWNLOAD_GUIDANCE": "¡Configura la conversión de voz a texto en ajustes, características!", "DOWNLOAD_GUIDANCE": "¡Configura el dictado en Ajustes > Funciones!",
"INITIAL_TEXT": "Mantén presionado el botón del micrófono para comenzar a transcribir...", "INITIAL_TEXT": "Mantén pulsado el botón del micro para empezar a transcribir...",
"INIT_ERROR": "Error al iniciar el motor de Whisper", "INIT_ERROR": "Error al iniciar el motor Whisper",
"ENTER_KEY": "Tecla Enter" "ENTER_KEY": "Tecla Enter"
}, },
"SCREENCAST": { "NOTIFICATION": {
"PENDING": "Por favor, espere...", "NOT_RUNNING_XR_VR": "Asegúrate de que Monado, WiVRn o SteamVR estén ejecutándose.",
"QUEUED": "Esperando a que se apruebe la ventana emergente de la transmisión de pantalla de otra superposición.", "NOT_RUNNING_VR": "Asegúrate de que Monado, WiVRn o SteamVR estén ejecutándose.",
"WAITING_FOR_USER_DESC": "Busca la ventana emergente de transmisión de pantalla en tu escritorio.\nSelecciona lo siguiente:", "NOT_RUNNING_XR": "Asegúrate de que Monado o WiVRn se estén ejecutando.",
"WAITING_FOR_USER": "Revisa tu escritorio para ver la ventana emergente de transmisión de pantalla.", "INVALID_ARGS": "Revisa tus argumentos de lanzamiento.",
"FAIL": "No se pudo inicializar la fuente de transmisión de pantalla." "COUD_NOT_CONNECT_TO_VR_RUNTIME": "No se pudo conectar al entorno de ejecución de VR.",
"SELECT_SCREEN_CAST_FOR": "Seleccionar transmisión de pantalla para la pantalla {DISPLAY}",
"CANNOT_CAPTURE_KBD_MOUSE": "¡No se pudo inicializar la captura de teclado/ratón!\nComprueba que tu usuario esté en el grupo 'input'.",
"WE_ARE_GRABBING": "¡WayVR tiene el control de tu teclado y ratón!\nPulsa Super+Z para liberarlos."
} }
} }

View File

@ -1,52 +1,5 @@
{ {
"ANCHOR": {
"CENTER": "Centro"
},
"BAR": {
"ADD_MIRROR": "Aggiungi un nuovo overlay specchio",
"EDIT_MODE_TOGGLE": "Attiva/disattiva modalità modifica",
"ADD_NEW_SET": "Aggiungi nuovo set",
"DELETE_CURRENT_SET": "Elimina set attuale",
"TOGGLE_VISIBILITY": "Alterna visibilità",
"RESET_POSITION": "Ripristina posizione",
"RELOAD_FROM_DISK": "Ricarica XML dal disco",
"CLOSE_MIRROR": "Chiudi mirror",
"CLOSE_APP": "Chiudi app",
"FORCE_CLOSE_APP": "Chiudi forzatamente l'app",
"HANDSFREE": {
"TITLE": "Modalità a mani libere",
"NONE": "Disattivato",
"HMD": "HMD + pizzico",
"EYE_TRACKING": "Occhio + pizzico",
"HMD_ONLY": "Solo HMD",
"EYE_ONLY": "Solo occhi"
}
},
"DEFAULT": "Predefinito",
"DISABLED": "Disabilitato",
"EDIT_MODE": { "EDIT_MODE": {
"ADJUST_CURVATURE": "Regola curvatura",
"ALPHA_BLEND_MODE": "Modalità di fusione Alpha",
"BLENDING_ADDITIVE": "Blending additivo",
"CURVATURE": "Curvatura",
"DELETE": "Tenere premuto per rimuovere dal set corrente",
"DISABLE_GRAB": "Disabilita l'afferra",
"HINT_POINT_WINDOW": "Punta a una finestra per modificarne i parametri.\nUna volta fatto, esci dalla modalità di modifica usando il pulsante a destra.",
"INTERPOLATION": "Interpolazione",
"ALIGN_TO_HMD": "Allinea all'HMD",
"KEYBOARD": "Tastiera",
"LEAVE": "Esci dalla modalità di modifica",
"LOCK_INTERACTION": "Blocca interazione",
"MOVE_PRESS_AND_DRAG": "Muovi (premi e trascina)",
"OPACITY": "Opacità",
"POS_ANCHORED": "Ancorato: si muove con il marker centrale. Predefinito.",
"POS_FLOATING": "Galleggiante: si muove indipendentemente, si recentra quando viene visualizzato.",
"POS_HAND_L": "Segui la mano sinistra.",
"POS_HAND_R": "Segui la mano destra.",
"POS_HMD": "Segui l'HMD.",
"POS_STATIC": "Statico: non fa parte di alcun set, senza recentratura.",
"POSITIONING": "Posizionamento",
"RESIZE_PRESS_AND_DRAG": "Ridimensiona (premi e trascina)",
"STEREO_3D_MODE": { "STEREO_3D_MODE": {
"SPLIT_BOTTOM_TOP": "DAL BASSO→IN ALTO", "SPLIT_BOTTOM_TOP": "DAL BASSO→IN ALTO",
"SPLIT_LEFT_RIGHT": "SINISTRA→DESTRA", "SPLIT_LEFT_RIGHT": "SINISTRA→DESTRA",
@ -71,67 +24,157 @@
"FLIP180": "Ruotato di 180°", "FLIP180": "Ruotato di 180°",
"FLIP270": "Ruotato di 270°" "FLIP270": "Ruotato di 270°"
}, },
"GLOBAL": "Sempre visibile", "ADJUST_CURVATURE": "Regola curvatura",
"ALIGN_TO_HMD": "Allinea al visore",
"ALPHA_BLEND_MODE": "Modalità Alpha blend",
"ANGLE_FADE": "Dissolvenza angolare", "ANGLE_FADE": "Dissolvenza angolare",
"ANGLE_FADE_HELP": "Sfumatura quando non si guarda l'HMD", "ANGLE_FADE_HELP": "Dissolvenza quando non guardi il visore",
"BLOCK_INPUT": "Blocca l'input del gioco", "BLENDING_ADDITIVE": "Blending additivo",
"BLOCK_INPUT": "Blocca input gioco",
"CURVATURE": "Curvatura",
"DELETE": "Tieni premuto per rimuovere dal set attuale",
"DISABLE_GRAB": "Disattiva presa",
"GLOBAL": "Sempre visibile",
"HINT_POINT_WINDOW": "Punta una finestra per cambiarne i parametri.\nAl termine, esci dalla modalità modifica usando il pulsante a destra.",
"INTERPOLATION": "Interpolazione",
"KEYBOARD": "Tastiera",
"LEAVE": "Esci dalla modalità modifica",
"LOCK_INTERACTION": "Blocca interazione",
"MOVE_PRESS_AND_DRAG": "Sposta (premi e trascina)",
"OPACITY": "Opacità",
"POS_ANCHORED": "Ancorato: Si muove insieme al set. Predefinito.",
"POS_FLOATING": "Fluttuante: si muove indipendentemente, si ricentra quando appare.",
"POS_HAND_L": "Segui la mano sinistra.",
"POS_HAND_R": "Segui la mano destra.",
"POS_HMD": "Segue l'HMD.",
"POS_STATIC": "Statico: non fa parte di alcun set, nessun ricentramento.",
"POSITIONING": "Posizionamento",
"RESIZE_PRESS_AND_DRAG": "Ridimensiona (premi e trascina)",
"RESIZE_CORNER": "Trascina per ridimensionare" "RESIZE_CORNER": "Trascina per ridimensionare"
}, },
"DEFINITIONS": {
"ANCHORED": "Ancorato",
"FLOATING": "Fluttuante",
"STATIC": "Statico",
"SET": "Set",
"WATCH": "Orologio",
"DASHBOARD": "Dashboard",
"EDIT_MODE": "Modalità modifica",
"MIRROR": "Specchio",
"SETTINGS": "Impostazioni",
"KEYBOARD": "Tastiera",
"TASKBAR": "Barra delle applicazioni",
"FEATURES": "Funzionalità",
"OVERLAY": "Overlay"
},
"ANCHOR": {
"CENTER": "Centro"
},
"BAR": {
"ADD_MIRROR": "Aggiungi un nuovo overlay specchio",
"ADD_NEW_SET": "Aggiungi nuovo set",
"CLOSE_APP": "Chiudi app",
"CLOSE_OVERLAY": "Chiudi overlay",
"DELETE_CURRENT_SET": "Elimina set corrente",
"EDIT_MODE_TOGGLE": "Attiva/disattiva modalità modifica",
"FORCE_CLOSE_APP": "Forza chiusura app",
"HANDSFREE": {
"EYE_ONLY": "Laser oculare",
"EYE_TRACKING": "Sguardo + pinch",
"HMD": "HMD + pinch",
"HMD_ONLY": "Laser HMD",
"NONE": "Disattivo",
"TITLE": "Modalità mani libere"
},
"RELOAD_FROM_DISK": "Ricarica XML da disco",
"RESET_POSITION": "Ripristina posizione",
"TOGGLE_VISIBILITY": "Attiva/disattiva visibilità",
"ADD_PASSTHRU": "Aggiungi ritaglio passthrough"
},
"DEFAULT": "Predefinito",
"DISABLED": "Disabilitato",
"DONE": "Completato",
"ALTTAB": {
"RELEASE_TO_FOCUS": "Mira a un'app e rilascia Super per metterla a fuoco.",
"WHILE_AIMING": "Mentre punti",
"CLICK": "Clic puntatore VR",
"GRABALL": "Sposta l'intero set",
"GRAB": "Sposta singolo overlay",
"DASH": "Attiva/disattiva dashboard",
"EDIT": "Attiva/disattiva modalità modifica",
"SET": "Cambia set",
"RECENTER": "Mostra/nascondi/ricentra",
"GENERAL_BINDS": "Tasti generali",
"TOGGLE_CAPTURE": "Rendi il controllo al desktop",
"FOCUS_MODE": "Modalità focus (tieni premuto Super)",
"CLOSE": "Chiudi app selezionata",
"MOUSE": "I clic e lo scorrimento del mouse reale influenzano anche il puntatore VR"
},
"GRAB": { "GRAB": {
"ADJUST_DISTANCE": "Regola la distanza", "ADJUST_DISTANCE": "Regola distanza",
"ADJUST_SIZE": "Regola dimensione", "ADJUST_SIZE": "Regola dimensione",
"UNRESTRICTED_MOVEMENT": "Movimento libero", "GRABBING_ANCHORED": "Gli overlay ancorati si muovono con il set. Separa una singola finestra afferrandola con l'altra mano mentre tieni ancora il set.",
"GRABBING_WATCH": "Per cambiare mano, sposta il watch davanti a te e afferralo con l'altra mano.", "GRABBING_ANCHORED_EDIT": "Questo overlay rimarrà ancorato al centro.",
"GRABBING_STATIC": "Questo overlay è Statico e rimarrà in posizione, ignorando il recenter.", "GRABBING_FLOATING": "Questo overlay è fluttuante e rimarrà in posizione, a meno che non venga ricentrato.",
"GRABBING_ANCHORED": "Gli overlay ancorati si muovono tutti insieme. Separa una singola finestra afferrandola con l'altra mano mentre tieni ancora l'ancora.", "GRABBING_FOLLOW": "Questo overlay seguirà il dispositivo a cui è collegato.",
"GRABBING_ANCHORED_EDIT": "Questo overlay rimarrà ancorato al marcatore centrale.", "GRABBING_STATIC": "Questo overlay è statico e rimarrà in posizione, ignorando il ricentramento.",
"GRABBING_FLOATING": "Questo overlay è mobile e rimarrà in posizione, a meno che non venga recentrato.", "GRABBING_WATCH": "Per cambiare mano, sposta l'orologio davanti a te e afferralo con l'altra mano.",
"GRABBING_FOLLOW": "Questo overlay seguirà il dispositivo a cui è collegato." "UNRESTRICTED_MOVEMENT": "Movimento libero"
},
"SCREENCAST": {
"PENDING": "Attendere...",
"QUEUED": "In attesa dell'approvazione del pop-up di screen cast di un altro overlay.",
"WAITING_FOR_USER_DESC": "Controlla sul desktop se è apparso il pop-up per il mirroring dello schermo.\nSeleziona quanto segue:",
"WAITING_FOR_USER": "Controlla il desktop per il pop-up di mirroring dello schermo.",
"FAIL": "Impossibile inizializzare la sorgente del mirroring."
}, },
"TOAST": { "TOAST": {
"DEFAULT_TITLE": "Notifica", "TITLE_SCREENCAST_FAIL": "Impossibile avviare la sorgente di mirroring!",
"ERROR": "Errore",
"CANNOT_ADD_SET": "Impossibile aggiungere il set!", "CANNOT_ADD_SET": "Impossibile aggiungere il set!",
"MAXIMUM_SETS_REACHED": "Numero massimo di set raggiunto.",
"CANNOT_REMOVE_SET": "Impossibile rimuovere il set!", "CANNOT_REMOVE_SET": "Impossibile rimuovere il set!",
"NO_SET_SELECTED": "Nessun set è selezionato.", "DEFAULT_TITLE": "Notifica",
"LAST_EXISTING_SET": "Questo è l'ultimo set esistente.",
"EMPTY_SET": "Set vuoto!", "EMPTY_SET": "Set vuoto!",
"ONE_CONTROLLER_ON_FLOOR": "Posiziona un controller a terra!", "ERROR": "Errore",
"FIXING_FLOOR_IN_X_SECS": "Correzione del pavimento in {SECONDS} secondo/i...", "FIXING_FLOOR_IN_X_SECS": "Regolazione pavimento tra {SECONDS} secondi...",
"TITLE_SCREENCAST_FAIL": "Impossibile avviare la sorgente dello screen cast!", "LAST_EXISTING_SET": "Questo è l'ultimo set esistente.",
"LETS_ADD_OVERLAYS": "Aggiungiamo alcuni overlay dalla barra delle applicazioni!" "LETS_ADD_OVERLAYS": "Aggiungi alcuni overlay dalla barra delle applicazioni!",
"MAXIMUM_SETS_REACHED": "Raggiunto il numero massimo di set.",
"NO_SET_SELECTED": "Nessun set selezionato.",
"ONE_CONTROLLER_ON_FLOOR": "Appoggia un controller sul pavimento!",
"NO_KEYMAPS_CONFIGURED": "Nessuna disposizione tastiera configurata",
"NO_KEYMAPS_CONFIGURED_HELP": "Consulta wayvr.org per configurare i layout della tastiera!"
}, },
"WATCH": { "WATCH": {
"ADD_NEW_SET": "Aggiungi un nuovo set", "ADD_NEW_SET": "Aggiungi un nuovo set",
"CLEANUP_MIRRORS": "Rimuovi gli specchi che\nnon sono attualmente visibili", "CLEANUP_MIRRORS": "Rimuovi gli specchi \nnon attualmente visibili",
"DASHBOARD": "Pannello di controllo", "DASHBOARD": "Dashboard",
"EDIT_MODE": "Modalità modifica", "EDIT_MODE": "Modalità modifica",
"EDIT_MODE_EXPLANATION": "Gli overlay possono ora essere spostati e regolati individualmente.\nControlla quali overlay sono visibili in questo set:", "FIX_FLOOR": "Fissa livello pavimento",
"FIX_FLOOR": "Fissa il livello del pavimento", "LONG_PRESS_TO_DELETE_SET": "Tieni premuto per eliminare",
"LONG_PRESS_TO_DELETE_SET": "Tenere premuto per eliminare", "RECENTER": "Ricentra playspace",
"RECENTER": "Recentra l'area di gioco", "SWITCH_TO_SET": "Passa al set",
"SWITCH_TO_SET": "Passa a set", "TOGGLE_FOR_CURRENT_SET": "Attiva/disattiva set corrente"
"TOGGLE_FOR_CURRENT_SET": "Attiva/disattiva per il set corrente"
}, },
"DONE": "Fatto",
"WHISPER": { "WHISPER": {
"TRANSCRIBE": "Tieni premuto per trascrivere il testo", "TRANSCRIBE": "Tieni premuto per trascrivere il testo",
"PASTE": "Copia trascrizione negli appunti", "PASTE": "Copia trascrizione negli appunti",
"PASTE_AND_GO": "Copia trascrizione e invia Ctrl-V all'app a fuoco", "PASTE_AND_GO": "Copia trascrizione e invia Ctrl-V all'app focalizzata",
"SEND_OSC": "Invia trascrizione alla chatbox OSC", "SEND_OSC": "Invia trascrizione a chatbox OSC",
"UNLOAD_AND_CLOSE": "Scarica modello e chiudi", "UNLOAD_AND_CLOSE": "Scarica modello e chiudi",
"MODEL_NOT_DOWNLOADED": "Speech-to-text non configurato!", "MODEL_NOT_DOWNLOADED": "Riconoscimento vocale non configurato!",
"DOWNLOAD_GUIDANCE": "Configura il riconoscimento vocale in impostazioni, funzionalità!", "DOWNLOAD_GUIDANCE": "Configura il riconoscimento vocale in Impostazioni > Funzionalità!",
"INITIAL_TEXT": "Tieni premuto il tasto del microfono per iniziare la trascrizione...", "INITIAL_TEXT": "Tieni premuto il tasto del microfono per trascrivere...",
"INIT_ERROR": "Errore durante l'avvio del motore Whisper", "INIT_ERROR": "Errore durante l'avvio del motore Whisper",
"ENTER_KEY": "Tasto Invio" "ENTER_KEY": "Tasto Invio"
}, },
"SCREENCAST": { "NOTIFICATION": {
"PENDING": "Attendi prego...", "NOT_RUNNING_XR_VR": "Assicurati che Monado, WiVRn o SteamVR siano attivi.",
"QUEUED": "In attesa dell'approvazione del pop-up di screen cast di un altro overlay.", "NOT_RUNNING_VR": "Assicurati che Monado, WiVRn o SteamVR siano attivi.",
"WAITING_FOR_USER_DESC": "Controlla il desktop per un pop-up di condivisione schermo.\nSeleziona quanto segue:", "NOT_RUNNING_XR": "Assicurati che Monado o WiVRn siano attivi.",
"WAITING_FOR_USER": "Controlla il desktop per un pop-up di condivisione schermo.", "INVALID_ARGS": "Controlla gli argomenti di avvio.",
"FAIL": "Impossibile inizializzare la sorgente di trasmissione dello schermo." "COUD_NOT_CONNECT_TO_VR_RUNTIME": "Impossibile connettersi al VR runtime.",
"SELECT_SCREEN_CAST_FOR": "Seleziona la trasmissione schermo per il display {DISPLAY}",
"CANNOT_CAPTURE_KBD_MOUSE": "Impossibile inizializzare la cattura di tastiera/mouse!\nControlla che il tuo utente sia nel gruppo 'input'.",
"WE_ARE_GRABBING": "WayVR sta controllando tastiera e mouse!\nPremi Super+Z per rilasciare il controllo."
} }
} }

View File

@ -1,61 +1,5 @@
{ {
"ANCHOR": {
"CENTER": "センター"
},
"BAR": {
"ADD_MIRROR": "新しいミラーを追加",
"EDIT_MODE_TOGGLE": "編集モードの切り替え",
"ADD_NEW_SET": "新しいセットを追加",
"DELETE_CURRENT_SET": "現在のセットを削除",
"TOGGLE_VISIBILITY": "表示/非表示の切り替え",
"RESET_POSITION": "位置をリセット",
"RELOAD_FROM_DISK": "ディスクからXMLを再読み込み",
"CLOSE_MIRROR": "ミラーを閉じる",
"CLOSE_APP": "アプリを閉じる",
"FORCE_CLOSE_APP": "アプリを強制終了",
"HANDSFREE": {
"TITLE": "ハンズフリーモード",
"NONE": "オフ",
"HMD": "HMD + ピンチ",
"EYE_TRACKING": "視線 + ピンチ",
"HMD_ONLY": "HMDのみ",
"EYE_ONLY": "目のみ"
}
},
"WATCH": {
"RECENTER": "プレイスペースをリセンター",
"FIX_FLOOR": "床の高さを修正",
"EDIT_MODE_EXPLANATION": "オーバーレイは個別に移動および調整できます。\n現在のセットのオーバーレイを切り替え",
"DASHBOARD": "ダッシュボード",
"EDIT_MODE": "編集モード",
"ADD_NEW_SET": "新しいセットを追加",
"SWITCH_TO_SET": "セットに切り替える",
"TOGGLE_FOR_CURRENT_SET": "現在のセットで表示を切り替え",
"LONG_PRESS_TO_DELETE_SET": "長押しでセットを削除",
"CLEANUP_MIRRORS": "現在表示されていないミラーを削除"
},
"EDIT_MODE": { "EDIT_MODE": {
"ADJUST_CURVATURE": "曲率の調整",
"ALPHA_BLEND_MODE": "アルファブレンド",
"BLENDING_ADDITIVE": "加算モード",
"CURVATURE": "曲率",
"DELETE": "削除",
"HINT_POINT_WINDOW": "ウィンドウをタップしてそのパラメータを変更できます。\n右側のボタンで編集モードを終了できます。",
"LEAVE": "編集モードを終了する",
"LOCK_INTERACTION": "インタラクションを無効化",
"DISABLE_GRAB": "グラブを無効化",
"MOVE_PRESS_AND_DRAG": "移動(押してドラッグ)",
"OPACITY": "不透明度",
"POSITIONING": "位置付け",
"RESIZE_PRESS_AND_DRAG": "サイズ変更(押してドラッグ)",
"POS_STATIC": "固定:置かれた場所に留まり、再センタリングされません。",
"POS_ANCHORED": "アンカー:セット内の他のウィンドウと共に移動します。デフォルト。",
"POS_FLOATING": "フローティング:置かれた場所に留まるが、表示される時に再センタリングされます。",
"POS_HMD": "HMD に追従する。",
"POS_HAND_L": "左手に追従する。",
"POS_HAND_R": "右手に追従する。",
"INTERPOLATION": "スムージング",
"KEYBOARD": "キーボード",
"STEREO_3D_MODE": { "STEREO_3D_MODE": {
"TITLE": "ステレオ3Dモード", "TITLE": "ステレオ3Dモード",
"SPLIT_LEFT_RIGHT": "左→右", "SPLIT_LEFT_RIGHT": "左→右",
@ -68,7 +12,6 @@
"FULL_FRAME_BAT": "フルBAT", "FULL_FRAME_BAT": "フルBAT",
"ADJUST_MOUSE": "マウス調整" "ADJUST_MOUSE": "マウス調整"
}, },
"ALIGN_TO_HMD": "常にHMDの方を向く",
"MOUSE": { "MOUSE": {
"TITLE": "マウスの修正", "TITLE": "マウスの修正",
"WRONG_SCREEN_SELECTION_HELP": "カーソルが全く別のスクリーンで動く場合、\nスクリーンが正しく選択されていない可能性があります。\nReadmeをご参照ください。", "WRONG_SCREEN_SELECTION_HELP": "カーソルが全く別のスクリーンで動く場合、\nスクリーンが正しく選択されていない可能性があります。\nReadmeをご参照ください。",
@ -81,57 +24,157 @@
"ROTATE180": "回転 180°", "ROTATE180": "回転 180°",
"ROTATE270": "回転 270°" "ROTATE270": "回転 270°"
}, },
"GLOBAL": "常に表示", "ADJUST_CURVATURE": "曲率を調整",
"ANGLE_FADE": "角度フェード", "ALIGN_TO_HMD": "HMDに向ける",
"ANGLE_FADE_HELP": "HMDに向いていない時にフェード", "ALPHA_BLEND_MODE": "アルファブレンディングモード",
"BLOCK_INPUT": "ゲーム入力をブロック", "ANGLE_FADE": "角度によるフェード",
"RESIZE_CORNER": "ドラッグしてサイズ変更" "ANGLE_FADE_HELP": "HMDに向いていない時にフェードアウト",
"BLENDING_ADDITIVE": "加算合成",
"BLOCK_INPUT": "ゲームへの入力を遮断",
"CURVATURE": "曲率",
"DELETE": "長押しで現在のセットから削除",
"DISABLE_GRAB": "掴むのを無効化",
"GLOBAL": "常時表示",
"HINT_POINT_WINDOW": "ウィンドウを指してパラメータを変更してください。\n完了したら、右側のボタンで編集モードを終了します。",
"INTERPOLATION": "補間",
"KEYBOARD": "キーボード",
"LEAVE": "編集モードを終了",
"LOCK_INTERACTION": "インタラクションをロック",
"MOVE_PRESS_AND_DRAG": "移動(押しながらドラッグ)",
"OPACITY": "不透明度",
"POS_FLOATING": "フローティング:独立して移動し、表示時に中心位置がリセットされる。",
"POS_HAND_L": "左手に追従",
"POS_HAND_R": "右手に従う",
"POS_HMD": "HMDに従う",
"POS_STATIC": "固定:どのセットにも属さず、リセンターを行わない。",
"POSITIONING": "配置",
"RESIZE_PRESS_AND_DRAG": "リサイズ (押し込みながらドラッグ)",
"RESIZE_CORNER": "ドラッグしてリサイズ",
"POS_ANCHORED": "セット追従:セットと一緒に移動。デフォルト。"
},
"DEFINITIONS": {
"ANCHORED": "セット追従",
"FLOATING": "フローティング",
"STATIC": "固定",
"SET": "セット",
"WATCH": "ウォッチ",
"DASHBOARD": "ダッシュボード",
"EDIT_MODE": "編集モード",
"MIRROR": "ミラー",
"SETTINGS": "設定",
"KEYBOARD": "キーボード",
"TASKBAR": "タスクバー",
"FEATURES": "機能",
"OVERLAY": "オーバーレイ"
},
"ANCHOR": {
"CENTER": "中心"
},
"BAR": {
"ADD_MIRROR": "ミラーオーバーレイを追加",
"ADD_NEW_SET": "セットを追加",
"CLOSE_APP": "アプリを終了",
"CLOSE_OVERLAY": "オーバーレイを閉じる",
"DELETE_CURRENT_SET": "現在のセットを削除",
"EDIT_MODE_TOGGLE": "編集モード切替",
"FORCE_CLOSE_APP": "アプリを強制終了",
"HANDSFREE": {
"EYE_ONLY": "視線ポインター",
"EYE_TRACKING": "視線 + ピンチ",
"HMD": "HMD + ピンチ",
"HMD_ONLY": "HMDレーザー",
"NONE": "オフ",
"TITLE": "ハンズフリーモード"
},
"RELOAD_FROM_DISK": "ディスクからXMLを再読み込み",
"RESET_POSITION": "位置をリセット",
"TOGGLE_VISIBILITY": "表示切替",
"ADD_PASSTHRU": "パススルー・カットアウトを追加"
}, },
"DISABLED": "無効",
"DEFAULT": "デフォルト", "DEFAULT": "デフォルト",
"DISABLED": "無効",
"DONE": "完了",
"ALTTAB": {
"RELEASE_TO_FOCUS": "アプリに合わせてSuperキーを離すと、そのアプリがフォーカスされる。",
"WHILE_AIMING": "ポインター操作中",
"CLICK": "VRポインターでクリック",
"GRABALL": "セット全体を移動",
"GRAB": "個別のオーバーレイを移動",
"DASH": "ダッシュボードの切り替え",
"EDIT": "編集モードの切り替え",
"SET": "セットを切り替え",
"RECENTER": "表示/非表示/中心に配置",
"GENERAL_BINDS": "基本操作",
"TOGGLE_CAPTURE": "デスクトップに操作を戻す",
"FOCUS_MODE": "フォーカスモード (Superキーを長押し)",
"CLOSE": "フォーカス中のアプリを閉じる",
"MOUSE": "実マウスのクリックとスクロールもVRポインターに反映される"
},
"GRAB": { "GRAB": {
"ADJUST_DISTANCE": "距離を調整", "ADJUST_DISTANCE": "距離を調整",
"ADJUST_SIZE": "サイズ調整", "ADJUST_SIZE": "サイズ調整",
"UNRESTRICTED_MOVEMENT": "配置制限なし", "GRABBING_FLOATING": "このオーバーレイはフローティング状態であり、再センタリングしない限りその場に固定される。",
"GRABBING_WATCH": "手を入れ替えるにはウォッチを前に移動させて、もう一方の手で掴んでください。", "GRABBING_FOLLOW": "このオーバーレイは、アタッチされているデバイスに従って移動する。",
"GRABBING_STATIC": "このオーバーレイは固定であり、リセンターを無視してその場に留まります。", "GRABBING_STATIC": "このオーバーレイは「固定」されており、リセンターしても位置が変わりません。",
"GRABBING_ANCHORED": "アンカーされたオーバーレイはすべて一緒に移動します。もう一方の手で掴んでアンカーを掴んだまま、単一のウィンドウを分離できます。", "GRABBING_WATCH": "手を変えるには、ウォッチを前に出して、もう一方の手で掴んでください。",
"GRABBING_ANCHORED_EDIT": "このオーバーレイは、センター・マーカーに固定されます。", "UNRESTRICTED_MOVEMENT": "自由移動",
"GRABBING_FLOATING": "このオーバーレイはフローティングのため、リセンターまではその場所に留まります。", "GRABBING_ANCHORED": "セット追従しているオーバーレイは、セットと一緒に移動します。セットを掴んだまま、もう一方の手でウィンドウを掴むことで、個別のウィンドウとして切り離せます。",
"GRABBING_FOLLOW": "このオーバーレイは、接続されているデバイスに追従します。" "GRABBING_ANCHORED_EDIT": "このオーバーレイは中心マーカーに固定される。"
},
"SCREENCAST": {
"PENDING": "待機中...",
"QUEUED": "別のオーバーレイのスクリーンキャストポップアップの承認待ち。",
"WAITING_FOR_USER_DESC": "デスクトップのスクリーンキャスト通知を確認して、以下を選択してほしい:",
"WAITING_FOR_USER": "デスクトップのスクリーンキャスト通知を確認して。",
"FAIL": "スクリーンキャストのソースを初期化できませんでした。"
}, },
"TOAST": { "TOAST": {
"DEFAULT_TITLE": "通知", "TITLE_SCREENCAST_FAIL": "スクリーンキャストソースを開始できませんでした!",
"ERROR": "エラー",
"CANNOT_REMOVE_SET": "セットを削除できません!",
"NO_SET_SELECTED": "セットが選択されていません。",
"LAST_EXISTING_SET": "これが最後の設定です。",
"EMPTY_SET": "空のセットです!",
"ONE_CONTROLLER_ON_FLOOR": "コントローラーを床に置いてください!",
"CANNOT_ADD_SET": "セットを追加できません!", "CANNOT_ADD_SET": "セットを追加できません!",
"MAXIMUM_SETS_REACHED": "最大セット数に達しました。", "CANNOT_REMOVE_SET": "セットを削除できない!",
"FIXING_FLOOR_IN_X_SECS": "{SECONDS}秒で床を固定中...", "DEFAULT_TITLE": "通知",
"TITLE_SCREENCAST_FAIL": "スクリーンキャストのソースを開始できませんでした!", "EMPTY_SET": "セットが空です!",
"LETS_ADD_OVERLAYS": "タスクバーからオーバーレイを追加しましょう!" "ERROR": "エラー",
"FIXING_FLOOR_IN_X_SECS": "{SECONDS}秒後に床の高さを調整します...",
"LAST_EXISTING_SET": "最後のセットです。",
"LETS_ADD_OVERLAYS": "タスクバーからオーバーレイを追加しよう!",
"MAXIMUM_SETS_REACHED": "セット数が上限に達しました。",
"NO_SET_SELECTED": "セットが選択されていません。",
"ONE_CONTROLLER_ON_FLOOR": "コントローラーを片方、床に置いてください!",
"NO_KEYMAPS_CONFIGURED": "キーボードレイアウトが設定されていない",
"NO_KEYMAPS_CONFIGURED_HELP": "キーボードレイアウトの設定方法は wayvr.org を確認してね!"
},
"WATCH": {
"ADD_NEW_SET": "新しいセットを追加",
"CLEANUP_MIRRORS": "表示されていない\nミラーを削除",
"DASHBOARD": "ダッシュボード",
"EDIT_MODE": "編集モード",
"FIX_FLOOR": "床の高さを固定",
"LONG_PRESS_TO_DELETE_SET": "長押しで削除",
"RECENTER": "プレイスペースをリセンター",
"SWITCH_TO_SET": "セットを切り替える",
"TOGGLE_FOR_CURRENT_SET": "現在のセットを切り替え"
}, },
"DONE": "完了",
"WHISPER": { "WHISPER": {
"TRANSCRIBE": "ボタンを長押ししてテキストを文字起こしする", "TRANSCRIBE": "押して離さないで文字起こし",
"PASTE": "文字起こしをクリップボードにコピー", "PASTE": "書き起こしをクリップボードにコピー",
"PASTE_AND_GO": "コピーしてフォーカスされているアプリにCtrl-Vを送信", "PASTE_AND_GO": "書き起こしをコピーして、フォーカス中のアプリにCtrl-Vを送信",
"SEND_OSC": "OSCチャットボックスに送信", "SEND_OSC": "文字起こし結果をOSCチャットボックスに送信",
"UNLOAD_AND_CLOSE": "モデルをアンロードして閉じる", "UNLOAD_AND_CLOSE": "モデルを解除して閉じる",
"MODEL_NOT_DOWNLOADED": "文字起こしが設定されていません!", "MODEL_NOT_DOWNLOADED": "音声認識が設定されていません!",
"DOWNLOAD_GUIDANCE": "機能設定の中に文字起こしを設定してください!", "DOWNLOAD_GUIDANCE": "設定の「機能」タブで音声入力の設定をしてね",
"INITIAL_TEXT": "マイクボタンを押し続けて文字起こしを開始してください...", "INITIAL_TEXT": "マイクボタンを長押しして文字起こしを開始...",
"INIT_ERROR": "Whisperエンジンの起動中にエラーが発生しました", "INIT_ERROR": "Whisperエンジンの起動中にエラーが発生しました",
"ENTER_KEY": "Enterキー" "ENTER_KEY": "Enterキー"
}, },
"SCREENCAST": { "NOTIFICATION": {
"PENDING": "少々お待ちください...", "NOT_RUNNING_XR_VR": "Monado、WiVRn、またはSteamVRが実行されていることを確認してください。",
"QUEUED": "別のオーバーレイのスクリーンキャスト許可ポップアップの応答を待っています。", "NOT_RUNNING_VR": "Monado、WiVRn、またはSteamVRが実行されているか確認してください。",
"WAITING_FOR_USER_DESC": "デスクトップのスクリーンキャストのポップアップを確認してください。\n以下を選択してください", "NOT_RUNNING_XR": "Monado または WiVRn が実行されているか確認してください。",
"WAITING_FOR_USER": "デスクトップにスクリーンキャストのポップアップが表示されていないか確認してください。", "INVALID_ARGS": "起動引数を確認してください。",
"FAIL": "スクリーンキャストのソースを初期化できませんでした。" "COUD_NOT_CONNECT_TO_VR_RUNTIME": "VRランタイムに接続できませんでした。",
"SELECT_SCREEN_CAST_FOR": "ディスプレイ {DISPLAY} のスクリーンキャストを選択してください",
"CANNOT_CAPTURE_KBD_MOUSE": "キーボード/マウスのキャプチャを初期化できませんでした!\nユーザーが 'input' グループに所属しているか確認してください。",
"WE_ARE_GRABBING": "WayVR がキーボードとマウスを制御しています。\n解除するには、Super+Zを押してください。"
} }
} }

View File

@ -1,62 +1,5 @@
{ {
"ANCHOR": {
"CENTER": "Centrum"
},
"BAR": {
"ADD_MIRROR": "Dodaj nowy widok lustrzany",
"EDIT_MODE_TOGGLE": "Przełącz tryb edycji",
"ADD_NEW_SET": "Dodaj nowy zestaw",
"DELETE_CURRENT_SET": "Usuń aktualny zestaw",
"TOGGLE_VISIBILITY": "Przełącz widoczność",
"RESET_POSITION": "Zresetuj pozycję",
"RELOAD_FROM_DISK": "Przeładuj XML z dysku",
"CLOSE_MIRROR": "Zamknij lustro",
"CLOSE_APP": "Zamknij aplikację",
"FORCE_CLOSE_APP": "Wymuś zamknięcie aplikacji",
"HANDSFREE": {
"TITLE": "Tryb wolnych rąk",
"NONE": "Wyłączone",
"HMD": "HMD + uszczypnięcie",
"EYE_TRACKING": "Oko + uszczypnięcie",
"HMD_ONLY": "Tylko HMD",
"EYE_ONLY": "Tylko oczy"
}
},
"WATCH": {
"RECENTER": "Wyśrodkuj przestrzeń gry",
"FIX_FLOOR": "Napraw wysokość podłogi",
"EDIT_MODE_EXPLANATION": "Nakładki można teraz przesuwać i dostosowywać indywidualnie.\nPrzełącz nakładki dla bieżącego zestawu:",
"DASHBOARD": "Pulpit",
"EDIT_MODE": "Tryb edycji",
"ADD_NEW_SET": "Dodaj nowy zestaw",
"SWITCH_TO_SET": "Przełącz na zestaw",
"TOGGLE_FOR_CURRENT_SET": "Przełącz widoczność w bieżącym zestawie",
"LONG_PRESS_TO_DELETE_SET": "Przytrzymaj, aby usunąć zestaw",
"CLEANUP_MIRRORS": "Usuń lustra, które\nnie są obecnie widoczne"
},
"EDIT_MODE": { "EDIT_MODE": {
"ADJUST_CURVATURE": "Dostosuj zakrzywienie",
"ALPHA_BLEND_MODE": "Tryb mieszania kolorów",
"BLENDING_ADDITIVE": "Addytywne",
"CURVATURE": "Zakrzywienie",
"DELETE": "Usuń",
"HINT_POINT_WINDOW": "Wskaż na okno, aby zmienić jego parametry.\nPo zakończeniu wyjdź z trybu edycji za pomocą przycisku po prawej stronie.",
"LEAVE": "Wyjdź z trybu edycji",
"LOCK_INTERACTION": "Zablokuj interakcję",
"DISABLE_GRAB": "Wyłącz chwytanie",
"MOVE_PRESS_AND_DRAG": "Przesuń (naciśnij i przeciągnij)",
"OPACITY": "Przezroczystość",
"POSITIONING": "Pozycjonowanie",
"BLOCK_INPUT": "Blokuj input z gry",
"RESIZE_PRESS_AND_DRAG": "Zmień rozmiar (naciśnij i przeciągnij)",
"POS_STATIC": "Statyczne: Pozostaje w miejscu i nigdy nie jest ponownie wyśrodkowywane.",
"POS_ANCHORED": "Zakotwiczone: Porusza się razem z resztą zestawu. Domyślne.",
"POS_FLOATING": "Pływające: Pozostaje w miejscu, ponownie się wyśrodkowuje po pokazaniu.",
"POS_HMD": "Podążaj za HMD.",
"POS_HAND_L": "Podążaj za lewą dłonią.",
"POS_HAND_R": "Podążaj za prawą dłonią.",
"INTERPOLATION": "Interpolacja",
"KEYBOARD": "Klawiatura",
"STEREO_3D_MODE": { "STEREO_3D_MODE": {
"SPLIT_BOTTOM_TOP": "DOŁ→GÓRA", "SPLIT_BOTTOM_TOP": "DOŁ→GÓRA",
"SPLIT_LEFT_RIGHT": "LEWO→PRAWO", "SPLIT_LEFT_RIGHT": "LEWO→PRAWO",
@ -69,7 +12,6 @@
"FULL_FRAME_BAT": "Full-BAT", "FULL_FRAME_BAT": "Full-BAT",
"ADJUST_MOUSE": "Dostosuj mysz" "ADJUST_MOUSE": "Dostosuj mysz"
}, },
"ALIGN_TO_HMD": "Dopasuj do HMD",
"MOUSE": { "MOUSE": {
"TITLE": "Naprawa myszy", "TITLE": "Naprawa myszy",
"WRONG_SCREEN_SELECTION_HELP": "Jeśli kursor porusza się na zupełnie innym ekranie,\nekrany zostały prawdopodobnie nieprawidłowo wybrane. Zobacz dokument README.", "WRONG_SCREEN_SELECTION_HELP": "Jeśli kursor porusza się na zupełnie innym ekranie,\nekrany zostały prawdopodobnie nieprawidłowo wybrane. Zobacz dokument README.",
@ -82,56 +24,157 @@
"FLIP180": "Odwrócony o 180°", "FLIP180": "Odwrócony o 180°",
"FLIP270": "Odwrócony o 270°" "FLIP270": "Odwrócony o 270°"
}, },
"ADJUST_CURVATURE": "Dostosuj krzywiznę",
"ALIGN_TO_HMD": "Dopasuj do HMD",
"ALPHA_BLEND_MODE": "Tryb mieszania alfa",
"ANGLE_FADE": "Wygaszanie kątowe",
"ANGLE_FADE_HELP": "Wygaszenie, gdy nie patrzysz na HMD",
"BLENDING_ADDITIVE": "Mieszanie addytywne",
"BLOCK_INPUT": "Blokuj wejście z gry",
"CURVATURE": "Krzywizna",
"DELETE": "Przytrzymaj, aby usunąć z bieżącego zestawu",
"DISABLE_GRAB": "Wyłącz chwytanie",
"GLOBAL": "Zawsze widoczne", "GLOBAL": "Zawsze widoczne",
"ANGLE_FADE": "Zanik kątowy", "HINT_POINT_WINDOW": "Wskaż okno, aby zmienić jego parametry.\nPo zakończeniu wyjdź z trybu edycji przyciskiem po prawej stronie.",
"ANGLE_FADE_HELP": "Wyblaknij, gdy nie patrzysz na HMD", "INTERPOLATION": "Interpolacja",
"KEYBOARD": "Klawiatura",
"LEAVE": "Wyjdź z trybu edycji",
"LOCK_INTERACTION": "Blokuj interakcję",
"MOVE_PRESS_AND_DRAG": "Przesuń (przyciśnij i przeciągnij)",
"OPACITY": "Przezroczystość",
"POS_ANCHORED": "Przytwierdzone: Przesuwa się wraz z zestawem. Domyślnie.",
"POS_FLOATING": "Pływający: przesuwa się niezależnie, centruje się po wyświetleniu.",
"POS_HAND_L": "Podążaj za lewą ręką.",
"POS_HAND_R": "Podążaj za prawą ręką.",
"POS_HMD": "Podążaj za HMD.",
"POS_STATIC": "Stacjonarny: Poza jakimkolwiek zestawem, brak recentrowania.",
"POSITIONING": "Pozycjonowanie",
"RESIZE_PRESS_AND_DRAG": "Zmień rozmiar (naciśnij i przeciągnij)",
"RESIZE_CORNER": "Przeciągnij, aby zmienić rozmiar" "RESIZE_CORNER": "Przeciągnij, aby zmienić rozmiar"
}, },
"DISABLED": "Wyłączone", "DEFINITIONS": {
"ANCHORED": "Przytwierdzone",
"FLOATING": "Pływający",
"STATIC": "Stacjonarny",
"SET": "Zestaw",
"WATCH": "Zegarek",
"DASHBOARD": "Panel sterowania",
"EDIT_MODE": "Tryb edycji",
"MIRROR": "Lustro",
"SETTINGS": "Ustawienia",
"KEYBOARD": "Klawiatura",
"TASKBAR": "Pasek zadań",
"FEATURES": "Funkcje",
"OVERLAY": "Nakładka"
},
"ANCHOR": {
"CENTER": "Środek"
},
"BAR": {
"ADD_MIRROR": "Dodaj nową nakładkę lustra",
"ADD_NEW_SET": "Dodaj nowy zestaw",
"CLOSE_APP": "Zamknij aplikację",
"CLOSE_OVERLAY": "Zamknij nakładkę",
"DELETE_CURRENT_SET": "Usuń aktualny zestaw",
"EDIT_MODE_TOGGLE": "Przełącz tryb edycji",
"FORCE_CLOSE_APP": "Wymuś zamknięcie aplikacji",
"HANDSFREE": {
"EYE_ONLY": "Laser z oczu",
"EYE_TRACKING": "Wzrok + szczypanie",
"HMD": "HMD + szczypanie",
"HMD_ONLY": "Laser z HMD",
"NONE": "Wył.",
"TITLE": "Tryb bezkontaktowy"
},
"RELOAD_FROM_DISK": "Przeładuj XML z dysku",
"RESET_POSITION": "Resetuj pozycję",
"TOGGLE_VISIBILITY": "Przełącz widoczność",
"ADD_PASSTHRU": "Dodaj wycięcie passthrough"
},
"DEFAULT": "Domyślny", "DEFAULT": "Domyślny",
"DISABLED": "Wyłączony",
"DONE": "Gotowe",
"ALTTAB": {
"RELEASE_TO_FOCUS": "Wyceluj w aplikację i puść klawisz Super, aby ją zaznaczyć.",
"WHILE_AIMING": "Podczas celowania",
"CLICK": "Kliknięcie wskaźnikiem VR",
"GRABALL": "Przesuń cały zestaw",
"GRAB": "Przesuń pojedynczą nakładkę",
"DASH": "Przełącz panel sterowania",
"EDIT": "Przełącz tryb edycji",
"SET": "Zmień zestaw",
"RECENTER": "Pokaż/ukryj/wyśrodkuj",
"GENERAL_BINDS": "Ogólne przypisania",
"TOGGLE_CAPTURE": "Oddaj kontrolę do pulpitu",
"FOCUS_MODE": "Tryb skupienia (przytrzymaj Super)",
"CLOSE": "Zamknij aktywną aplikację",
"MOUSE": "Kliknięcia i przewijanie myszką przenoszą się na wskaźnik VR"
},
"GRAB": { "GRAB": {
"ADJUST_DISTANCE": "Dostosuj odległość", "ADJUST_DISTANCE": "Dostosuj odległość",
"ADJUST_SIZE": "Dostosuj rozmiar", "ADJUST_SIZE": "Dopasuj rozmiar",
"UNRESTRICTED_MOVEMENT": "Nieograniczony ruch", "GRABBING_ANCHORED": "Przytwierdzone nakładki poruszają się wraz z zestawem. Aby odseparować pojedyncze okno, chwyć je drugą ręką, nadal trzymając zestaw.",
"GRABBING_WATCH": "Aby zamienić ręce, przenieś zegarek na przód i chwyć go drugą ręką.", "GRABBING_ANCHORED_EDIT": "Ten overlay pozostanie zakotwiczony w markerze środka.",
"GRABBING_STATIC": "Ta nakładka jest statyczna i pozostanie na swoim miejscu, ignorując centrowanie.", "GRABBING_FLOATING": "Ten overlay jest pływający i pozostanie w miejscu, chyba że zostanie wycentrowany.",
"GRABBING_ANCHORED": "Przymocowane nakładki poruszają się razem. Aby oddzielić pojedyncze okno, chwyć je drugą ręką, podczas gdy nadal trzymasz kotwicę.", "GRABBING_FOLLOW": "Nakładka będzie podążać za urządzeniem, do którego jest przypisana.",
"GRABBING_ANCHORED_EDIT": "Ta nakładka pozostanie zakotwiczona do znacznika centralnego.", "GRABBING_STATIC": "Ten overlay jest stacjonarny i pozostanie w miejscu, ignorując centrowanie.",
"GRABBING_FLOATING": "Ta nakładka jest zawieszony i pozostanie na miejscu, chyba że zostanie wycentrowany.", "GRABBING_WATCH": "Aby zmienić rękę, przesuń zegarek do przodu i chwyć go drugą ręką.",
"GRABBING_FOLLOW": "Ta nakładka będzie śledzić urządzenie, do którego jest dołączona." "UNRESTRICTED_MOVEMENT": "Ruch swobodny"
},
"TOAST": {
"DEFAULT_TITLE": "Powiadomienie",
"ERROR": "Błąd",
"CANNOT_REMOVE_SET": "Nie można usunąć zestawu!",
"NO_SET_SELECTED": "Nie wybrano żadnego zestawu.",
"LAST_EXISTING_SET": "To jest ostatni istniejący zestaw.",
"EMPTY_SET": "Pusty zestaw!",
"ONE_CONTROLLER_ON_FLOOR": "Umieść jeden kontroler na podłodze!",
"CANNOT_ADD_SET": "Nie można dodać zestawu!",
"MAXIMUM_SETS_REACHED": "Osiągnięto maksymalną liczbę zestawów.",
"FIXING_FLOOR_IN_X_SECS": "Naprawianie podłogi za {SECONDS} sekund(y)...",
"TITLE_SCREENCAST_FAIL": "Nie udało się uruchomić źródła przesyłania obrazu z ekranu!",
"LETS_ADD_OVERLAYS": "Dodajmy kilka nakładek z paska zadań!"
},
"DONE": "Gotowe",
"WHISPER": {
"TRANSCRIBE": "Naciśnij i przytrzymaj, aby transkrybować tekst",
"PASTE": "Kopiuj transkrypcję do schowka",
"PASTE_AND_GO": "Kopiuj transkrypcję i wyślij Ctrl-V do aktywnej aplikacji",
"SEND_OSC": "Wyślij transkrypcję do okna czatu OSC",
"UNLOAD_AND_CLOSE": "Odładuj model i zamknij",
"MODEL_NOT_DOWNLOADED": "Zamiana mowy na tekst nie została skonfigurowana!",
"DOWNLOAD_GUIDANCE": "Skonfiguruj funkcję zamiany mowy na tekst w ustawieniach, w sekcji funkcje!",
"INITIAL_TEXT": "Naciśnij i przytrzymaj przycisk mikrofonu, aby rozpocząć transkrypcję...",
"INIT_ERROR": "Błąd podczas uruchamiania silnika Whisper",
"ENTER_KEY": "Klawisz Enter"
}, },
"SCREENCAST": { "SCREENCAST": {
"PENDING": "Proszę czekać...", "PENDING": "Proszę czekać...",
"QUEUED": "Oczekiwanie na zatwierdzenie okna wysyłania obrazu z innego nakładki.", "QUEUED": "Oczekiwanie na zatwierdzenie okna przesyłania obrazu z innej nakładki.",
"WAITING_FOR_USER_DESC": "Sprawdź na pulpicie okno wyboru ekranu do transmitowania.\nWybierz następujące:", "WAITING_FOR_USER_DESC": "Sprawdź na pulpicie powiadomienie o przesyłaniu ekranu.\nWybierz następujące:",
"WAITING_FOR_USER": "Sprawdź na pulpicie powiadomienie o przesyłaniu ekranu.", "WAITING_FOR_USER": "Sprawdź powiadomienie o przesyłaniu ekranu na pulpicie.",
"FAIL": "Nie udało się zainicjować źródła przesyłania obrazu z ekranu." "FAIL": "Nie udało się zainicjować źródła przesyłania obrazu."
},
"TOAST": {
"TITLE_SCREENCAST_FAIL": "Nie udało się uruchomić źródła przesyłania obrazu!",
"CANNOT_ADD_SET": "Nie można dodać zestawu!",
"CANNOT_REMOVE_SET": "Nie można usunąć zestawu!",
"DEFAULT_TITLE": "Powiadomienie",
"EMPTY_SET": "Pusty zestaw!",
"ERROR": "Błąd",
"FIXING_FLOOR_IN_X_SECS": "Korekta wysokości podłogi za {SECONDS} s...",
"LAST_EXISTING_SET": "To ostatni istniejący zestaw.",
"LETS_ADD_OVERLAYS": "Dodaj kilka nakładek z paska zadań!",
"MAXIMUM_SETS_REACHED": "Osiągnięto maksymalną liczbę zestawów.",
"NO_SET_SELECTED": "Żaden zestaw nie jest wybrany.",
"ONE_CONTROLLER_ON_FLOOR": "Połóż jeden kontroler na podłodze!",
"NO_KEYMAPS_CONFIGURED": "Brak skonfigurowanych układów klawiatury",
"NO_KEYMAPS_CONFIGURED_HELP": "Odwiedź stronę wayvr.org, aby dowiedzieć się, jak skonfigurować układy klawiatury!"
},
"WATCH": {
"ADD_NEW_SET": "Dodaj nowy zestaw",
"CLEANUP_MIRRORS": "Usuń niewidoczne\nlustra",
"DASHBOARD": "Panel sterowania",
"EDIT_MODE": "Tryb edycji",
"FIX_FLOOR": "Dostosuj poziom podłogi",
"LONG_PRESS_TO_DELETE_SET": "Przytrzymaj, aby usunąć",
"RECENTER": "Wyśrodkuj obszar gry",
"SWITCH_TO_SET": "Zmień zestaw",
"TOGGLE_FOR_CURRENT_SET": "Przełącz widoczność zestawu"
},
"WHISPER": {
"TRANSCRIBE": "Przytrzymaj, aby zapisać tekst",
"PASTE": "Kopiuj transkrypcję do schowka",
"PASTE_AND_GO": "Kopiuj transkrypcję i wyślij Ctrl-V do aktywnej aplikacji",
"SEND_OSC": "Wyślij transkrypcję do czatu OSC",
"UNLOAD_AND_CLOSE": "Odładuj model i zamknij",
"MODEL_NOT_DOWNLOADED": "Konwersja mowy na tekst nie jest skonfigurowana!",
"DOWNLOAD_GUIDANCE": "Skonfiguruj zamianę mowy na tekst w ustawieniach, w zakładce funkcje!",
"INITIAL_TEXT": "Przytrzymaj przycisk mikrofonu, aby rozpocząć transkrypcję...",
"INIT_ERROR": "Błąd podczas uruchamiania silnika Whisper",
"ENTER_KEY": "Klawisz Enter"
},
"NOTIFICATION": {
"NOT_RUNNING_XR_VR": "Upewnij się, że Monado, WiVRn lub SteamVR jest uruchomione.",
"NOT_RUNNING_VR": "Upewnij się, że Monado, WiVRn lub SteamVR są uruchomione.",
"NOT_RUNNING_XR": "Upewnij się, że Monado lub WiVRn są uruchomione.",
"INVALID_ARGS": "Sprawdź argumenty uruchamiania.",
"COUD_NOT_CONNECT_TO_VR_RUNTIME": "Nie można połączyć się z runtime VR.",
"SELECT_SCREEN_CAST_FOR": "Wybierz przesyłanie ekranu dla wyświetlacza {DISPLAY}",
"CANNOT_CAPTURE_KBD_MOUSE": "Nie można zainicjować przechwytywania klawiatury/myszy!\nSprawdź, czy Twój użytkownik należy do grupy 'input'.",
"WE_ARE_GRABBING": "WayVR przejął kontrolę nad klawiaturą i myszą!\nNaciśnij Super+Z, aby zwolnić."
} }
} }

View File

@ -1,52 +1,5 @@
{ {
"ANCHOR": {
"CENTER": "中心"
},
"BAR": {
"ADD_MIRROR": "添加新的镜像覆盖层",
"EDIT_MODE_TOGGLE": "切换编辑模式",
"ADD_NEW_SET": "添加新集合",
"DELETE_CURRENT_SET": "删除当前集合",
"TOGGLE_VISIBILITY": "切换可见性",
"RESET_POSITION": "重置位置",
"RELOAD_FROM_DISK": "从磁盘重新加载 XML",
"CLOSE_MIRROR": "关闭镜像",
"CLOSE_APP": "关闭应用",
"FORCE_CLOSE_APP": "强制关闭应用",
"HANDSFREE": {
"TITLE": "免提模式",
"NONE": "关闭",
"HMD": "HMD + 捏合",
"EYE_TRACKING": "眼动 + 捏合",
"HMD_ONLY": "仅 HMD",
"EYE_ONLY": "仅限眼睛"
}
},
"DEFAULT": "默认",
"DISABLED": "已禁用",
"EDIT_MODE": { "EDIT_MODE": {
"ADJUST_CURVATURE": "调整曲率",
"ALPHA_BLEND_MODE": "Alpha 混合模式",
"BLENDING_ADDITIVE": "叠加混合",
"CURVATURE": "曲率",
"DELETE": "长按以从当前集合中移除",
"DISABLE_GRAB": "禁用抓取",
"HINT_POINT_WINDOW": "指向窗口以更改其参数。\n完成后使用右侧按钮退出编辑模式。",
"INTERPOLATION": "插值",
"ALIGN_TO_HMD": "对齐到头显 (HMD)",
"KEYBOARD": "键盘",
"LEAVE": "离开编辑模式",
"LOCK_INTERACTION": "锁定交互",
"MOVE_PRESS_AND_DRAG": "移动 (按住并拖拽)",
"OPACITY": "不透明度",
"POS_ANCHORED": "锚定:随中心标记移动。默认。",
"POS_FLOATING": "悬浮:独立移动,显示时重新居中。",
"POS_HAND_L": "跟随左手。",
"POS_HAND_R": "跟随右手。",
"POS_HMD": "跟随头显 (HMD)。",
"POS_STATIC": "静态:不属于任何集合,不重新居中。",
"POSITIONING": "定位",
"RESIZE_PRESS_AND_DRAG": "调整大小 (按住并拖拽)",
"STEREO_3D_MODE": { "STEREO_3D_MODE": {
"SPLIT_BOTTOM_TOP": "下→上", "SPLIT_BOTTOM_TOP": "下→上",
"SPLIT_LEFT_RIGHT": "左→右", "SPLIT_LEFT_RIGHT": "左→右",
@ -71,67 +24,157 @@
"FLIP180": "镜像旋转 180°", "FLIP180": "镜像旋转 180°",
"FLIP270": "镜像旋转 270°" "FLIP270": "镜像旋转 270°"
}, },
"ADJUST_CURVATURE": "调整曲率",
"ALIGN_TO_HMD": "朝向 HMD",
"ALPHA_BLEND_MODE": "Alpha 混合模式",
"ANGLE_FADE": "角度渐变",
"ANGLE_FADE_HELP": "远离 HMD 时淡出",
"BLENDING_ADDITIVE": "加法混合",
"BLOCK_INPUT": "屏蔽游戏输入",
"CURVATURE": "曲率",
"DELETE": "长按将其从当前套装中移除",
"DISABLE_GRAB": "禁用抓取",
"GLOBAL": "始终可见", "GLOBAL": "始终可见",
"ANGLE_FADE": "角度淡出", "HINT_POINT_WINDOW": "指向窗口以更改其参数。\n完成后点击右侧按钮退出编辑模式。",
"ANGLE_FADE_HELP": "未朝向HMD时淡出", "INTERPOLATION": "插值",
"BLOCK_INPUT": "阻止游戏输入", "KEYBOARD": "键盘",
"LEAVE": "退出编辑模式",
"LOCK_INTERACTION": "锁定交互",
"MOVE_PRESS_AND_DRAG": "移动 (按下并拖拽)",
"OPACITY": "不透明度",
"POS_ANCHORED": "同步移动:随套装一起移动。默认。",
"POS_FLOATING": "悬浮:独立移动,显示时自动居中。",
"POS_HAND_L": "跟随左手",
"POS_HAND_R": "跟随右手。",
"POS_HMD": "跟随 HMD",
"POS_STATIC": "静态:不属于任何套装,不重新居中。",
"POSITIONING": "位置设定",
"RESIZE_PRESS_AND_DRAG": "调整大小(按住并拖动)",
"RESIZE_CORNER": "拖动以调整大小" "RESIZE_CORNER": "拖动以调整大小"
}, },
"DEFINITIONS": {
"ANCHORED": "同步移动",
"FLOATING": "悬浮",
"STATIC": "静态",
"SET": "套装",
"WATCH": "手表",
"DASHBOARD": "控制面板",
"EDIT_MODE": "编辑模式",
"MIRROR": "镜像",
"SETTINGS": "设置",
"KEYBOARD": "键盘",
"TASKBAR": "任务栏",
"FEATURES": "功能",
"OVERLAY": "叠加层"
},
"ANCHOR": {
"CENTER": "中心"
},
"BAR": {
"ADD_MIRROR": "添加一个新的镜像叠加层",
"ADD_NEW_SET": "添加新套装",
"CLOSE_APP": "关闭应用",
"CLOSE_OVERLAY": "关闭覆盖层",
"DELETE_CURRENT_SET": "删除当前套装",
"EDIT_MODE_TOGGLE": "切换编辑模式",
"FORCE_CLOSE_APP": "强制关闭应用",
"HANDSFREE": {
"EYE_ONLY": "眼球射线",
"EYE_TRACKING": "眼动 + 捏合",
"HMD": "头显 + 捏合",
"HMD_ONLY": "头显射线",
"NONE": "关闭",
"TITLE": "免手操模式"
},
"RELOAD_FROM_DISK": "从磁盘重新加载 XML",
"RESET_POSITION": "重置位置",
"TOGGLE_VISIBILITY": "切换显示状态",
"ADD_PASSTHRU": "添加新的透视窗口"
},
"DEFAULT": "默认",
"DISABLED": "禁用",
"DONE": "完成",
"ALTTAB": {
"RELEASE_TO_FOCUS": "将光标对准应用并松开 Super 键以聚焦该应用。",
"WHILE_AIMING": "瞄准时",
"CLICK": "VR 指针点击",
"GRABALL": "移动整个集合",
"GRAB": "移动单个覆盖层",
"DASH": "切换控制面板",
"EDIT": "切换编辑模式",
"SET": "切换组",
"RECENTER": "显示/隐藏/重新居中",
"GENERAL_BINDS": "通用按键绑定",
"TOGGLE_CAPTURE": "将控制权还给桌面",
"FOCUS_MODE": "焦点模式 (按住 Super 键)",
"CLOSE": "关闭当前应用",
"MOUSE": "实体鼠标点击与滚动同样可转换为 VR 指针"
},
"GRAB": { "GRAB": {
"ADJUST_DISTANCE": "调整距离", "ADJUST_DISTANCE": "调整距离",
"ADJUST_SIZE": "调整大小", "ADJUST_SIZE": "调整尺寸",
"UNRESTRICTED_MOVEMENT": "无限制移动", "GRABBING_ANCHORED": "同步移动的覆盖层随套装一起移动。在抓取套装的同时,用另一只手抓取单个窗口即可将其分离。",
"GRABBING_WATCH": "若要更换手,请将手表移至前方并用另一只手抓取。", "GRABBING_ANCHORED_EDIT": "该覆盖层将锚定在中心标记处。",
"GRABBING_STATIC": "此覆盖层是静态的,将固定在原位,忽略重新居中。", "GRABBING_FLOATING": "该覆盖层处于悬浮状态,除非重新居中,否则将保持在原位。",
"GRABBING_ANCHORED": "锚定覆盖层将一起移动。通过用另一只手抓取单个窗口,同时仍抓取锚点来分离它。", "GRABBING_FOLLOW": "该覆盖层将跟随其绑定的设备移动。",
"GRABBING_ANCHORED_EDIT": "此覆盖层将保持锚定在中心标记上。", "GRABBING_STATIC": "该覆盖层为静态,将保持在原位,不受重新居中影响。",
"GRABBING_FLOATING": "此覆盖层是悬浮的,将固定在原位,除非重新居中。", "GRABBING_WATCH": "若要切换佩戴手,请将手表移至前方并用另一只手抓取。",
"GRABBING_FOLLOW": "此覆盖层将跟随它所连接的设备。" "UNRESTRICTED_MOVEMENT": "自由移动"
},
"TOAST": {
"DEFAULT_TITLE": "通知",
"ERROR": "错误",
"CANNOT_ADD_SET": "无法添加集合!",
"MAXIMUM_SETS_REACHED": "已达到集合数量上限。",
"CANNOT_REMOVE_SET": "无法移除集合!",
"NO_SET_SELECTED": "未选择集合。",
"LAST_EXISTING_SET": "这是最后一个现有的集合。",
"EMPTY_SET": "空集合!",
"ONE_CONTROLLER_ON_FLOOR": "请将一个控制器放在地面上!",
"FIXING_FLOOR_IN_X_SECS": "{SECONDS}秒内固定地面...",
"TITLE_SCREENCAST_FAIL": "无法启动屏幕投影源!",
"LETS_ADD_OVERLAYS": "让我们从任务栏添加一些覆盖层吧!"
},
"WATCH": {
"ADD_NEW_SET": "添加新集合",
"CLEANUP_MIRRORS": "移除当前不可见的镜像",
"DASHBOARD": "控制面板 (Dashboard)",
"EDIT_MODE": "编辑模式",
"EDIT_MODE_EXPLANATION": "覆盖层现在可以单独移动和调整。\n控制此集合中哪些覆盖层可见",
"FIX_FLOOR": "修复地面水平",
"LONG_PRESS_TO_DELETE_SET": "按住以删除",
"RECENTER": "重置游玩区中心 (Recenter)",
"SWITCH_TO_SET": "切换到集合",
"TOGGLE_FOR_CURRENT_SET": "切换当前集合"
},
"DONE": "完成",
"WHISPER": {
"TRANSCRIBE": "按住以转录文本",
"PASTE": "将转录内容复制到剪贴板",
"PASTE_AND_GO": "复制转录文本并向当前聚焦的应用发送 Ctrl-V",
"SEND_OSC": "将转录文本发送至 OSC 聊天框",
"UNLOAD_AND_CLOSE": "卸载模型并关闭",
"MODEL_NOT_DOWNLOADED": "语音转文本未设置!",
"DOWNLOAD_GUIDANCE": "请在“设置”中的“功能”选项下配置语音转文本!",
"INITIAL_TEXT": "按住麦克风按钮开始转录...",
"INIT_ERROR": "启动 Whisper 引擎时出错",
"ENTER_KEY": "回车键"
}, },
"SCREENCAST": { "SCREENCAST": {
"PENDING": "请稍候...", "PENDING": "请稍候...",
"QUEUED": "等待另一个覆盖层的屏幕投射确认弹窗。", "QUEUED": "正在等待另一个叠加层的屏幕投射确认。",
"WAITING_FOR_USER_DESC": "请检查桌面上的屏幕投射弹出窗口。\n选择以下选项", "WAITING_FOR_USER_DESC": "检查桌面上的屏幕共享弹窗。\n请选择以下项",
"WAITING_FOR_USER": "请检查桌面上的屏幕投射弹出窗口。", "WAITING_FOR_USER": "请检查桌面上的屏幕传输弹窗。",
"FAIL": "无法初始化屏幕镜像源。" "FAIL": "无法初始化屏幕传输源。"
},
"TOAST": {
"TITLE_SCREENCAST_FAIL": "无法启动屏幕投影源!",
"CANNOT_ADD_SET": "无法添加套装!",
"CANNOT_REMOVE_SET": "无法删除套装!",
"DEFAULT_TITLE": "通知",
"EMPTY_SET": "套装为空!",
"ERROR": "错误",
"FIXING_FLOOR_IN_X_SECS": "将在 {SECONDS} 秒后修正地面高度...",
"LAST_EXISTING_SET": "这是最后一个现有的套装。",
"LETS_ADD_OVERLAYS": "快从任务栏添加一些叠加层吧!",
"MAXIMUM_SETS_REACHED": "已达到最大套装数量。",
"NO_SET_SELECTED": "未选择套装。",
"ONE_CONTROLLER_ON_FLOOR": "将一只控制器放在地面上!",
"NO_KEYMAPS_CONFIGURED": "尚未配置键盘布局",
"NO_KEYMAPS_CONFIGURED_HELP": "请访问 wayvr.org 了解如何设置键盘布局!"
},
"WATCH": {
"ADD_NEW_SET": "添加新套装",
"CLEANUP_MIRRORS": "移除当前\n不可见的镜像",
"DASHBOARD": "控制面板",
"EDIT_MODE": "编辑模式",
"FIX_FLOOR": "固定地面高度",
"LONG_PRESS_TO_DELETE_SET": "长按以删除",
"RECENTER": "重新中心化活动范围",
"SWITCH_TO_SET": "切换至套装",
"TOGGLE_FOR_CURRENT_SET": "切换当前集合"
},
"WHISPER": {
"TRANSCRIBE": "按住以转写文本",
"PASTE": "将转写文本复制到剪贴板",
"PASTE_AND_GO": "复制转写文本并向当前聚焦的应用发送 Ctrl-V",
"SEND_OSC": "将转写文本发送至 OSC 聊天框",
"UNLOAD_AND_CLOSE": "卸载模型并关闭",
"MODEL_NOT_DOWNLOADED": "语音转文字尚未设置!",
"DOWNLOAD_GUIDANCE": "请在“设置”的“功能”选项卡中配置语音转文本!",
"INITIAL_TEXT": "按住麦克风按钮开始转写...",
"INIT_ERROR": "启动 Whisper 引擎时出错",
"ENTER_KEY": "回车键"
},
"NOTIFICATION": {
"NOT_RUNNING_XR_VR": "请确保 Monado、WiVRn 或 SteamVR 正在运行。",
"NOT_RUNNING_VR": "请确保 Monado、WiVRn 或 SteamVR 正在运行。",
"NOT_RUNNING_XR": "请确保 Monado 或 WiVRn 正在运行。",
"INVALID_ARGS": "检查你的启动参数。",
"COUD_NOT_CONNECT_TO_VR_RUNTIME": "无法连接到 VR 运行时。",
"SELECT_SCREEN_CAST_FOR": "为显示器 {DISPLAY} 选择屏幕投射",
"CANNOT_CAPTURE_KBD_MOUSE": "无法初始化键盘/鼠标捕获!\n请检查您的用户是否在 'input' 组中。",
"WE_ARE_GRABBING": "WayVR 正在接管你的键盘和鼠标!\n按 Super+Z 释放。"
} }
} }

Binary file not shown.

Binary file not shown.

View File

@ -1,27 +1,26 @@
use std::f32::consts::PI; use std::f32::consts::PI;
use std::process::{Child, Command}; use std::process::{Child, Command};
use std::sync::Arc; use std::sync::Arc;
use std::time::Instant; use std::time::{Duration, Instant};
use glam::{Affine3A, Vec2, Vec3A, Vec3Swizzles}; use glam::{Affine3A, Vec2, Vec3A, Vec3Swizzles};
use idmap_derive::IntegerId; use idmap_derive::IntegerId;
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};
use strum::AsRefStr; use strum::{AsRefStr, EnumIs};
use wayvr_ipc::packet_client::{HandsfreeAction, HandsfreeParams}; use wayvr_ipc::packet_client::{HandsfreeAction, HandsfreeParams};
use wlx_common::common::LeftRight; use wlx_common::common::LeftRight;
use wlx_common::windowing::{OverlayWindowState, Positioning}; use wlx_common::windowing::{OverlayWindowState, Positioning};
use crate::backend::task::{InputTask, OverlayTask}; use crate::backend::task::{InputTask, OverlayTask};
use crate::overlays::anchor::{ANCHOR_NAME, GRAB_HELP_NAME}; use crate::overlays::anchor::{ANCHOR_NAME, GRAB_HELP_NAME};
use crate::overlays::keyboard::KEYBOARD_NAME;
use crate::overlays::watch::WATCH_NAME; use crate::overlays::watch::WATCH_NAME;
use crate::state::{AppSession, AppState}; use crate::state::{AppSession, AppState};
use crate::subsystem::hid::WheelDelta; use crate::subsystem::hid::WheelDelta;
use crate::subsystem::input::KeyboardFocus; use crate::subsystem::input::InputFocus;
use crate::windowing::backend::OverlayEventData; use crate::windowing::backend::OverlayEventData;
use crate::windowing::manager::OverlayWindowManager; use crate::windowing::manager::OverlayWindowManager;
use crate::windowing::window::{self, OverlayWindowData, realign, scalar_scale}; use crate::windowing::window::{self, OverlayCategory, OverlayWindowData, realign, scalar_scale};
use crate::windowing::{OverlayID, OverlaySelector}; use crate::windowing::{OverlayID, OverlaySelector};
use super::task::TaskType; use super::task::TaskType;
@ -58,13 +57,24 @@ pub enum TrackedDeviceRole {
Tracker, Tracker,
} }
#[derive(Debug, Eq, PartialEq, Clone, Copy, EnumIs)]
pub enum FocusPickState {
None,
/// aiming to pick the focus
Aiming,
/// picking the focus. this will be consumed on valid on_hover
Picking,
}
pub struct InputState { pub struct InputState {
pub hmd: Affine3A, pub hmd: Affine3A,
pub ipd: f32, pub ipd: f32,
pub pointers: [Pointer; 2], pub pointers: [Pointer; 2],
pub devices: Vec<TrackedDevice>, pub devices: Vec<TrackedDevice>,
pub handsfree_state: PointerState, pub handsfree_state: PointerState,
pub picking_focus: FocusPickState,
processes: Vec<Child>, processes: Vec<Child>,
disable_lerp_until: Instant,
} }
impl InputState { impl InputState {
@ -76,17 +86,30 @@ impl InputState {
devices: Vec::new(), devices: Vec::new(),
processes: Vec::new(), processes: Vec::new(),
handsfree_state: PointerState::default(), handsfree_state: PointerState::default(),
picking_focus: FocusPickState::None,
disable_lerp_until: Instant::now(),
}
}
pub fn should_disable_lerp(&self) -> bool {
self.disable_lerp_until > Instant::now()
}
pub fn stop_picking(&mut self) {
if !self.picking_focus.is_none() {
self.picking_focus = FocusPickState::None;
self.disable_lerp_until = Instant::now() + Duration::from_millis(250);
} }
} }
pub fn apply_handsfree_action(&mut self, params: HandsfreeParams) { pub fn apply_handsfree_action(&mut self, params: HandsfreeParams) {
fn set_true(v: &mut bool) { const fn set_true(v: &mut bool) {
*v = true; *v = true;
} }
fn set_false(v: &mut bool) { const fn set_false(v: &mut bool) {
*v = false; *v = false;
} }
fn toggle(v: &mut bool) { const fn toggle(v: &mut bool) {
*v = !*v; *v = !*v;
} }
@ -107,10 +130,10 @@ impl InputState {
HandsfreeAction::Click => apply(&mut self.handsfree_state.click), HandsfreeAction::Click => apply(&mut self.handsfree_state.click),
HandsfreeAction::RightModifier => apply(&mut self.handsfree_state.click_modifier_right), HandsfreeAction::RightModifier => apply(&mut self.handsfree_state.click_modifier_right),
HandsfreeAction::MiddleModifier => { HandsfreeAction::MiddleModifier => {
apply(&mut self.handsfree_state.click_modifier_middle) apply(&mut self.handsfree_state.click_modifier_middle);
} }
HandsfreeAction::Grab => apply(&mut self.handsfree_state.grab), HandsfreeAction::Grab => apply(&mut self.handsfree_state.grab),
}; }
} }
pub fn handle_task(&mut self, task: InputTask) { pub fn handle_task(&mut self, task: InputTask) {
@ -208,6 +231,9 @@ fn debug_print_hand(hand: &Pointer) {
if hand.now.grab != hand.before.grab { if hand.now.grab != hand.before.grab {
log::debug!("Hand {}: grab {}", hand.idx, hand.now.grab); log::debug!("Hand {}: grab {}", hand.idx, hand.now.grab);
} }
if hand.now.grab_float != hand.before.grab_float {
log::debug!("Hand {}: grab {}", hand.idx, hand.now.grab);
}
if hand.now.alt_click != hand.before.alt_click { if hand.now.alt_click != hand.before.alt_click {
log::debug!("Hand {}: alt_click {}", hand.idx, hand.now.alt_click); log::debug!("Hand {}: alt_click {}", hand.idx, hand.now.alt_click);
} }
@ -254,6 +280,7 @@ pub struct InteractionState {
pub hovered_id: Option<OverlayID>, pub hovered_id: Option<OverlayID>,
pub should_block_input: bool, pub should_block_input: bool,
pub should_block_poses: bool, pub should_block_poses: bool,
pub kbd_block_activated: bool,
} }
impl Default for InteractionState { impl Default for InteractionState {
@ -265,6 +292,7 @@ impl Default for InteractionState {
hovered_id: None, hovered_id: None,
should_block_input: false, should_block_input: false,
should_block_poses: false, should_block_poses: false,
kbd_block_activated: false,
} }
} }
} }
@ -314,6 +342,7 @@ pub struct PointerState {
pub scroll_y: f32, pub scroll_y: f32,
pub click: bool, pub click: bool,
pub grab: bool, pub grab: bool,
pub grab_float: bool,
pub alt_click: bool, pub alt_click: bool,
pub show_hide: bool, pub show_hide: bool,
pub toggle_dashboard: bool, pub toggle_dashboard: bool,
@ -407,12 +436,14 @@ fn populate_lines(
} }
} }
fn update_focus(focus: &mut KeyboardFocus, overlay_keyboard_focus: Option<KeyboardFocus>) { fn update_focus(app: &mut AppState, overlay_input_focus: Option<InputFocus>) {
if let Some(f) = &overlay_keyboard_focus if let Some(f) = &overlay_input_focus
&& *focus != *f && app.input_state.picking_focus.is_none()
&& app
.hid_provider
.set_input_focus(app.wvr_server.as_mut(), *f)
{ {
log::debug!("Setting keyboard focus to {:?}", *f); log::debug!("Setting keyboard focus to {:?}", *f);
*focus = *f;
} }
} }
@ -460,6 +491,7 @@ where
if !pointer.tracked { if !pointer.tracked {
pointer.interaction.should_block_input = false; pointer.interaction.should_block_input = false;
pointer.interaction.should_block_poses = false; pointer.interaction.should_block_poses = false;
pointer.interaction.kbd_block_activated = false;
return (None, pending_haptics); // no hit return (None, pending_haptics); // no hit
} }
@ -524,7 +556,8 @@ where
pointer.interaction.should_block_poses = state.block_input pointer.interaction.should_block_poses = state.block_input
&& app.session.config.block_poses_on_kbd_interaction && app.session.config.block_poses_on_kbd_interaction
&& hovered.config.name.as_ref() == KEYBOARD_NAME; && hovered.config.category == OverlayCategory::Keyboard
&& pointer.interaction.kbd_block_activated;
} else { } else {
pointer.interaction.should_block_input = false; pointer.interaction.should_block_input = false;
pointer.interaction.should_block_poses = false; pointer.interaction.should_block_poses = false;
@ -535,21 +568,22 @@ where
let hovered_state = hovered.config.active_state.as_mut().unwrap(); let hovered_state = hovered.config.active_state.as_mut().unwrap();
let grab_float = pointer.now.grab_float;
let grab_start = pointer.now.grab && !pointer.before.grab;
// grab // grab
if pointer.now.grab && !pointer.before.grab && hovered_state.grabbable { if grab_start && hovered_state.grabbable {
update_focus( update_focus(app, hovered.config.input_focus);
&mut app.hid_provider.keyboard_focus, start_grab(StartGrabParams {
hovered.config.keyboard_focus,
);
start_grab(
idx, idx,
hit.overlay, id: hit.overlay,
hovered.config.name.clone(), name: hovered.config.name.clone(),
hovered.config.editing, editing: hovered.config.editing,
hovered_state, state: hovered_state,
app, app,
edit_mode, edit_mode,
); grab_float,
});
log::debug!("Hand {}: grabbed {}", hit.pointer, hovered.config.name); log::debug!("Hand {}: grabbed {}", hit.pointer, hovered.config.name);
return ( return (
Some((hit, raw_hit)), Some((hit, raw_hit)),
@ -567,10 +601,10 @@ where
let pointer = &mut app.input_state.pointers[hit.pointer]; let pointer = &mut app.input_state.pointers[hit.pointer];
if pointer.now.click && !pointer.before.click { if pointer.now.click && !pointer.before.click {
pointer.interaction.clicked_id = Some(hit.overlay); pointer.interaction.clicked_id = Some(hit.overlay);
update_focus( if hovered.config.category == OverlayCategory::Keyboard {
&mut app.hid_provider.keyboard_focus, pointer.interaction.kbd_block_activated = true;
hovered.config.keyboard_focus, }
); update_focus(app, hovered.config.input_focus);
hovered.config.backend.on_pointer(app, &hit, true); hovered.config.backend.on_pointer(app, &hit, true);
} else if !pointer.now.click && pointer.before.click { } else if !pointer.now.click && pointer.before.click {
// send release event to overlay that was originally clicked // send release event to overlay that was originally clicked
@ -606,6 +640,7 @@ fn handle_no_hit<O>(
let pointer = &mut app.input_state.pointers[pointer_idx]; let pointer = &mut app.input_state.pointers[pointer_idx];
pointer.interaction.should_block_input = false; pointer.interaction.should_block_input = false;
pointer.interaction.should_block_poses = false; pointer.interaction.should_block_poses = false;
pointer.interaction.kbd_block_activated = false;
// in case click released while not aiming at anything // in case click released while not aiming at anything
// send release event to overlay that was originally clicked // send release event to overlay that was originally clicked
@ -631,8 +666,10 @@ fn handle_scroll<O>(hit: &PointerHit, hovered: &mut OverlayWindowData<O>, app: &
} }
let config = &app.session.config; let config = &app.session.config;
let scroll_factor = 90.0 * app.delta_time;
let scroll_x = pointer.now.scroll_x let scroll_x = pointer.now.scroll_x
* scroll_factor
* config.scroll_speed * config.scroll_speed
* if config.invert_scroll_direction_x { * if config.invert_scroll_direction_x {
-1.0 -1.0
@ -640,6 +677,7 @@ fn handle_scroll<O>(hit: &PointerHit, hovered: &mut OverlayWindowData<O>, app: &
1.0 1.0
}; };
let scroll_y = pointer.now.scroll_y let scroll_y = pointer.now.scroll_y
* scroll_factor
* config.scroll_speed * config.scroll_speed
* if config.invert_scroll_direction_x { * if config.invert_scroll_direction_x {
-1.0 -1.0
@ -734,10 +772,8 @@ where
continue; continue;
}; };
if uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0 { if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) && !overlay.config.resizing {
if !overlay.config.resizing { continue;
continue;
}
} }
let pointer_hit = PointerHit { let pointer_hit = PointerHit {
@ -757,23 +793,31 @@ where
(None, None) (None, None)
} }
fn start_grab( struct StartGrabParams<'a> {
idx: usize, idx: usize,
id: OverlayID, id: OverlayID,
name: Arc<str>, name: Arc<str>,
editing: bool, editing: bool,
state: &mut OverlayWindowState, state: &'a mut OverlayWindowState,
app: &mut AppState, app: &'a mut AppState,
edit_mode: bool, edit_mode: bool,
) { grab_float: bool,
let pointer = &mut app.input_state.pointers[idx]; }
fn start_grab(par: StartGrabParams) {
let (app, id, state) = (par.app, par.id, par.state);
let pointer = &mut app.input_state.pointers[par.idx];
// Grab anchor if: // Grab anchor if:
// - grabbed overlay is Anchored // - grabbed overlay is Anchored
// - not in editmode // - not in editmode
// - not using grab_float
// - grabbing with one hand. (grabbing with the 2nd hand will grab the individual overlay instead) // - grabbing with one hand. (grabbing with the 2nd hand will grab the individual overlay instead)
let grab_anchor = let grab_anchor = !par.edit_mode
!edit_mode && !app.anchor_grabbed && matches!(state.positioning, Positioning::Anchored); && !par.grab_float
&& !app.anchor_grabbed
&& matches!(state.positioning, Positioning::Anchored);
let relative_grab_transform = if grab_anchor { let relative_grab_transform = if grab_anchor {
app.anchor app.anchor
@ -795,11 +839,18 @@ fn start_grab(
OverlaySelector::Id(id), OverlaySelector::Id(id),
Box::new({ Box::new({
let pos = state.positioning; let pos = state.positioning;
let name = name.clone(); let name = par.name.clone();
move |app, o| { move |app, o| {
let _ = o let _ = o
.backend .backend
.notify(app, OverlayEventData::OverlayGrabbed { name, pos, editing }) .notify(
app,
OverlayEventData::OverlayGrabbed {
name,
pos,
editing: par.editing,
},
)
.inspect_err(|e| log::warn!("Error during Notify OverlayGrabbed: {e:?}")); .inspect_err(|e| log::warn!("Error during Notify OverlayGrabbed: {e:?}"));
} }
}), }),
@ -809,7 +860,7 @@ fn start_grab(
app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify( app.tasks.enqueue(TaskType::Overlay(OverlayTask::Modify(
OverlaySelector::Name(ANCHOR_NAME.clone()), OverlaySelector::Name(ANCHOR_NAME.clone()),
Box::new(|app, o| { Box::new(|app, o| {
o.activate(app); o.activate(app, true);
}), }),
))); )));
@ -823,15 +874,19 @@ fn start_grab(
Box::new(move |app, o| { Box::new(move |app, o| {
let _ = o let _ = o
.backend .backend
.notify(app, OverlayEventData::OverlayGrabbed { name, pos, editing }) .notify(
app,
OverlayEventData::OverlayGrabbed {
name: par.name,
pos,
editing: par.editing,
},
)
.inspect_err(|e| log::warn!("Error during Notify OverlayGrabbed: {e:?}")); .inspect_err(|e| log::warn!("Error during Notify OverlayGrabbed: {e:?}"));
o.default_state.positioning = Positioning::FollowHand { o.default_state.positioning = Positioning::FollowHand { hand, lerp: 0.1 };
hand, o.default_state.align_to_hmd = true;
lerp: 0.1, o.activate(app, true);
align_to_hmd: true,
};
o.activate(app);
}), }),
))); )));
} }
@ -870,16 +925,25 @@ where
return; return;
}; };
let scroll_factor = 90.0 * app.delta_time;
if grab_anchor { if grab_anchor {
if pointer.now.click { if pointer.now.click {
pointer.interaction.mode = PointerMode::Special; pointer.interaction.mode = PointerMode::Special;
let grab_dist = grab_data.offset.translation.length().clamp(0.5, 5.0) * 0.2 + 0.4; let grab_dist = grab_data.offset.translation.length().clamp(0.5, 5.0) * 0.2 + 0.4;
handle_scale(&mut app.anchor, pointer.now.scroll_y * grab_dist); handle_scale(
handle_scale(&mut grab_data.offset, pointer.now.scroll_y * grab_dist); &mut app.anchor,
pointer.now.scroll_y * grab_dist * scroll_factor,
);
handle_scale(
&mut grab_data.offset,
pointer.now.scroll_y * grab_dist * scroll_factor,
);
} else if app.session.config.allow_sliding && pointer.now.scroll_y.is_finite() { } else if app.session.config.allow_sliding && pointer.now.scroll_y.is_finite() {
// single grab push/pull // single grab push/pull
let grab_dist = grab_data.offset.translation.length().clamp(0.5, 5.0); let grab_dist = grab_data.offset.translation.length().clamp(0.5, 5.0);
grab_data.offset.translation.z -= pointer.now.scroll_y * 0.02 * grab_dist; grab_data.offset.translation.z -=
pointer.now.scroll_y * scroll_factor * 0.02 * grab_dist;
grab_data.offset.translation.z = grab_data.offset.translation.z.min(-0.05); grab_data.offset.translation.z = grab_data.offset.translation.z.min(-0.05);
} }
if pointer.now.click_modifier_right { if pointer.now.click_modifier_right {
@ -902,13 +966,17 @@ where
let grab_dist = grab_data.offset.translation.length().clamp(0.5, 5.0) * 0.2 + 0.4; let grab_dist = grab_data.offset.translation.length().clamp(0.5, 5.0) * 0.2 + 0.4;
handle_scale( handle_scale(
&mut overlay_state.transform, &mut overlay_state.transform,
pointer.now.scroll_y * grab_dist, pointer.now.scroll_y * grab_dist * scroll_factor,
);
handle_scale(
&mut grab_data.offset,
pointer.now.scroll_y * grab_dist * scroll_factor,
); );
handle_scale(&mut grab_data.offset, pointer.now.scroll_y * grab_dist);
} else if app.session.config.allow_sliding && pointer.now.scroll_y.is_finite() { } else if app.session.config.allow_sliding && pointer.now.scroll_y.is_finite() {
// single grab push/pull // single grab push/pull
let grab_dist = grab_data.offset.translation.length().clamp(0.5, 5.0); let grab_dist = grab_data.offset.translation.length().clamp(0.5, 5.0);
grab_data.offset.translation.z -= pointer.now.scroll_y * 0.02 * grab_dist; grab_data.offset.translation.z -=
pointer.now.scroll_y * scroll_factor * 0.02 * grab_dist;
grab_data.offset.translation.z = grab_data.offset.translation.z.min(-0.05); grab_data.offset.translation.z = grab_data.offset.translation.z.min(-0.05);
} }
if pointer.now.click_modifier_right { if pointer.now.click_modifier_right {
@ -937,30 +1005,22 @@ where
if &*overlay.config.name == WATCH_NAME { if &*overlay.config.name == WATCH_NAME {
// watch special: when dropped, follow the hand that wasn't grabbing // watch special: when dropped, follow the hand that wasn't grabbing
if let Some(overlay_state) = overlay.config.active_state.as_mut() { if let Some(overlay_state) = overlay.config.active_state.as_mut() {
let align_to_hmd = overlay_state.align_to_hmd;
overlay_state.positioning = match overlay_state.positioning { overlay_state.positioning = match overlay_state.positioning {
Positioning::FollowHand { Positioning::FollowHand { hand, lerp } => match pointer.hand() {
hand,
lerp,
align_to_hmd,
} => match pointer.hand() {
Some(LeftRight::Left) => Positioning::FollowHand { Some(LeftRight::Left) => Positioning::FollowHand {
hand: LeftRight::Right, hand: LeftRight::Right,
lerp, lerp,
align_to_hmd,
}, },
Some(LeftRight::Right) => Positioning::FollowHand { Some(LeftRight::Right) => Positioning::FollowHand {
hand: LeftRight::Left, hand: LeftRight::Left,
lerp, lerp,
align_to_hmd,
},
_ => Positioning::FollowHand {
hand,
lerp,
align_to_hmd,
}, },
_ => Positioning::FollowHand { hand, lerp },
}, },
x => x, x => x,
}; };
overlay_state.align_to_hmd = align_to_hmd;
} }
} else if overlay.config.global } else if overlay.config.global
&& let Some(active_state) = overlay.config.active_state.as_ref() && let Some(active_state) = overlay.config.active_state.as_ref()

View File

@ -14,12 +14,8 @@ pub mod set;
pub mod task; pub mod task;
use thiserror::Error; use thiserror::Error;
use wgui::globals::WguiGlobals;
#[derive(Clone, Copy)] use wlx_common::config::GeneralConfig;
pub enum XrBackend {
OpenXR,
OpenVR,
}
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum BackendError { pub enum BackendError {
@ -37,3 +33,8 @@ pub enum BackendError {
#[error("Fatal: {0:?}")] #[error("Fatal: {0:?}")]
Fatal(#[from] anyhow::Error), Fatal(#[from] anyhow::Error),
} }
pub struct RunParams {
pub wgui_globals: WguiGlobals,
pub config: GeneralConfig,
}

View File

@ -12,12 +12,13 @@ use ovr_overlay::{
}; };
use smallvec::smallvec; use smallvec::smallvec;
use vulkano::{Handle, VulkanObject, device::physical::PhysicalDevice}; use vulkano::{Handle, VulkanObject, device::physical::PhysicalDevice};
use wlx_common::overlays::ToastTopic; use wgui::i18n::Translation;
use wlx_common::{dash_interface::InterfaceFeats, overlays::ToastTopic};
use crate::{ use crate::{
Args, FRAME_COUNTER, RUNNING, Args, FRAME_COUNTER, RUNNING, XrBackend,
backend::{ backend::{
BackendError, XrBackend, BackendError, RunParams,
input::interact, input::interact,
openvr::{ openvr::{
helpers::adjust_gain, helpers::adjust_gain,
@ -57,7 +58,7 @@ pub fn openvr_uninstall() {
} }
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)] #[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn openvr_run(args: &Args) -> Result<(), BackendError> { pub fn openvr_run(args: &Args, params: RunParams) -> Result<(), BackendError> {
let app_type = EVRApplicationType::VRApplication_Overlay; let app_type = EVRApplicationType::VRApplication_Overlay;
let Ok(context) = ovr_overlay::Context::init(app_type) else { let Ok(context) = ovr_overlay::Context::init(app_type) else {
if !args.wait { if !args.wait {
@ -87,9 +88,11 @@ pub fn openvr_run(args: &Args) -> Result<(), BackendError> {
names.iter().map(std::string::String::as_str).collect() names.iter().map(std::string::String::as_str).collect()
}; };
let feats = InterfaceFeats::default_for_backend(XrBackend::OpenVR);
let mut app = { let mut app = {
let (gfx, gfx_extras) = init_openvr_graphics(instance_extensions, device_extensions_fn)?; let (gfx, gfx_extras) = init_openvr_graphics(instance_extensions, device_extensions_fn)?;
AppState::from_graphics(gfx, gfx_extras, XrBackend::OpenVR)? AppState::from_graphics(gfx, gfx_extras, feats, params)?
}; };
app.session.no_autostart = args.no_autostart; app.session.no_autostart = args.no_autostart;
@ -193,8 +196,8 @@ pub fn openvr_run(args: &Args) -> Result<(), BackendError> {
log::info!("IPD: {:.1} mm -> {:.1} mm", app.input_state.ipd, ipd); log::info!("IPD: {:.1} mm -> {:.1} mm", app.input_state.ipd, ipd);
Toast::new( Toast::new(
ToastTopic::IpdChange, ToastTopic::IpdChange,
"IPD".into(), Some(Translation::from_raw_text("IPD")),
format!("{ipd:.1} mm"), Translation::from_raw_text_string(format!("{ipd:.1} mm")),
) )
.submit(&mut app); .submit(&mut app);
} }
@ -219,6 +222,9 @@ pub fn openvr_run(args: &Args) -> Result<(), BackendError> {
while let Some(task) = due_tasks.pop_front() { while let Some(task) = due_tasks.pop_front() {
match task { match task {
TaskType::Global(task) => {
task(&mut app);
}
TaskType::Input(task) => { TaskType::Input(task) => {
app.input_state.handle_task(task); app.input_state.handle_task(task);
} }
@ -226,7 +232,7 @@ pub fn openvr_run(args: &Args) -> Result<(), BackendError> {
overlays.handle_task(&mut app, task)?; overlays.handle_task(&mut app, task)?;
} }
TaskType::Playspace(task) => { TaskType::Playspace(task) => {
playspace.handle_task(&app, &mut chaperone_mgr, task); playspace.handle_task(&mut app, &mut chaperone_mgr, &mut overlays, task);
} }
TaskType::OpenVR(task) => match task { TaskType::OpenVR(task) => match task {
OpenVrTask::ColorGain(channel, value) => { OpenVrTask::ColorGain(channel, value) => {
@ -276,7 +282,7 @@ pub fn openvr_run(args: &Args) -> Result<(), BackendError> {
overlays.values_mut().for_each(|o| o.config.tick(&mut app)); overlays.values_mut().for_each(|o| o.config.tick(&mut app));
playspace.update(&mut chaperone_mgr, &mut overlays, &app); playspace.update(&mut chaperone_mgr, &mut overlays, &mut app);
current_lines.clear(); current_lines.clear();

View File

@ -35,7 +35,7 @@ impl OverlayWindowData<OpenVrOverlayData> {
app: &mut AppState, app: &mut AppState,
) -> anyhow::Result<OverlayHandle> { ) -> anyhow::Result<OverlayHandle> {
let key = format!("wlx-{}", self.config.name); let key = format!("wlx-{}", self.config.name);
log::debug!("Create overlay with key: {}", &key); log::debug!("Create overlay with key: {key}");
let handle = match overlay.create_overlay(&key, &key) { let handle = match overlay.create_overlay(&key, &key) {
Ok(handle) => handle, Ok(handle) => handle,
Err(e) => { Err(e) => {

View File

@ -4,10 +4,11 @@ use ovr_overlay::{
compositor::CompositorManager, compositor::CompositorManager,
sys::{EChaperoneConfigFile, ETrackingUniverseOrigin, HmdMatrix34_t}, sys::{EChaperoneConfigFile, ETrackingUniverseOrigin, HmdMatrix34_t},
}; };
use wgui::log::LogErr;
use crate::{ use crate::{
backend::{input::InputState, playspace_common, task::PlayspaceTask}, backend::{playspace_common, task::PlayspaceTask},
state::AppState, state::{AppState, PlayspaceState, load_playspace_state, save_playspace_state},
windowing::manager::OverlayWindowManager, windowing::manager::OverlayWindowManager,
}; };
@ -23,32 +24,41 @@ pub(super) struct PlayspaceMover {
universe: ETrackingUniverseOrigin, universe: ETrackingUniverseOrigin,
drag: Option<MoverData<Vec3A>>, drag: Option<MoverData<Vec3A>>,
rotate: Option<MoverData<Quat>>, rotate: Option<MoverData<Quat>>,
playspace_state: PlayspaceState,
} }
impl PlayspaceMover { impl PlayspaceMover {
pub const fn new() -> Self { pub fn new() -> Self {
Self { Self {
universe: ETrackingUniverseOrigin::TrackingUniverseRawAndUncalibrated, universe: ETrackingUniverseOrigin::TrackingUniverseRawAndUncalibrated,
drag: None, drag: None,
rotate: None, rotate: None,
playspace_state: load_playspace_state().unwrap_or_default(),
} }
} }
pub fn handle_task( pub fn handle_task(
&mut self, &mut self,
app: &AppState, app: &mut AppState,
chaperone_mgr: &mut ChaperoneSetupManager, chaperone_mgr: &mut ChaperoneSetupManager,
overlays: &mut OverlayWindowManager<OpenVrOverlayData>,
task: PlayspaceTask, task: PlayspaceTask,
) { ) {
match task { match task {
PlayspaceTask::FixFloor => { PlayspaceTask::FixFloor => {
self.fix_floor(chaperone_mgr, &app.input_state); self.fix_floor(chaperone_mgr, app, overlays);
} }
PlayspaceTask::Reset => { PlayspaceTask::Reset => {
self.reset_offset(chaperone_mgr, &app.input_state); self.reset_offset(chaperone_mgr, app, overlays);
} }
PlayspaceTask::Recenter => { PlayspaceTask::Recenter => {
self.recenter(chaperone_mgr, &app.input_state); self.recenter(chaperone_mgr, app, overlays);
}
PlayspaceTask::SaveCenter => {
self.save_center(chaperone_mgr);
}
PlayspaceTask::ResetCenter => {
self.playspace_state.openvr_space_center = Affine3A::IDENTITY;
} }
} }
} }
@ -58,7 +68,7 @@ impl PlayspaceMover {
&mut self, &mut self,
chaperone_mgr: &mut ChaperoneSetupManager, chaperone_mgr: &mut ChaperoneSetupManager,
overlays: &mut OverlayWindowManager<OpenVrOverlayData>, overlays: &mut OverlayWindowManager<OpenVrOverlayData>,
app: &AppState, app: &mut AppState,
) { ) {
let universe = self.universe.clone(); let universe = self.universe.clone();
@ -85,7 +95,11 @@ impl PlayspaceMover {
* -1.0; * -1.0;
space_transform.translation = offset; space_transform.translation = offset;
let before_pose = data.pose;
data.pose *= space_transform; data.pose *= space_transform;
if !app.session.config.space_drag_affects_world {
playspace_common::shift_world(overlays, &mut app.anchor, &before_pose, &data.pose);
}
data.hand_pose = new_hand; data.hand_pose = new_hand;
if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding { if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding {
@ -137,9 +151,11 @@ impl PlayspaceMover {
} }
let overlay_offset = data.pose.inverse().transform_vector3a(relative_pos) * -1.0; let overlay_offset = data.pose.inverse().transform_vector3a(relative_pos) * -1.0;
playspace_common::shift_overlays(overlays, overlay_offset); let before_pose = data.pose;
data.pose.translation += relative_pos; data.pose.translation += relative_pos;
if !app.session.config.space_drag_affects_world {
playspace_common::shift_world(overlays, &mut app.anchor, &before_pose, &data.pose);
}
data.hand_pose = new_hand; data.hand_pose = new_hand;
if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding { if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding {
@ -169,31 +185,36 @@ impl PlayspaceMover {
for pointer in &app.input_state.pointers { for pointer in &app.input_state.pointers {
if pointer.now.space_reset && !pointer.before.space_reset { if pointer.now.space_reset && !pointer.before.space_reset {
self.reset_offset(chaperone_mgr, &app.input_state); self.reset_offset(chaperone_mgr, app, overlays);
log::info!("Space reset"); log::info!("Space reset");
return; return;
} }
} }
} }
pub fn reset_offset(&mut self, chaperone_mgr: &mut ChaperoneSetupManager, input: &InputState) { pub fn reset_offset(
let mut height = 1.6; &mut self,
if let Some(mat) = get_working_copy(&self.universe, chaperone_mgr) { chaperone_mgr: &mut ChaperoneSetupManager,
height = input.hmd.translation.y - mat.translation.y; app: &mut AppState,
if self.universe == ETrackingUniverseOrigin::TrackingUniverseStanding { overlays: &mut OverlayWindowManager<OpenVrOverlayData>,
apply_chaperone_transform(mat, chaperone_mgr); ) {
} let Some(before) = get_working_copy(&self.universe, chaperone_mgr) else {
} log::warn!("Can't reset offset - failed to get zero pose");
return;
let xform = if self.universe == ETrackingUniverseOrigin::TrackingUniverseSeated {
Affine3A::from_translation(Vec3::NEG_Y * height)
} else {
Affine3A::IDENTITY
}; };
let mut xform = self.playspace_state.openvr_space_center;
if self.universe == ETrackingUniverseOrigin::TrackingUniverseSeated {
xform.translation.y -= 1.7;
}
set_working_copy(&self.universe, chaperone_mgr, &xform); set_working_copy(&self.universe, chaperone_mgr, &xform);
chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live); chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live);
if !app.session.config.space_drag_affects_world {
playspace_common::shift_world(overlays, &mut app.anchor, &before, &xform);
}
if self.drag.is_some() { if self.drag.is_some() {
log::info!("Space drag interrupted by manual reset"); log::info!("Space drag interrupted by manual reset");
self.drag = None; self.drag = None;
@ -204,7 +225,14 @@ impl PlayspaceMover {
} }
} }
pub fn fix_floor(&mut self, chaperone_mgr: &mut ChaperoneSetupManager, input: &InputState) { pub fn fix_floor(
&mut self,
chaperone_mgr: &mut ChaperoneSetupManager,
app: &mut AppState,
overlays: &mut OverlayWindowManager<OpenVrOverlayData>,
) {
let input = &app.input_state;
let anchor = &mut app.anchor;
let y1 = input.pointers[0].pose.translation.y; let y1 = input.pointers[0].pose.translation.y;
let y2 = input.pointers[1].pose.translation.y; let y2 = input.pointers[1].pose.translation.y;
let Some(mut mat) = get_working_copy(&self.universe, chaperone_mgr) else { let Some(mut mat) = get_working_copy(&self.universe, chaperone_mgr) else {
@ -212,11 +240,17 @@ impl PlayspaceMover {
return; return;
}; };
let offset = y1.min(y2) - 0.03; let offset = y1.min(y2) - 0.03;
let before = mat;
mat.translation.y += offset; mat.translation.y += offset;
self.playspace_state.openvr_space_center.translation.y = mat.translation.y;
set_working_copy(&self.universe, chaperone_mgr, &mat); set_working_copy(&self.universe, chaperone_mgr, &mat);
chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live); chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live);
if !app.session.config.space_drag_affects_world {
playspace_common::shift_world(overlays, anchor, &before, &mat);
}
if self.drag.is_some() { if self.drag.is_some() {
log::info!("Space drag interrupted by fix floor"); log::info!("Space drag interrupted by fix floor");
self.drag = None; self.drag = None;
@ -227,18 +261,12 @@ impl PlayspaceMover {
} }
} }
pub fn recenter(&mut self, chaperone_mgr: &mut ChaperoneSetupManager, input: &InputState) { pub fn recenter(
let Some(mut mat) = get_working_copy(&self.universe, chaperone_mgr) else { &mut self,
log::warn!("Can't recenter - failed to get zero pose"); chaperone_mgr: &mut ChaperoneSetupManager,
return; app: &mut AppState,
}; overlays: &mut OverlayWindowManager<OpenVrOverlayData>,
) {
mat.translation.x += input.hmd.translation.x;
mat.translation.z += input.hmd.translation.z;
set_working_copy(&self.universe, chaperone_mgr, &mat);
chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live);
if self.drag.is_some() { if self.drag.is_some() {
log::info!("Space drag interrupted by recenter"); log::info!("Space drag interrupted by recenter");
self.drag = None; self.drag = None;
@ -247,6 +275,54 @@ impl PlayspaceMover {
log::info!("Space rotate interrupted by recenter"); log::info!("Space rotate interrupted by recenter");
self.rotate = None; self.rotate = None;
} }
let input = &app.input_state;
let anchor = &mut app.anchor;
let Some(mat) = get_working_copy(&self.universe, chaperone_mgr) else {
log::warn!("Can't recenter - failed to get zero pose");
return;
};
let before = mat;
let cur_rot: Quat = Quat::from_affine3(&mat);
let cur_pos: Vec3 = Vec3::from(mat.translation);
let mut stage_offset = Affine3A::from_rotation_translation(cur_rot, cur_pos);
let horiz_hmd_pos = Vec3::new(input.hmd.translation.x, 0.0, input.hmd.translation.z);
let fwd = input.hmd.transform_vector3a(Vec3A::NEG_Z);
let horiz_len_sq = fwd.x.mul_add(fwd.x, fwd.z * fwd.z);
let hmd_yaw = if horiz_len_sq > f32::EPSILON {
let yaw = (-fwd.x).atan2(-fwd.z);
Quat::from_rotation_y(yaw)
} else {
Quat::IDENTITY
};
let recenter_offset = Affine3A::from_rotation_translation(hmd_yaw, horiz_hmd_pos);
stage_offset *= recenter_offset;
let (_, new_rot, new_pos) = stage_offset.to_scale_rotation_translation();
let new_mat = if horiz_len_sq > f32::EPSILON {
Affine3A::from_rotation_translation(new_rot, new_pos)
} else {
let mut m = mat;
m.translation = new_pos.into();
m
};
set_working_copy(&self.universe, chaperone_mgr, &new_mat);
chaperone_mgr.commit_working_copy(EChaperoneConfigFile::EChaperoneConfigFile_Live);
if !app.session.config.space_drag_affects_world {
playspace_common::shift_world(overlays, anchor, &before, &new_mat);
}
} }
pub fn playspace_changed( pub fn playspace_changed(
@ -277,6 +353,26 @@ impl PlayspaceMover {
pub fn get_universe(&self) -> ETrackingUniverseOrigin { pub fn get_universe(&self) -> ETrackingUniverseOrigin {
self.universe.clone() self.universe.clone()
} }
pub fn save_center(&mut self, chaperone_mgr: &mut ChaperoneSetupManager) {
if self.drag.is_some() {
log::info!("Space drag interrupted by save center");
self.drag = None;
}
if self.rotate.is_some() {
log::info!("Space rotate interrupted by save center");
self.rotate = None;
}
let Some(mat) = get_working_copy(&self.universe, chaperone_mgr) else {
log::warn!("Can't save center - failed to get zero pose");
return;
};
self.playspace_state.openvr_space_center = mat;
let _ =
save_playspace_state(&self.playspace_state).log_err("Could not save playspace state");
}
} }
const fn universe_str(universe: &ETrackingUniverseOrigin) -> &'static str { const fn universe_str(universe: &ETrackingUniverseOrigin) -> &'static str {

View File

@ -1,3 +1,5 @@
use std::ffi::CStr;
use anyhow::{bail, ensure}; use anyhow::{bail, ensure};
use glam::{Affine3A, Quat, Vec3, Vec3A}; use glam::{Affine3A, Quat, Vec3, Vec3A};
use openxr::{self as xr, SessionCreateFlags, Version, sys::Handle}; use openxr::{self as xr, SessionCreateFlags, Version, sys::Handle};
@ -41,6 +43,12 @@ pub(super) fn init_xr() -> Result<(xr::Instance, xr::SystemId), anyhow::Error> {
} else { } else {
log::warn!("Missing EXT_dpad_binding extension."); log::warn!("Missing EXT_dpad_binding extension.");
} }
if available_extensions.fb_composition_layer_alpha_blend {
enabled_extensions.fb_composition_layer_alpha_blend = true;
} else {
log::warn!("Missing XR_FB_composition_layer_alpha_blend extension.");
}
if available_extensions.ext_samsung_odyssey_controller { if available_extensions.ext_samsung_odyssey_controller {
enabled_extensions.ext_samsung_odyssey_controller = true; enabled_extensions.ext_samsung_odyssey_controller = true;
} else { } else {
@ -77,12 +85,17 @@ pub(super) fn init_xr() -> Result<(xr::Instance, xr::SystemId), anyhow::Error> {
log::warn!("Missing XR_KHR_composition_layer_color_scale_bias extension."); log::warn!("Missing XR_KHR_composition_layer_color_scale_bias extension.");
} }
let xr_extension = b"XR_MNDX_system_buttons".to_vec(); let xr_extension = b"XR_MNDX_system_buttons\0".to_vec();
if available_extensions.other.contains(&xr_extension) { if available_extensions.other.contains(&xr_extension) {
enabled_extensions.other.push(xr_extension); enabled_extensions.other.push(xr_extension);
} }
let xr_extension = b"XR_VALVE_frame_controller_interaction".to_vec(); let xr_extension = b"XR_VALVE_frame_controller_interaction\0".to_vec();
if available_extensions.other.contains(&xr_extension) {
enabled_extensions.other.push(xr_extension);
}
let xr_extension: Vec<u8> = b"XR_MND_contactglove2_interaction\0".to_vec();
if available_extensions.other.contains(&xr_extension) { if available_extensions.other.contains(&xr_extension) {
enabled_extensions.other.push(xr_extension); enabled_extensions.other.push(xr_extension);
} }
@ -118,6 +131,22 @@ pub(super) fn init_xr() -> Result<(xr::Instance, xr::SystemId), anyhow::Error> {
instance_props.runtime_version instance_props.runtime_version
); );
let enabled_extensions = enabled_extensions
.names()
.into_iter()
.filter_map(|name| {
Some(
CStr::from_bytes_with_nul(name)
.ok()?
.to_string_lossy()
.into_owned(),
)
})
.collect::<Vec<_>>()
.join("\n");
log::info!("OpenXR extensions:\n{enabled_extensions}");
let Ok(system) = xr_instance.system(xr::FormFactor::HEAD_MOUNTED_DISPLAY) else { let Ok(system) = xr_instance.system(xr::FormFactor::HEAD_MOUNTED_DISPLAY) else {
bail!("Failed to access OpenXR HMD system."); bail!("Failed to access OpenXR HMD system.");
}; };

View File

@ -4,7 +4,7 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use glam::{Affine3A, Quat, Vec3, bool}; use glam::{Affine3A, FloatExt, Quat, Vec3, bool};
use libmonado::{self as mnd, DeviceLogic}; use libmonado::{self as mnd, DeviceLogic};
use openxr::{self as xr, Quaternionf, Vector2f, Vector3f}; use openxr::{self as xr, Quaternionf, Vector2f, Vector3f};
use wlx_common::{ use wlx_common::{
@ -51,7 +51,7 @@ pub struct MultiClickHandler<const COUNT: usize> {
impl<const COUNT: usize> MultiClickHandler<COUNT> { impl<const COUNT: usize> MultiClickHandler<COUNT> {
fn new(action_set: &xr::ActionSet, action_name: &str, side: &str) -> anyhow::Result<Self> { fn new(action_set: &xr::ActionSet, action_name: &str, side: &str) -> anyhow::Result<Self> {
let name = format!("{side}_{COUNT}-{action_name}"); let name = format!("{side}_{COUNT}-{action_name}");
let name_f32 = format!("{}_value", &name); let name_f32 = format!("{name}_value");
let action_bool = action_set.create_action::<bool>(&name, &name, &[])?; let action_bool = action_set.create_action::<bool>(&name, &name, &[])?;
let action_f32 = action_set.create_action::<f32>(&name_f32, &name_f32, &[])?; let action_f32 = action_set.create_action::<f32>(&name_f32, &name_f32, &[])?;
@ -135,7 +135,7 @@ impl CustomClickAction {
}) })
} }
pub fn set_threshold(&mut self, threshold: [f32; 2]) { pub const fn set_threshold(&mut self, threshold: [f32; 2]) {
self.threshold = threshold; self.threshold = threshold;
} }
@ -211,7 +211,7 @@ impl OpenXrInputSource {
); );
} }
pub fn update(&mut self, xr: &XrState, state: &mut AppState) -> anyhow::Result<()> { pub fn update(&mut self, xr: &XrState, app: &mut AppState) -> anyhow::Result<()> {
xr.session.sync_actions(&[(&self.action_set).into()])?; xr.session.sync_actions(&[(&self.action_set).into()])?;
let loc = xr.view.locate(&xr.stage, xr.predicted_display_time)?; let loc = xr.view.locate(&xr.stage, xr.predicted_display_time)?;
@ -221,7 +221,7 @@ impl OpenXrInputSource {
.location_flags .location_flags
.contains(xr::SpaceLocationFlags::ORIENTATION_VALID) .contains(xr::SpaceLocationFlags::ORIENTATION_VALID)
{ {
state.input_state.hmd.matrix3 = hmd.matrix3; app.input_state.hmd.matrix3 = hmd.matrix3;
} else { } else {
hmd_tracked = false; hmd_tracked = false;
} }
@ -230,26 +230,46 @@ impl OpenXrInputSource {
.location_flags .location_flags
.contains(xr::SpaceLocationFlags::POSITION_VALID) .contains(xr::SpaceLocationFlags::POSITION_VALID)
{ {
state.input_state.hmd.translation = hmd.translation; app.input_state.hmd.translation = hmd.translation;
} else { } else {
hmd_tracked = false; hmd_tracked = false;
} }
let mut any_tracked = false; let mut any_tracked = false;
for i in 0..2 { let old_handsfree = app.session.config.handsfree_pointer;
let pointer = &mut state.input_state.pointers[i];
self.pointers[i].update(pointer, xr, &state.session)?; if app.input_state.picking_focus.is_none() {
any_tracked |= pointer.tracked; let should_disable_lerp = app.input_state.should_disable_lerp();
for i in 0..2 {
let pointer = &mut app.input_state.pointers[i];
self.pointers[i].update(pointer, xr, &app.session, !should_disable_lerp)?;
any_tracked |= pointer.tracked;
}
} else {
app.session.config.handsfree_pointer = app.session.config.handsfree_alt_tab.into();
app.input_state.handsfree_state.scroll_x =
app.input_state.handsfree_state.scroll_x.lerp(0.0, 0.7);
app.input_state.handsfree_state.scroll_y =
app.input_state.handsfree_state.scroll_y.lerp(0.0, 0.7);
let ptr1 = &mut app.input_state.pointers[1];
ptr1.before = ptr1.now;
ptr1.now = PointerState::default();
ptr1.tracked = false;
} }
if !any_tracked { if !any_tracked {
self.handsfree_pointer.update_handsfree( self.handsfree_pointer.update_handsfree(
&mut state.input_state.pointers[0], &mut app.input_state.pointers[0],
xr, xr,
&state.session, &app.session,
hmd, hmd,
hmd_tracked, hmd_tracked,
&state.input_state.handsfree_state, &app.input_state.handsfree_state,
)?; )?;
app.session.config.handsfree_pointer = old_handsfree;
} }
Ok(()) Ok(())
@ -374,7 +394,11 @@ impl OpenXrPointer {
} }
HandsfreePointer::EyeTracking | HandsfreePointer::EyeTrackingOnly => { HandsfreePointer::EyeTracking | HandsfreePointer::EyeTrackingOnly => {
// more aggressive smoothing for eye // more aggressive smoothing for eye
self.pointer_load_pose(pointer, xr, session.config.pointer_lerp_factor * 0.5)?; self.pointer_load_pose(
pointer,
xr,
Some(session.config.pointer_lerp_factor * 0.5),
)?;
} }
} }
@ -386,6 +410,7 @@ impl OpenXrPointer {
// input from wayvrctl // input from wayvrctl
pointer.now.click = handsfree_state.click; pointer.now.click = handsfree_state.click;
pointer.now.grab = handsfree_state.grab; pointer.now.grab = handsfree_state.grab;
pointer.now.grab_float = handsfree_state.grab_float;
pointer.now.click_modifier_right = handsfree_state.click_modifier_right; pointer.now.click_modifier_right = handsfree_state.click_modifier_right;
pointer.now.click_modifier_middle = handsfree_state.click_modifier_middle; pointer.now.click_modifier_middle = handsfree_state.click_modifier_middle;
pointer.now.scroll_y = handsfree_state.scroll_y; pointer.now.scroll_y = handsfree_state.scroll_y;
@ -407,9 +432,18 @@ impl OpenXrPointer {
pointer: &mut Pointer, pointer: &mut Pointer,
xr: &XrState, xr: &XrState,
session: &AppSession, session: &AppSession,
do_lerp: bool,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
pointer.handsfree = false; pointer.handsfree = false;
self.pointer_load_pose(pointer, xr, session.config.pointer_lerp_factor)?; self.pointer_load_pose(
pointer,
xr,
if do_lerp {
Some(session.config.pointer_lerp_factor)
} else {
None
},
)?;
self.pointer_load_actions(pointer, xr)?; self.pointer_load_actions(pointer, xr)?;
Ok(()) Ok(())
@ -419,7 +453,7 @@ impl OpenXrPointer {
&mut self, &mut self,
pointer: &mut Pointer, pointer: &mut Pointer,
xr: &XrState, xr: &XrState,
lerp_factor: f32, lerp_factor: Option<f32>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let location = self.space.locate(&xr.stage, xr.predicted_display_time)?; let location = self.space.locate(&xr.stage, xr.predicted_display_time)?;
if location if location
@ -434,12 +468,17 @@ impl OpenXrPointer {
transmute::<Vector3f, Vec3>(location.pose.position), transmute::<Vector3f, Vec3>(location.pose.position),
) )
}; };
let lerp_factor = (1.0 / (xr.fps / 100.0) * lerp_factor).clamp(0.1, 1.0);
pointer.raw_pose = Affine3A::from_rotation_translation(new_quat, new_pos); pointer.raw_pose = Affine3A::from_rotation_translation(new_quat, new_pos);
pointer.pose = Affine3A::from_rotation_translation( if let Some(lerp_factor) = lerp_factor {
cur_quat.lerp(new_quat, lerp_factor), let lerp_factor = (1.0 / (xr.fps / 100.0) * lerp_factor).clamp(0.1, 1.0);
cur_pos.lerp(new_pos.into(), lerp_factor).into(), pointer.pose = Affine3A::from_rotation_translation(
); cur_quat.lerp(new_quat, lerp_factor),
cur_pos.lerp(new_pos.into(), lerp_factor).into(),
);
} else {
pointer.pose = pointer.raw_pose; // no lerp
}
pointer.tracked = true; pointer.tracked = true;
} else { } else {
pointer.tracked = false; pointer.tracked = false;
@ -670,7 +709,7 @@ fn suggest_bindings(instance: &xr::Instance, hands: &mut [&mut OpenXrHandSource;
let profiles = load_xr_input_profiles(); let profiles = load_xr_input_profiles();
for profile in profiles { for profile in profiles {
log::debug!("Loading profile {}", &profile.profile); log::debug!("Loading profile {}", profile.profile);
let Ok(profile_path) = instance.string_to_path(&profile.profile) else { let Ok(profile_path) = instance.string_to_path(&profile.profile) else {
log::warn!("Profile not supported: {}", profile.profile); log::warn!("Profile not supported: {}", profile.profile);

View File

@ -10,12 +10,16 @@ use input::OpenXrInputSource;
use openxr as xr; use openxr as xr;
use skybox::{Skybox, create_skybox}; use skybox::{Skybox, create_skybox};
use vulkano::{Handle, VulkanObject}; use vulkano::{Handle, VulkanObject};
use wlx_common::overlays::{StereoMode, ToastTopic}; use wgui::i18n::Translation;
use wlx_common::{
dash_interface::InterfaceFeats,
overlays::{StereoMode, ToastTopic},
};
use crate::{ use crate::{
Args, FRAME_COUNTER, RUNNING, Args, FRAME_COUNTER, RUNNING, XrBackend,
backend::{ backend::{
BackendError, XrBackend, BackendError, RunParams,
input::interact, input::interact,
openxr::{helpers::try_apply_chroma_key, lines::LinePool, overlay::OpenXrOverlayData}, openxr::{helpers::try_apply_chroma_key, lines::LinePool, overlay::OpenXrOverlayData},
task::{OpenXrTask, OverlayTask, TaskType}, task::{OpenXrTask, OverlayTask, TaskType},
@ -52,7 +56,7 @@ struct XrState {
} }
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)] #[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
pub fn openxr_run(args: &Args) -> Result<(), BackendError> { pub fn openxr_run(args: &Args, params: RunParams) -> Result<(), BackendError> {
let (xr_instance, system) = match helpers::init_xr() { let (xr_instance, system) = match helpers::init_xr() {
Ok((xr_instance, system)) => (xr_instance, system), Ok((xr_instance, system)) => (xr_instance, system),
Err(e) => { Err(e) => {
@ -63,9 +67,17 @@ pub fn openxr_run(args: &Args) -> Result<(), BackendError> {
} }
}; };
let feats = InterfaceFeats {
passthru: xr_instance
.exts()
.fb_composition_layer_alpha_blend
.is_some(),
..InterfaceFeats::default_for_backend(XrBackend::OpenXR)
};
let mut app = { let mut app = {
let (gfx, gfx_extras) = init_openxr_graphics(xr_instance.clone(), system)?; let (gfx, gfx_extras) = init_openxr_graphics(xr_instance.clone(), system)?;
AppState::from_graphics(gfx, gfx_extras, XrBackend::OpenXR)? AppState::from_graphics(gfx, gfx_extras, feats, params)?
}; };
app.session.no_autostart = args.no_autostart; app.session.no_autostart = args.no_autostart;
@ -88,11 +100,7 @@ pub fn openxr_run(args: &Args) -> Result<(), BackendError> {
app.late_init(); app.late_init();
let mut playspace_mover = app.monado_state.as_mut().and_then(|m| { let mut playspace_mover = playspace::PlayspaceMover::new();
playspace::PlayspaceMover::new(&mut m.ipc)
.map_err(|e| log::warn!("Will not use Monado playspace mover: {e}"))
.ok()
});
let mut blocker = app let mut blocker = app
.monado_state .monado_state
@ -294,9 +302,7 @@ pub fn openxr_run(args: &Args) -> Result<(), BackendError> {
.enqueue(TaskType::Overlay(OverlayTask::ToggleDashboard)); .enqueue(TaskType::Overlay(OverlayTask::ToggleDashboard));
} }
if let Some(ref mut playspace_mover) = playspace_mover { playspace_mover.update(&mut overlays, &mut app);
playspace_mover.update(&mut overlays, &mut app);
}
for o in overlays.values_mut() { for o in overlays.values_mut() {
o.after_input(&mut app)?; o.after_input(&mut app)?;
@ -317,8 +323,12 @@ pub fn openxr_run(args: &Args) -> Result<(), BackendError> {
if (app.input_state.ipd - ipd).abs() > 0.05 { if (app.input_state.ipd - ipd).abs() > 0.05 {
log::info!("IPD changed: {} -> {}", app.input_state.ipd, ipd); log::info!("IPD changed: {} -> {}", app.input_state.ipd, ipd);
app.input_state.ipd = ipd; app.input_state.ipd = ipd;
Toast::new(ToastTopic::IpdChange, "IPD".into(), format!("{ipd:.1} mm")) Toast::new(
.submit(&mut app); ToastTopic::IpdChange,
Some(Translation::from_raw_text("IPD")),
Translation::from_raw_text_string(format!("{ipd:.1} mm")),
)
.submit(&mut app);
} }
overlays.values_mut().for_each(|o| o.config.tick(&mut app)); overlays.values_mut().for_each(|o| o.config.tick(&mut app));
@ -345,7 +355,7 @@ pub fn openxr_run(args: &Args) -> Result<(), BackendError> {
let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic let watch = overlays.mut_by_id(watch_id).unwrap(); // want panic
if watch.config.active_state.is_none() { if watch.config.active_state.is_none() {
watch.config.activate(&mut app); watch.config.activate(&mut app, true);
} }
let watch_state = watch.config.active_state.as_mut().unwrap(); let watch_state = watch.config.active_state.as_mut().unwrap();
let watch_transform = watch_state.transform; let watch_transform = watch_state.transform;
@ -473,6 +483,9 @@ pub fn openxr_run(args: &Args) -> Result<(), BackendError> {
app.tasks.retrieve_due(&mut due_tasks); app.tasks.retrieve_due(&mut due_tasks);
while let Some(task) = due_tasks.pop_front() { while let Some(task) = due_tasks.pop_front() {
match task { match task {
TaskType::Global(task) => {
task(&mut app);
}
TaskType::Input(task) => { TaskType::Input(task) => {
app.input_state.handle_task(task); app.input_state.handle_task(task);
} }
@ -480,9 +493,7 @@ pub fn openxr_run(args: &Args) -> Result<(), BackendError> {
overlays.handle_task(&mut app, task)?; overlays.handle_task(&mut app, task)?;
} }
TaskType::Playspace(task) => { TaskType::Playspace(task) => {
if let Some(playspace_mover) = playspace_mover.as_mut() { playspace_mover.handle_task(&mut app, &mut overlays, task);
playspace_mover.handle_task(&mut app, task);
}
} }
TaskType::OpenXR(task) => { TaskType::OpenXR(task) => {
if matches!(task, OpenXrTask::EnvironmentChanged) { if matches!(task, OpenXrTask::EnvironmentChanged) {

View File

@ -11,7 +11,7 @@ use crate::{
swapchain::{SwapchainOpts, WlxSwapchainImage, create_swapchain}, swapchain::{SwapchainOpts, WlxSwapchainImage, create_swapchain},
}, },
state::AppState, state::AppState,
windowing::window::OverlayWindowData, windowing::window::{OverlayCategory, OverlayWindowData},
}; };
#[derive(Default)] #[derive(Default)]
@ -21,6 +21,7 @@ pub struct OpenXrOverlayData {
pub(super) init: bool, pub(super) init: bool,
pub(super) cur_visible: bool, pub(super) cur_visible: bool,
color_bias_khr: Option<Box<xr::sys::CompositionLayerColorScaleBiasKHR>>, color_bias_khr: Option<Box<xr::sys::CompositionLayerColorScaleBiasKHR>>,
layer_alpha_blend_fb: Option<Box<xr::sys::CompositionLayerAlphaBlendFB>>,
} }
impl OverlayWindowData<OpenXrOverlayData> { impl OverlayWindowData<OpenXrOverlayData> {
@ -104,12 +105,34 @@ impl OverlayWindowData<OpenXrOverlayData> {
(major, major / aspect_ratio) (major, major / aspect_ratio)
}; };
let flags = if state.additive { let mut flags = CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA;
CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA
} else { if state.additive {
CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA flags |= CompositionLayerFlags::UNPREMULTIPLIED_ALPHA;
| CompositionLayerFlags::UNPREMULTIPLIED_ALPHA }
};
if xr
.instance
.exts()
.fb_composition_layer_alpha_blend
.is_some()
&& self.config.category == OverlayCategory::Passthru
&& self.data.layer_alpha_blend_fb.is_none()
&& !self.config.editing
{
self.data.layer_alpha_blend_fb =
Some(Box::new(openxr::sys::CompositionLayerAlphaBlendFB {
ty: xr::sys::CompositionLayerAlphaBlendFB::TYPE,
next: std::ptr::null_mut(),
src_factor_color: xr::BlendFactorFB::ZERO,
dst_factor_color: xr::BlendFactorFB::SRC_ALPHA,
src_factor_alpha: xr::BlendFactorFB::ONE,
dst_factor_alpha: xr::BlendFactorFB::ZERO,
}));
flags &= !CompositionLayerFlags::BLEND_TEXTURE_SOURCE_ALPHA;
} else if self.config.editing {
self.data.layer_alpha_blend_fb = None;
}
if let Some(curvature) = state.curvature { if let Some(curvature) = state.curvature {
let radius = scale_x / (2.0 * PI * curvature); let radius = scale_x / (2.0 * PI * curvature);
@ -132,6 +155,12 @@ impl OverlayWindowData<OpenXrOverlayData> {
.central_angle(angle) .central_angle(angle)
.aspect_ratio(aspect_ratio); .aspect_ratio(aspect_ratio);
if let Some(layer_alpha_blend_fb) = self.data.layer_alpha_blend_fb.as_mut() {
unsafe {
let raw = next_chain_insert!(cylinder, layer_alpha_blend_fb);
cylinder = xr::CompositionLayerCylinderKHR::from_raw(raw);
}
}
if let Some(color_bias_khr) = self.data.color_bias_khr.as_mut() { if let Some(color_bias_khr) = self.data.color_bias_khr.as_mut() {
unsafe { unsafe {
let raw = next_chain_insert!(cylinder, color_bias_khr); let raw = next_chain_insert!(cylinder, color_bias_khr);
@ -157,6 +186,12 @@ impl OverlayWindowData<OpenXrOverlayData> {
height: scale_y, height: scale_y,
}); });
if let Some(layer_alpha_blend_fb) = self.data.layer_alpha_blend_fb.as_mut() {
unsafe {
let raw = next_chain_insert!(quad, layer_alpha_blend_fb);
quad = xr::CompositionLayerQuad::from_raw(raw);
}
}
if let Some(color_bias_khr) = self.data.color_bias_khr.as_mut() { if let Some(color_bias_khr) = self.data.color_bias_khr.as_mut() {
unsafe { unsafe {
let raw = next_chain_insert!(quad, color_bias_khr); let raw = next_chain_insert!(quad, color_bias_khr);

View File

@ -1,14 +1,13 @@
use glam::{Affine3A, Quat, Vec3, Vec3A, vec3a}; use glam::{Affine3A, Quat, Vec3, Vec3A, vec3a};
use libmonado::{MndResult, Monado, Pose, ReferenceSpaceType}; use libmonado::{Monado, Pose, ReferenceSpaceType};
use wgui::log::LogErr; use wgui::log::LogErr;
use crate::{ use crate::{
backend::{ backend::{
input::InputState,
playspace_common::{self, SpaceGravity, SpaceGravityUpdateParams}, playspace_common::{self, SpaceGravity, SpaceGravityUpdateParams},
task::PlayspaceTask, task::PlayspaceTask,
}, },
state::AppState, state::{AppState, PlayspaceState, load_playspace_state, save_playspace_state},
windowing::manager::OverlayWindowManager, windowing::manager::OverlayWindowManager,
}; };
@ -24,41 +23,46 @@ pub(super) struct PlayspaceMover {
drag: Option<MoverData<Vec3A>>, drag: Option<MoverData<Vec3A>>,
rotate: Option<MoverData<Quat>>, rotate: Option<MoverData<Quat>>,
gravity: SpaceGravity, gravity: SpaceGravity,
floor_y: f32, playspace_state: PlayspaceState,
} }
impl PlayspaceMover { impl PlayspaceMover {
pub fn new(monado: &mut Monado) -> anyhow::Result<Self> { pub fn new() -> Self {
log::info!("Monado: using space offset API"); log::info!("Monado: using space offset API");
let pose = match monado.get_reference_space_offset(ReferenceSpaceType::Stage) { Self {
Err(MndResult::ErrorInvalidVersion) => anyhow::bail!("Space offsets not supported."),
Err(e) => anyhow::bail!("Could not initialize space mover: {e:?}"),
Ok(pose) => pose,
};
Ok(Self {
drag: None, drag: None,
rotate: None, rotate: None,
gravity: SpaceGravity::new(), gravity: SpaceGravity::new(),
floor_y: pose.position.y, playspace_state: load_playspace_state().unwrap_or_default(),
}) }
} }
pub fn handle_task(&mut self, app: &mut AppState, task: PlayspaceTask) { pub fn handle_task(
&mut self,
app: &mut AppState,
overlays: &mut OverlayWindowManager<OpenXrOverlayData>,
task: PlayspaceTask,
) {
let Some(monado) = &mut app.monado_state else { let Some(monado) = &mut app.monado_state else {
return; // monado not available return; // monado not available
}; };
match task { match task {
PlayspaceTask::FixFloor => { PlayspaceTask::FixFloor => {
self.fix_floor(&app.input_state, &mut monado.ipc); self.fix_floor(app, overlays);
} }
PlayspaceTask::Reset => { PlayspaceTask::Reset => {
self.reset_offset(&mut monado.ipc); self.reset_offset(app, overlays);
} }
PlayspaceTask::Recenter => { PlayspaceTask::Recenter => {
self.recenter(&app.input_state, &mut monado.ipc); self.recenter(app, overlays);
}
PlayspaceTask::SaveCenter => {
self.save_center(&mut monado.ipc);
}
PlayspaceTask::ResetCenter => {
self.playspace_state.openxr_space_center = Affine3A::IDENTITY;
} }
} }
} }
@ -76,7 +80,7 @@ impl PlayspaceMover {
if pointer.now.space_reset { if pointer.now.space_reset {
if !pointer.before.space_reset { if !pointer.before.space_reset {
log::info!("Space reset"); log::info!("Space reset");
self.reset_offset(&mut monado.ipc); self.reset_offset(app, overlays);
} }
return; return;
} }
@ -110,7 +114,11 @@ impl PlayspaceMover {
space_transform.translation = offset; space_transform.translation = offset;
let before_pose = data.pose;
data.pose *= space_transform; data.pose *= space_transform;
if !app.session.config.space_drag_affects_world {
playspace_common::shift_world(overlays, &mut app.anchor, &before_pose, &data.pose);
}
data.hand_pose = new_hand; data.hand_pose = new_hand;
apply_offset(data.pose, &mut monado.ipc); apply_offset(data.pose, &mut monado.ipc);
@ -174,10 +182,11 @@ impl PlayspaceMover {
return; return;
} }
let overlay_offset = data.pose.inverse().transform_vector3a(relative_pos) * -1.0; let before_pose = data.pose;
playspace_common::shift_overlays(overlays, overlay_offset);
data.pose.translation += relative_pos; data.pose.translation += relative_pos;
if !app.session.config.space_drag_affects_world {
playspace_common::shift_world(overlays, &mut app.anchor, &before_pose, &data.pose);
}
data.hand_pose = new_hand; data.hand_pose = new_hand;
apply_offset(data.pose, &mut monado.ipc); apply_offset(data.pose, &mut monado.ipc);
@ -218,16 +227,26 @@ impl PlayspaceMover {
config: &app.session.config, config: &app.session.config,
floor_height: app.session.config.space_gravity_floor_height, floor_height: app.session.config.space_gravity_floor_height,
}) { }) {
apply_offset( let prev_playspace_pos = res.playspace_pos - res.playspace_pos_offset;
Affine3A::from_translation(res.playspace_pos.into()), let before_pose = Affine3A::from_translation(prev_playspace_pos.into());
&mut monado.ipc, let after_pose = Affine3A::from_translation(res.playspace_pos.into());
); apply_offset(after_pose, &mut monado.ipc);
playspace_common::shift_overlays(overlays, -res.playspace_pos_offset); if !app.session.config.space_drag_affects_world {
playspace_common::shift_world(overlays, &mut app.anchor, &before_pose, &after_pose);
}
} }
} }
pub fn recenter(&mut self, input: &InputState, monado: &mut Monado) { pub fn recenter(
&mut self,
app: &mut AppState,
overlays: &mut OverlayWindowManager<OpenXrOverlayData>,
) {
let Some(monado) = &mut app.monado_state else {
return;
};
if self.drag.is_some() { if self.drag.is_some() {
log::info!("Space drag interrupted by recenter"); log::info!("Space drag interrupted by recenter");
self.drag = None; self.drag = None;
@ -237,13 +256,20 @@ impl PlayspaceMover {
self.rotate = None; self.rotate = None;
} }
let input = &app.input_state;
let anchor = &mut app.anchor;
let Ok(mut pose) = monado let Ok(mut pose) = monado
.ipc
.get_reference_space_offset(ReferenceSpaceType::Stage) .get_reference_space_offset(ReferenceSpaceType::Stage)
.inspect_err(|e| log::warn!("Could not recenter due to libmonado error: {e:?}")) .inspect_err(|e| log::warn!("Could not recenter due to libmonado error: {e:?}"))
else { else {
return; return;
}; };
let before =
Affine3A::from_rotation_translation(pose.orientation.into(), pose.position.into());
let cur_rot: Quat = pose.orientation.into(); let cur_rot: Quat = pose.orientation.into();
let cur_pos: Vec3 = pose.position.into(); let cur_pos: Vec3 = pose.position.into();
@ -274,13 +300,28 @@ impl PlayspaceMover {
} }
let _ = monado let _ = monado
.ipc
.set_reference_space_offset(ReferenceSpaceType::Stage, pose) .set_reference_space_offset(ReferenceSpaceType::Stage, pose)
.inspect_err(|e| log::warn!("Could not recenter due to libmonado error: {e:?}")); .inspect_err(|e| log::warn!("Could not recenter due to libmonado error: {e:?}"));
self.gravity.reset(); self.gravity.reset();
if !app.session.config.space_drag_affects_world {
let after =
Affine3A::from_rotation_translation(pose.orientation.into(), pose.position.into());
playspace_common::shift_world(overlays, anchor, &before, &after);
}
} }
pub fn reset_offset(&mut self, monado: &mut Monado) { pub fn reset_offset(
&mut self,
app: &mut AppState,
overlays: &mut OverlayWindowManager<OpenXrOverlayData>,
) {
let Some(monado) = &mut app.monado_state else {
return;
};
if self.drag.is_some() { if self.drag.is_some() {
log::info!("Space drag interrupted by manual reset"); log::info!("Space drag interrupted by manual reset");
self.drag = None; self.drag = None;
@ -290,13 +331,36 @@ impl PlayspaceMover {
self.rotate = None; self.rotate = None;
} }
let Ok(pose) = monado
.ipc
.get_reference_space_offset(ReferenceSpaceType::Stage)
.inspect_err(|e| log::warn!("Could not reset offset due to libmonado error: {e:?}"))
else {
return;
};
let before =
Affine3A::from_rotation_translation(pose.orientation.into(), pose.position.into());
self.gravity.reset(); self.gravity.reset();
let mut offset = Affine3A::IDENTITY; let offset = self.playspace_state.openxr_space_center;
offset.translation.y = self.floor_y; apply_offset(offset, &mut monado.ipc);
apply_offset(offset, monado);
if !app.session.config.space_drag_affects_world {
let after = offset;
playspace_common::shift_world(overlays, &mut app.anchor, &before, &after);
}
} }
pub fn fix_floor(&mut self, input: &InputState, monado: &mut Monado) { pub fn fix_floor(
&mut self,
app: &mut AppState,
overlays: &mut OverlayWindowManager<OpenXrOverlayData>,
) {
let Some(monado) = &mut app.monado_state else {
return;
};
if self.drag.is_some() { if self.drag.is_some() {
log::info!("Space drag interrupted by fix floor"); log::info!("Space drag interrupted by fix floor");
self.drag = None; self.drag = None;
@ -306,24 +370,65 @@ impl PlayspaceMover {
self.rotate = None; self.rotate = None;
} }
let input = &app.input_state;
let anchor = &mut app.anchor;
let Ok(mut pose) = monado let Ok(mut pose) = monado
.ipc
.get_reference_space_offset(ReferenceSpaceType::Stage) .get_reference_space_offset(ReferenceSpaceType::Stage)
.inspect_err(|e| log::warn!("Could not fix floor due to libmonado error: {e:?}")) .inspect_err(|e| log::warn!("Could not fix floor due to libmonado error: {e:?}"))
else { else {
return; return;
}; };
let before =
Affine3A::from_rotation_translation(pose.orientation.into(), pose.position.into());
let y1 = input.pointers[0].raw_pose.translation.y; let y1 = input.pointers[0].raw_pose.translation.y;
let y2 = input.pointers[1].raw_pose.translation.y; let y2 = input.pointers[1].raw_pose.translation.y;
let delta = y1.min(y2) - 0.05; let delta = y1.min(y2) - 0.05;
pose.position.y += delta; pose.position.y += delta;
self.floor_y = pose.position.y; self.playspace_state.openxr_space_center.translation.y = pose.position.y;
let _ = monado let _ = monado
.ipc
.set_reference_space_offset(ReferenceSpaceType::Stage, pose) .set_reference_space_offset(ReferenceSpaceType::Stage, pose)
.inspect_err(|e| log::warn!("Could not fix floor due to libmonado error: {e:?}")); .inspect_err(|e| log::warn!("Could not fix floor due to libmonado error: {e:?}"));
let after =
Affine3A::from_rotation_translation(pose.orientation.into(), pose.position.into());
if !app.session.config.space_drag_affects_world {
playspace_common::shift_world(overlays, anchor, &before, &after);
}
}
pub fn save_center(&mut self, monado: &mut Monado) {
if self.drag.is_some() {
log::info!("Space drag interrupted by save center");
self.drag = None;
}
if self.rotate.is_some() {
log::info!("Space rotate interrupted by save center");
self.rotate = None;
}
let Ok(pose) = monado
.get_reference_space_offset(ReferenceSpaceType::Stage)
.inspect_err(|e| log::warn!("Could not fix floor due to libmonado error: {e:?}"))
else {
return;
};
let cur_rot: Quat = pose.orientation.into();
let cur_pos: Vec3 = pose.position.into();
let stage_offset = Affine3A::from_rotation_translation(cur_rot, cur_pos);
self.playspace_state.openxr_space_center = stage_offset;
let _ =
save_playspace_state(&self.playspace_state).log_err("Could not save playspace state");
} }
} }

View File

@ -1,4 +1,4 @@
use glam::Vec3A; use glam::{Affine3A, Vec3A};
use wlx_common::config::GeneralConfig; use wlx_common::config::GeneralConfig;
use crate::windowing::manager::OverlayWindowManager; use crate::windowing::manager::OverlayWindowManager;
@ -15,17 +15,20 @@ pub struct SpaceGravity {
space_pos: Vec3A, space_pos: Vec3A,
} }
pub fn shift_overlays<OverlayData>( pub fn shift_world<OverlayData>(
overlays: &mut OverlayWindowManager<OverlayData>, overlays: &mut OverlayWindowManager<OverlayData>,
overlay_offset: Vec3A, anchor: &mut Affine3A,
before: &Affine3A,
after: &Affine3A,
) { ) {
let correction = after.inverse() * before;
*anchor = correction * *anchor;
overlays.values_mut().for_each(|overlay| { overlays.values_mut().for_each(|overlay| {
let Some(state) = overlay.config.active_state.as_mut() else { let Some(state) = overlay.config.active_state.as_mut() else {
return; return;
}; };
if state.positioning.moves_with_space() { state.transform = correction * state.transform;
state.transform.translation += overlay_offset;
}
overlay.config.dirty = true; overlay.config.dirty = true;
}); });
} }

View File

@ -6,11 +6,15 @@ use std::{
}; };
use serde::Deserialize; use serde::Deserialize;
use strum::EnumIs;
use crate::{ use crate::{
backend::input, backend::input,
state::AppState, state::AppState,
windowing::{OverlaySelector, window::OverlayWindowConfig}, windowing::{
OverlaySelector,
window::{OverlayCategory, OverlayWindowConfig},
},
}; };
static TASK_AUTO_INCREMENT: AtomicUsize = AtomicUsize::new(0); static TASK_AUTO_INCREMENT: AtomicUsize = AtomicUsize::new(0);
@ -63,6 +67,8 @@ pub enum PlayspaceTask {
Recenter, Recenter,
Reset, Reset,
FixFloor, FixFloor,
SaveCenter,
ResetCenter,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -92,16 +98,24 @@ pub enum ToggleMode {
Toggle, Toggle,
} }
#[derive(Clone)] #[derive(Clone, EnumIs)]
pub enum SpawnPos { pub enum SpawnPos {
/// Always spawn at the designated pos /// Always spawn at designated position
Fixed, Fixed,
/// Always spawn at designated position and orientation
FixedNoRealign,
/// Automatically spread out for user experience /// Automatically spread out for user experience
Spread, Spread,
/// Spawn relative to a different overlay /// Spawn relative to a different overlay
Parent(OverlaySelector), Parent(OverlaySelector),
} }
pub enum GlobalChange {
Settings,
Keyboard,
ColorPalette,
}
pub type ModifyOverlayTask = dyn FnOnce(&mut AppState, &mut OverlayWindowConfig) + Send; pub type ModifyOverlayTask = dyn FnOnce(&mut AppState, &mut OverlayWindowConfig) + Send;
pub type CreateOverlayTask = dyn FnOnce(&mut AppState) -> Option<OverlayWindowConfig> + Send; pub type CreateOverlayTask = dyn FnOnce(&mut AppState) -> Option<OverlayWindowConfig> + Send;
pub enum OverlayTask { pub enum OverlayTask {
@ -115,17 +129,19 @@ pub enum OverlayTask {
ToggleEditMode, ToggleEditMode,
ToggleDashboard, ToggleDashboard,
ShowHide, ShowHide,
CleanupMirrors, CleanupOverlays(OverlayCategory),
SettingsChanged, GlobalChange(GlobalChange),
KeyboardChanged,
Modify(OverlaySelector, Box<ModifyOverlayTask>), Modify(OverlaySelector, Box<ModifyOverlayTask>),
Spawn(OverlaySelector, SpawnPos, Box<CreateOverlayTask>), Spawn(OverlaySelector, SpawnPos, Box<CreateOverlayTask>),
ModifyPanel(ModifyPanelTask), ModifyPanel(ModifyPanelTask),
Drop(OverlaySelector), Drop(OverlaySelector),
} }
pub type GlobalTask = dyn FnOnce(&mut AppState) + Send;
#[allow(dead_code)] #[allow(dead_code)]
pub enum TaskType { pub enum TaskType {
Global(Box<GlobalTask>),
Input(InputTask), Input(InputTask),
Overlay(OverlayTask), Overlay(OverlayTask),
Playspace(PlayspaceTask), Playspace(PlayspaceTask),

View File

@ -7,12 +7,13 @@ use std::{
}; };
use anyhow::Context; use anyhow::Context;
use glam::Vec2; use glam::{DVec2, Vec2};
use slotmap::DenseSlotMap;
use smithay::{ use smithay::{
backend::input::{Axis, AxisSource, ButtonState, Keycode}, backend::input::{Axis, AxisSource, ButtonState, Keycode},
input::{ input::{
keyboard::KeyboardHandle, keyboard::KeyboardHandle,
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerHandle}, pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerHandle, RelativeMotionEvent},
}, },
reexports::wayland_server::{self, protocol::wl_surface::WlSurface}, reexports::wayland_server::{self, protocol::wl_surface::WlSurface},
utils::{Logical, Point, SerialCounter}, utils::{Logical, Point, SerialCounter},
@ -146,7 +147,7 @@ impl WayVRCompositor {
fn accept_connection( fn accept_connection(
&mut self, &mut self,
stream: UnixStream, stream: UnixStream,
processes: &mut process::ProcessVec, processes: &mut DenseSlotMap<process::ProcessHandle, process::Process>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let client = self let client = self
.display .display
@ -154,13 +155,13 @@ impl WayVRCompositor {
.insert_client(stream, Arc::new(comp::ClientState::default())) .insert_client(stream, Arc::new(comp::ClientState::default()))
.unwrap(); .unwrap();
let creds = client.get_credentials(&self.display.handle())?; let credentials = client.get_credentials(&self.display.handle())?;
let process_env = get_wayvr_env_from_pid(creds.pid)?; let process_env = get_wayvr_env_from_pid(credentials.pid)?;
// Find suitable auth key from the process list // Find suitable auth key from the process list
for p in processes.vec.iter().flatten() { for (_, process) in processes {
if let process::Process::Managed(process) = &p.obj if let process::Process::Managed(process) = &process
&& let Some(auth_key) = &process_env.display_auth && let Some(auth_key) = &process_env.display_auth
{ {
// Find process with matching auth key // Find process with matching auth key
@ -168,7 +169,7 @@ impl WayVRCompositor {
// Add client // Add client
self.add_client(WayVRClient { self.add_client(WayVRClient {
client, client,
pid: creds.pid as u32, pid: credentials.pid as u32,
}); });
return Ok(()); return Ok(());
} }
@ -179,7 +180,7 @@ impl WayVRCompositor {
// Treat external processes exclusively (spawned by the user or external program) // Treat external processes exclusively (spawned by the user or external program)
log::warn!( log::warn!(
"External process ID {} connected to this Wayland server", "External process ID {} connected to this Wayland server",
creds.pid credentials.pid
); );
self.state self.state
@ -187,13 +188,16 @@ impl WayVRCompositor {
.send(WayVRTask::NewExternalProcess(ExternalProcessRequest { .send(WayVRTask::NewExternalProcess(ExternalProcessRequest {
env: process_env, env: process_env,
client, client,
pid: creds.pid as u32, pid: credentials.pid as u32,
})); }));
Ok(()) Ok(())
} }
fn accept_connections(&mut self, processes: &mut process::ProcessVec) -> anyhow::Result<()> { fn accept_connections(
&mut self,
processes: &mut DenseSlotMap<process::ProcessHandle, process::Process>,
) -> anyhow::Result<()> {
if let Some(stream) = self.listener.accept()? if let Some(stream) = self.listener.accept()?
&& let Err(e) = self.accept_connection(stream, processes) && let Err(e) = self.accept_connection(stream, processes)
{ {
@ -203,7 +207,10 @@ impl WayVRCompositor {
Ok(()) Ok(())
} }
pub fn tick_wayland(&mut self, processes: &mut process::ProcessVec) -> anyhow::Result<()> { pub fn tick_wayland(
&mut self,
processes: &mut DenseSlotMap<process::ProcessHandle, process::Process>,
) -> anyhow::Result<()> {
if let Err(e) = self.accept_connections(processes) { if let Err(e) = self.accept_connections(processes) {
log::error!("accept_connections failed: {e}"); log::error!("accept_connections failed: {e}");
} }
@ -232,11 +239,26 @@ impl WayVRCompositor {
Keycode::new(virtual_key), Keycode::new(virtual_key),
state, state,
self.serial_counter.next_serial(), self.serial_counter.next_serial(),
0, super::time::get_millis() as u32,
|_, _, _| smithay::input::keyboard::FilterResult::Forward, |_, _, _| smithay::input::keyboard::FilterResult::Forward,
); );
} }
pub fn release_all_keys(&mut self) {
let pressed = self.seat_keyboard.pressed_keys();
for keycode in pressed {
self.seat_keyboard.input::<(), _>(
&mut self.state,
keycode,
smithay::backend::input::KeyState::Released,
self.serial_counter.next_serial(),
super::time::get_millis() as u32,
|_, _, _| smithay::input::keyboard::FilterResult::Forward,
);
}
}
pub fn set_keymap(&mut self, keymap: &xkb::Keymap) -> anyhow::Result<()> { pub fn set_keymap(&mut self, keymap: &xkb::Keymap) -> anyhow::Result<()> {
// Smithay only accepts keymaps in a string form due to thread safety concerns // Smithay only accepts keymaps in a string form due to thread safety concerns
self.seat_keyboard self.seat_keyboard
@ -247,8 +269,16 @@ impl WayVRCompositor {
.context("Failed to set keymap") .context("Failed to set keymap")
} }
pub fn send_mouse_move(&mut self, focus: Option<(WlSurface, Vec2)>, global_pos: Vec2) { pub fn send_mouse_move(
let location: Point<f64, Logical> = (global_pos.x as f64, global_pos.y as f64).into(); &mut self,
focus: Option<(WlSurface, Vec2)>,
global_pos: DVec2,
delta: DVec2,
delta_unaccel: DVec2,
) {
let location: Point<f64, Logical> = (global_pos.x, global_pos.y).into();
let delta: Point<f64, Logical> = (delta.x, delta.y).into();
let delta_unaccel: Point<f64, Logical> = (delta_unaccel.x, delta_unaccel.y).into();
let focus = focus.map(|(surface, origin)| { let focus = focus.map(|(surface, origin)| {
let focus_location: Point<f64, Logical> = (origin.x as f64, origin.y as f64).into(); let focus_location: Point<f64, Logical> = (origin.x as f64, origin.y as f64).into();
@ -258,13 +288,22 @@ impl WayVRCompositor {
self.seat_pointer.motion( self.seat_pointer.motion(
&mut self.state, &mut self.state,
focus, focus.clone(),
&MotionEvent { &MotionEvent {
location, location,
serial: self.serial_counter.next_serial(), serial: self.serial_counter.next_serial(),
time: super::time::get_millis() as u32, time: super::time::get_millis() as u32,
}, },
); );
self.seat_pointer.relative_motion(
&mut self.state,
focus,
&RelativeMotionEvent {
delta,
delta_unaccel,
utime: super::time::get_millis(),
},
);
self.seat_pointer.frame(&mut self.state); self.seat_pointer.frame(&mut self.state);
} }
@ -297,7 +336,44 @@ impl WayVRCompositor {
self.seat_pointer.frame(&mut self.state); self.seat_pointer.frame(&mut self.state);
} }
pub fn send_pointer_axis_wheel(&mut self, delta: super::WheelDelta) { pub fn send_pointer_axis_wheel_raw(&mut self, delta: super::WheelDelta) {
// 15 logical axis units for one wheel detent of 120 v120 units
const AXIS_VALUE_PER_DETENT: f64 = 15.0;
let time = super::time::get_millis() as u32;
let v120_x = delta.x as i32;
let v120_y = delta.y as i32;
if v120_x == 0 && v120_y == 0 {
return;
}
let mut frame = AxisFrame::new(time).source(AxisSource::Wheel);
if v120_x != 0 {
frame = frame
.value(
Axis::Horizontal,
f64::from(v120_x) / 120.0 * AXIS_VALUE_PER_DETENT,
)
.v120(Axis::Horizontal, v120_x);
}
if v120_y != 0 {
frame = frame
.value(
Axis::Vertical,
f64::from(v120_y) / 120.0 * AXIS_VALUE_PER_DETENT,
)
.v120(Axis::Vertical, v120_y);
}
self.seat_pointer.axis(&mut self.state, frame);
self.seat_pointer.frame(&mut self.state);
}
pub fn send_pointer_axis_wheel_accumulated(&mut self, delta: super::WheelDelta) {
let time = super::time::get_millis() as u32; let time = super::time::get_millis() as u32;
let multiplier = 32.0; let multiplier = 32.0;

View File

@ -5,7 +5,7 @@ use smithay::desktop::{
PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab, PopupUngrabStrategy, PopupKeyboardGrab, PopupKind, PopupManager, PopupPointerGrab, PopupUngrabStrategy,
find_popup_root_surface, get_popup_toplevel_coords, find_popup_root_surface, get_popup_toplevel_coords,
}; };
use smithay::input::pointer::Focus; use smithay::input::pointer::{CursorImageStatus, Focus};
use smithay::input::{Seat, SeatHandler, SeatState}; use smithay::input::{Seat, SeatHandler, SeatState};
use smithay::output::Output; use smithay::output::Output;
use smithay::reexports::rustix::fs::{OFlags, fcntl_setfl}; use smithay::reexports::rustix::fs::{OFlags, fcntl_setfl};
@ -24,6 +24,7 @@ use smithay::wayland::dmabuf::{
}; };
use smithay::wayland::fractional_scale::with_fractional_scale; use smithay::wayland::fractional_scale::with_fractional_scale;
use smithay::wayland::output::OutputHandler; use smithay::wayland::output::OutputHandler;
use smithay::wayland::relative_pointer::RelativePointerManagerState;
use smithay::wayland::selection::data_device::{ use smithay::wayland::selection::data_device::{
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler, ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
set_data_device_focus, set_data_device_selection, set_data_device_focus, set_data_device_selection,
@ -45,8 +46,8 @@ use smithay::wayland::viewporter::ViewporterState;
use smithay::{ use smithay::{
delegate_compositor, delegate_data_control, delegate_data_device, delegate_dmabuf, delegate_compositor, delegate_data_control, delegate_data_device, delegate_dmabuf,
delegate_ext_data_control, delegate_kde_decoration, delegate_output, delegate_ext_data_control, delegate_kde_decoration, delegate_output,
delegate_primary_selection, delegate_seat, delegate_shm, delegate_single_pixel_buffer, delegate_primary_selection, delegate_relative_pointer, delegate_seat, delegate_shm,
delegate_viewporter, delegate_xdg_decoration, delegate_xdg_shell, delegate_single_pixel_buffer, delegate_viewporter, delegate_xdg_decoration, delegate_xdg_shell,
}; };
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fs::File; use std::fs::File;
@ -80,6 +81,8 @@ pub struct Application {
#[allow(dead_code)] #[allow(dead_code)]
pub xdg_decoration_state: XdgDecorationState, pub xdg_decoration_state: XdgDecorationState,
pub kde_decoration_state: KdeDecorationState, pub kde_decoration_state: KdeDecorationState,
#[allow(dead_code)]
pub relative_pointer_state: RelativePointerManagerState,
pub wayvr_tasks: SyncEventQueue<WayVRTask>, pub wayvr_tasks: SyncEventQueue<WayVRTask>,
pub popup_manager: PopupManager, pub popup_manager: PopupManager,
#[allow(dead_code)] #[allow(dead_code)]
@ -87,6 +90,7 @@ pub struct Application {
pub display_handle: DisplayHandle, pub display_handle: DisplayHandle,
pub redraw_requests: HashSet<ObjectId>, pub redraw_requests: HashSet<ObjectId>,
pub pending_frame_callbacks: HashMap<ObjectId, Vec<wl_callback::WlCallback>>, pub pending_frame_callbacks: HashMap<ObjectId, Vec<wl_callback::WlCallback>>,
pub cursor_image: CursorImageStatus,
} }
impl Application { impl Application {
@ -169,10 +173,10 @@ impl Application {
} }
pub fn output_logical_size(&self) -> Size<i32, Logical> { pub fn output_logical_size(&self) -> Size<i32, Logical> {
self.output self.output.current_mode().map_or_else(
.current_mode() || Size::new(WAYVR_SCREEN_RES[0], WAYVR_SCREEN_RES[1]),
.map(|mode| Size::new(mode.size.w, mode.size.h)) |mode| Size::new(mode.size.w, mode.size.h),
.unwrap_or_else(|| Size::new(WAYVR_SCREEN_RES[0], WAYVR_SCREEN_RES[1])) )
} }
fn surface_logical_size(surface: &WlSurface) -> Option<Size<i32, Logical>> { fn surface_logical_size(surface: &WlSurface) -> Option<Size<i32, Logical>> {
@ -334,11 +338,8 @@ impl SeatHandler for Application {
set_primary_focus(dh, seat, client); set_primary_focus(dh, seat, client);
} }
fn cursor_image( fn cursor_image(&mut self, _seat: &Seat<Self>, image: CursorImageStatus) {
&mut self, self.cursor_image = image;
_seat: &Seat<Self>,
_image: smithay::input::pointer::CursorImageStatus,
) {
} }
} }
@ -457,7 +458,7 @@ impl XdgShellHandler for Application {
serial serial
); );
let popup = PopupKind::Xdg(surface.clone()); let popup = PopupKind::Xdg(surface);
let Ok(root_surface) = find_popup_root_surface(&popup) else { let Ok(root_surface) = find_popup_root_surface(&popup) else {
log::warn!("xdg_popup.grab: could not find popup root surface"); log::warn!("xdg_popup.grab: could not find popup root surface");
@ -581,6 +582,13 @@ impl XdgShellHandler for Application {
.send(WayVRTask::MinimizeRequest(client.id(), surface.clone())); .send(WayVRTask::MinimizeRequest(client.id(), surface.clone()));
} }
} }
fn title_changed(&mut self, surface: ToplevelSurface) {
if let Some(client) = surface.wl_surface().client() {
self.wayvr_tasks
.send(WayVRTask::TitleChange(client.id(), surface.clone()));
}
}
} }
impl ShmHandler for Application { impl ShmHandler for Application {
@ -683,6 +691,7 @@ delegate_ext_data_control!(Application);
delegate_xdg_decoration!(Application); delegate_xdg_decoration!(Application);
delegate_kde_decoration!(Application); delegate_kde_decoration!(Application);
delegate_single_pixel_buffer!(Application); delegate_single_pixel_buffer!(Application);
delegate_relative_pointer!(Application);
const fn wl_transform_to_frame_transform( const fn wl_transform_to_frame_transform(
transform: wl_output::Transform, transform: wl_output::Transform,

View File

@ -1,177 +0,0 @@
#[macro_export]
macro_rules! gen_id {
(
$container_name:ident,
$instance_name:ident,
$cell_name:ident,
$handle_name:ident) => {
//ThingCell
#[derive(Debug)]
pub struct $cell_name {
pub obj: $instance_name,
pub generation: u64,
}
//ThingVec
#[derive(Debug)]
pub struct $container_name {
// Vec<Option<ThingCell>>
pub vec: Vec<Option<$cell_name>>,
cur_generation: u64,
}
//ThingHandle
#[derive(Default, Debug, Clone, Copy, PartialEq, Hash, Eq)]
pub struct $handle_name {
idx: u32,
generation: u64,
}
#[allow(dead_code)]
impl $handle_name {
pub const fn reset(&mut self) {
self.generation = 0;
}
pub const fn is_set(&self) -> bool {
self.generation > 0
}
pub const fn id(&self) -> u32 {
self.idx
}
pub const fn new(idx: u32, generation: u64) -> Self {
Self { idx, generation }
}
}
//ThingVec
impl $container_name {
pub const fn new() -> Self {
Self {
vec: Vec::new(),
cur_generation: 0,
}
}
pub fn iter(&self) -> impl Iterator<Item = ($handle_name, &$instance_name)> {
self.vec.iter().enumerate().filter_map(|(idx, opt_cell)| {
opt_cell.as_ref().map(|cell| {
let handle = $container_name::get_handle(&cell, idx);
(handle, &cell.obj)
})
})
}
#[allow(dead_code)]
pub fn iter_mut(
&mut self,
) -> impl Iterator<Item = ($handle_name, &mut $instance_name)> {
self.vec
.iter_mut()
.enumerate()
.filter_map(|(idx, opt_cell)| {
opt_cell.as_mut().map(|cell| {
let handle = $container_name::get_handle(&cell, idx);
(handle, &mut cell.obj)
})
})
}
pub const fn get_handle(cell: &$cell_name, idx: usize) -> $handle_name {
$handle_name {
idx: idx as u32,
generation: cell.generation,
}
}
fn find_unused_idx(&mut self) -> Option<u32> {
for (num, obj) in self.vec.iter().enumerate() {
if obj.is_none() {
return Some(num as u32);
}
}
None
}
pub fn add(&mut self, obj: $instance_name) -> $handle_name {
self.cur_generation += 1;
let generation = self.cur_generation;
let unused_idx = self.find_unused_idx();
let idx = if let Some(idx) = unused_idx {
idx
} else {
self.vec.len() as u32
};
let handle = $handle_name { idx, generation };
let cell = $cell_name { obj, generation };
if let Some(idx) = unused_idx {
self.vec[idx as usize] = Some(cell);
} else {
self.vec.push(Some(cell))
}
handle
}
pub fn remove(&mut self, handle: &$handle_name) {
// Out of bounds, ignore
if handle.idx as usize >= self.vec.len() {
return;
}
// Remove only if the generation matches
if let Some(cell) = &self.vec[handle.idx as usize] {
if cell.generation == handle.generation {
self.vec[handle.idx as usize] = None;
}
}
}
pub fn get(&self, handle: &$handle_name) -> Option<&$instance_name> {
// Out of bounds, ignore
if handle.idx as usize >= self.vec.len() {
return None;
}
if let Some(cell) = &self.vec[handle.idx as usize] {
if cell.generation == handle.generation {
return Some(&cell.obj);
}
}
None
}
pub fn get_mut(&mut self, handle: &$handle_name) -> Option<&mut $instance_name> {
// Out of bounds, ignore
if handle.idx as usize >= self.vec.len() {
return None;
}
if let Some(cell) = &mut self.vec[handle.idx as usize] {
if cell.generation == handle.generation {
return Some(&mut cell.obj);
}
}
None
}
}
};
}
/* Example usage:
gen_id!(ThingVec, ThingInstance, ThingCell, ThingHandle);
struct ThingInstance {}
impl ThingInstance {}
*/

View File

@ -0,0 +1,401 @@
use glam::{Affine2, Vec2};
use smithay::{
desktop::PopupManager,
reexports::wayland_server::{Resource, backend::ObjectId, protocol::wl_surface::WlSurface},
utils::{Logical, Point},
wayland::{
compositor::{
SUBSURFACE_ROLE, SubsurfaceCachedState, SurfaceAttributes, TraversalAction,
with_states, with_surface_tree_upward,
},
shell::xdg::XdgPopupSurfaceData,
},
};
use std::{ops::RangeInclusive, rc::Rc, sync::Arc};
use vulkano::image::view::ImageView;
use crate::graphics::ExtentExt;
use crate::backend::input::PointerHit;
use super::SurfaceBufWithImage;
pub const BORDER_SIZE: u32 = 5;
pub const BAR_SIZE: u32 = 48;
#[derive(Clone)]
pub struct PopupRoot {
pub surface: WlSurface,
pub surface_origin: Vec2,
}
#[derive(Clone)]
pub struct RenderedSurface {
pub surface: WlSurface,
pub surface_id: ObjectId,
pub image: Arc<ImageView>,
pub pos: Vec2,
pub size: Vec2,
}
#[derive(Clone)]
pub enum WvrHitTarget {
Panel(PointerHit),
Toplevel {
pos: Vec2,
},
Surface {
surface: WlSurface,
global_pos: Vec2,
origin: Vec2,
},
Popup {
surface: WlSurface,
global_pos: Vec2,
origin: Vec2,
},
}
pub struct WvrHitContext {
pub surfaces: Rc<[RenderedSurface]>,
pub popup_roots: Rc<[PopupRoot]>,
pub mouse_transform: Affine2,
pub uv_range: RangeInclusive<f32>,
pub inner_extent: [u32; 2],
pub panel_height: u32,
}
impl WvrHitContext {
pub fn popup_hit_at_client_pos(&self, pos: Vec2) -> Option<(WlSurface, Vec2)> {
self.popup_roots.iter().find_map(|popup| {
surface_tree_input_hit_test(&popup.surface, popup.surface_origin, pos, true)
})
}
pub fn is_inside_client_area(&self, transformed: Vec2) -> bool {
self.uv_range.contains(&transformed.x) && self.uv_range.contains(&transformed.y)
}
pub fn transformed_uv_from_hit(&self, hit: &PointerHit) -> Vec2 {
self.mouse_transform.transform_point2(hit.uv)
}
pub fn client_pos_from_transformed_uv(&self, transformed: Vec2) -> Vec2 {
Vec2::new(
transformed.x * self.inner_extent[0] as f32,
transformed.y * self.inner_extent[1] as f32,
)
}
pub fn unclamped_client_pos_from_hit(&self, hit: &PointerHit) -> Vec2 {
let transformed = self.transformed_uv_from_hit(hit);
self.client_pos_from_transformed_uv(transformed)
}
pub fn panel_hit_from_hit(&self, hit: &PointerHit) -> Option<PointerHit> {
if self.panel_height == 0 {
return None;
}
let mut hit2 = *hit;
let total_height = self.inner_extent[1] + self.panel_height;
hit2.uv.y *= total_height as f32 / self.panel_height as f32;
Some(hit2)
}
pub fn hit_target_at(&self, client_pos: Vec2) -> Option<WvrHitTarget> {
let transformed = self.mouse_transform.inverse().transform_point2(Vec2::new(
client_pos.x / self.inner_extent[0] as f32,
client_pos.y / self.inner_extent[1] as f32,
));
if let Some((surface, surface_origin)) = self.popup_hit_at_client_pos(client_pos) {
return Some(WvrHitTarget::Popup {
surface,
global_pos: client_pos,
origin: surface_origin,
});
}
if !self.is_inside_client_area(transformed) {
return None;
}
let hit_surface = self
.surfaces
.iter()
.rev()
.find(|s| surface_accepts_input(s, client_pos));
if let Some(surface) = hit_surface {
return Some(WvrHitTarget::Surface {
surface: surface.surface.clone(),
global_pos: client_pos,
origin: surface.pos,
});
}
Some(WvrHitTarget::Toplevel { pos: client_pos })
}
pub fn hit_target(&self, hit: &PointerHit) -> Option<WvrHitTarget> {
let transformed = self.transformed_uv_from_hit(hit);
let client_pos = self.client_pos_from_transformed_uv(transformed);
// popups are checked before the panel/client bounds.
if let Some((surface, surface_origin)) = self.popup_hit_at_client_pos(client_pos) {
return Some(WvrHitTarget::Popup {
surface,
global_pos: client_pos,
origin: surface_origin,
});
}
if !self.is_inside_client_area(transformed) {
return self.panel_hit_from_hit(hit).map(WvrHitTarget::Panel);
}
let hit_surface = self
.surfaces
.iter()
.rev()
.find(|s| surface_accepts_input(s, client_pos));
if let Some(surface) = hit_surface {
return Some(WvrHitTarget::Surface {
surface: surface.surface.clone(),
global_pos: client_pos,
origin: surface.pos,
});
}
let clamped = transformed.clamp(Vec2::ZERO, Vec2::ONE);
let pos = self.client_pos_from_transformed_uv(clamped);
Some(WvrHitTarget::Toplevel { pos })
}
}
fn surface_location(states: &smithay::wayland::compositor::SurfaceData) -> Point<i32, Logical> {
if states.role == Some(SUBSURFACE_ROLE) {
let mut guard = states.cached_state.get::<SubsurfaceCachedState>();
guard.current().location
} else {
(0, 0).into()
}
}
pub fn collect_rendered_surface_tree_at(
root: &WlSurface,
initial_pos: Point<i32, Logical>,
include_root: bool,
) -> Vec<RenderedSurface> {
let mut out = Vec::new();
let root_id = root.id();
with_surface_tree_upward(
root,
initial_pos,
|_, states, parent_pos| {
let pos = *parent_pos + surface_location(states);
// do not skip even if this surface has no buffer; children may still have buffers
TraversalAction::DoChildren(pos)
},
|surface, states, parent_pos| {
if !include_root && surface.id() == root_id {
return;
}
let pos = *parent_pos + surface_location(states);
if let Some(surf) = SurfaceBufWithImage::get_from_surface(states) {
let extent = surf.image.extent_f32();
let scale = surf.scale.max(1) as f32;
out.push(RenderedSurface {
surface: surface.clone(),
surface_id: surface.id(),
image: surf.image,
pos: Vec2::new(pos.x as f32, pos.y as f32),
size: Vec2::new(extent[0] / scale, extent[1] / scale),
});
}
},
|_, _, _| true,
);
out
}
pub fn collect_rendered_surface_tree(root: &WlSurface) -> Rc<[RenderedSurface]> {
collect_rendered_surface_tree_at(root, Point::<i32, Logical>::from((0, 0)), false).into()
}
fn surface_accepts_input(surface: &RenderedSurface, global_pos: Vec2) -> bool {
let local = global_pos - surface.pos;
if local.x < 0.0 || local.y < 0.0 || local.x >= surface.size.x || local.y >= surface.size.y {
return false;
}
#[allow(clippy::significant_drop_tightening)]
with_states(&surface.surface, |states| {
let mut guard = states.cached_state.get::<SurfaceAttributes>();
let attrs = guard.current();
match attrs.input_region.as_ref() {
None => true,
Some(region) => {
let point =
Point::<i32, Logical>::from((local.x.floor() as i32, local.y.floor() as i32));
region.contains(point)
}
}
})
}
#[allow(clippy::significant_drop_tightening)]
fn surface_accepts_input_states(
states: &smithay::wayland::compositor::SurfaceData,
local: Vec2,
) -> bool {
if local.x < 0.0 || local.y < 0.0 {
return false;
}
let mut guard = states.cached_state.get::<SurfaceAttributes>();
let attrs = guard.current();
let point = Point::<i32, Logical>::from((local.x.floor() as i32, local.y.floor() as i32));
// explicit input region wins, even if no render buffer
if let Some(region) = attrs.input_region.as_ref() {
return region.contains(point);
}
// fallback for normal rendered surfaces
if let Some(surf) = SurfaceBufWithImage::get_from_surface(states) {
let extent = surf.image.extent_f32();
let scale = surf.scale.max(1) as f32;
return local.x < extent[0] / scale && local.y < extent[1] / scale;
}
false
}
pub fn surface_tree_input_hit_test(
root: &WlSurface,
root_origin: Vec2,
global_pos: Vec2,
include_root: bool,
) -> Option<(WlSurface, Vec2)> {
let mut hit = None;
let root_id = root.id();
with_surface_tree_upward(
root,
Point::<i32, Logical>::from((root_origin.x as i32, root_origin.y as i32)),
|_, states, parent_pos| {
let pos = *parent_pos + surface_location(states);
TraversalAction::DoChildren(pos)
},
|surface, states, parent_pos| {
if !include_root && surface.id() == root_id {
return;
}
let pos = *parent_pos + surface_location(states);
let surface_origin = Vec2::new(pos.x as f32, pos.y as f32);
let local = global_pos - surface_origin;
if surface_accepts_input_states(states, local) {
// with_surface_tree_upward visits bottom-to-top, so later hits win
hit = Some((surface.clone(), surface_origin));
}
},
|_, _, _| true,
);
hit
}
pub fn rendered_surfaces_dirty(old: &[RenderedSurface], new: &[RenderedSurface]) -> bool {
if old.len() != new.len() {
return true;
}
old.iter().zip(new).any(|(a, b)| {
a.surface_id != b.surface_id
|| a.pos != b.pos
|| a.size != b.size
|| *a.image.image() != *b.image.image()
})
}
pub fn compute_transforms(inner_extent: [u32; 2]) -> (Affine2, RangeInclusive<f32>) {
let ix = inner_extent[0].max(1) as f32;
let iy = inner_extent[1].max(1) as f32;
let extent_x = ix + BORDER_SIZE as f32 * 2.0;
let extent_y = iy + BORDER_SIZE as f32 * 2.0 + BAR_SIZE as f32;
let scale_x = (extent_x + BORDER_SIZE as f32 * 2.0) / extent_x;
let scale_y = (extent_y + BORDER_SIZE as f32 * 2.0 + BAR_SIZE as f32) / extent_y;
let translation_x = -(BORDER_SIZE as f32) / ix;
let translation_y = -((BORDER_SIZE + BAR_SIZE) as f32) / iy;
let mouse_transform = Affine2::from_scale_angle_translation(
Vec2::new(scale_x, scale_y),
0.0,
Vec2::new(translation_x, translation_y),
);
let uv_range = translation_x..=(1.0 - translation_x);
(mouse_transform, uv_range)
}
pub fn build_hit_context(
toplevel: &WlSurface,
_popup_manager: &PopupManager,
inner_extent: [u32; 2],
) -> WvrHitContext {
let (mouse_transform, uv_range) = compute_transforms(inner_extent);
let panel_height = BORDER_SIZE * 2 + BAR_SIZE;
let surfaces = collect_rendered_surface_tree(toplevel);
let mut popup_roots = Vec::new();
for (popup, point) in PopupManager::popups_for_surface(toplevel) {
let configured = with_states(popup.wl_surface(), |states| {
states
.data_map
.get::<XdgPopupSurfaceData>()
.unwrap()
.lock()
.unwrap()
.configured
});
if !configured {
continue;
}
let popup_origin = point - popup.geometry().loc;
popup_roots.push(PopupRoot {
surface: popup.wl_surface().clone(),
surface_origin: Vec2::new(popup_origin.x as f32, popup_origin.y as f32),
});
}
WvrHitContext {
surfaces,
popup_roots: popup_roots.into(),
mouse_transform,
uv_range,
inner_extent,
panel_height,
}
}

Some files were not shown because too many files have changed in this diff Show More