Repository: xanderfrangos/twinkle-tray Branch: master Commit: 4fce279da9ac Files: 158 Total size: 1.4 MB Directory structure: gitextract_15q36qbk/ ├── .babelrc ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ └── ci.yml ├── .gitignore ├── .sassrc ├── .vscode/ │ └── settings.json ├── LICENSE ├── README.md ├── package.json ├── resources/ │ ├── appx/ │ │ └── extensions.xml │ └── nsis/ │ └── installer.nsh └── src/ ├── Monitors.js ├── Translate.js ├── TranslateReact.js ├── Utils.js ├── components/ │ ├── BrightnessPanel.jsx │ ├── DDCCISliders.jsx │ ├── HDRSliders.jsx │ ├── IntroWindow.jsx │ ├── MonitorFeatures.jsx │ ├── MonitorInfo.jsx │ ├── SafeRender.jsx │ ├── SettingsOption.jsx │ ├── SettingsWindow.jsx │ ├── Slider.jsx │ └── Titlebar.jsx ├── css/ │ ├── common.scss │ ├── intro.scss │ ├── mica.scss │ ├── page.scss │ ├── panel.scss │ ├── settings-option.scss │ ├── slider.scss │ └── vars.scss ├── electron.js ├── hooks/ │ └── useObject.js ├── html/ │ ├── index.html │ ├── intro.html │ └── settings.html ├── intro-preload.js ├── intro.js ├── localization/ │ ├── ar.json │ ├── az.json │ ├── bn.json │ ├── ckb.json │ ├── cs.json │ ├── de.json │ ├── el.json │ ├── en-GB.json │ ├── en.json │ ├── es.json │ ├── fa.json │ ├── fi.json │ ├── fr.json │ ├── he.json │ ├── hi.json │ ├── hr.json │ ├── hu.json │ ├── id.json │ ├── it.json │ ├── ja.json │ ├── ko.json │ ├── lt.json │ ├── nb.json │ ├── nl.json │ ├── pl.json │ ├── pt-BR.json │ ├── pt.json │ ├── ro.json │ ├── ru.json │ ├── sk.json │ ├── sv.json │ ├── ta.json │ ├── th.json │ ├── tr.json │ ├── uk.json │ ├── vi.json │ ├── zh-Hant.json │ └── zh_Hans.json ├── modules/ │ ├── acrylic/ │ │ ├── .gitignore │ │ ├── acrylic.cc │ │ ├── binding.gyp │ │ ├── index.js │ │ └── package.json │ ├── node-active-window/ │ │ ├── .eslintrc.json │ │ ├── .gitignore │ │ ├── .prettierrc.json │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── binding.gyp │ │ ├── dist/ │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── types.d.ts │ │ │ └── types.js │ │ ├── module/ │ │ │ └── windows/ │ │ │ ├── demo/ │ │ │ │ ├── Makefile │ │ │ │ └── main.cpp │ │ │ ├── napi/ │ │ │ │ ├── main.cpp │ │ │ │ ├── module.cpp │ │ │ │ └── module.h │ │ │ └── src/ │ │ │ ├── ActiveWindow.cpp │ │ │ └── ActiveWindow.h │ │ ├── package.json │ │ ├── src/ │ │ │ ├── index.ts │ │ │ └── types.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── node-ddcci/ │ │ ├── .clang-format │ │ ├── .gitignore │ │ ├── README.md │ │ ├── binding.gyp │ │ ├── ddcci.cc │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── package.json │ │ └── vcp.js │ ├── tt-windows-utils/ │ │ ├── .gitignore │ │ ├── binding.gyp │ │ ├── index.js │ │ ├── package.json │ │ ├── windows_app_startup.cc │ │ ├── windows_media_status.cc │ │ ├── windows_power_events.cc │ │ ├── windows_window_material.cc │ │ └── windows_window_utils.cc │ ├── win32-displayconfig/ │ │ ├── .gitignore │ │ ├── CONTRIBUTORS │ │ ├── COPYRIGHT │ │ ├── README.md │ │ ├── binding.gyp │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── package.json │ │ ├── scripts/ │ │ │ ├── dumpextract.js │ │ │ ├── dumpquery.js │ │ │ └── watchmouse.js │ │ └── win32-displayconfig.cc │ ├── windows-hdr/ │ │ ├── .gitignore │ │ ├── binding.gyp │ │ ├── index.js │ │ ├── package.json │ │ └── windows-hdr.cc │ └── wmi-bridge/ │ ├── binding.gyp │ ├── example.js │ ├── index.js │ ├── package.json │ └── wmi-bridge.cc ├── monitor-rules.json ├── panel-preload.js ├── panel.js ├── parcel.js ├── parcelAPI.js ├── settings-preload.js ├── settings.js ├── utils/ │ └── BrightnessPanel/ │ └── getMonitorName.js ├── vcp-codes.js └── wmi-bridge-test.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .babelrc ================================================ { "presets": ["@babel/preset-react"], "plugins": [] } ================================================ FILE: .gitattributes ================================================ # Auto detect text files and perform LF normalization * text=auto ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: "xanderfrangos" # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: "xanderfrangos" # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: ['paypal.me/xanderfrangos', 'xanderfrangos.com/crypto.md'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI Build on: [push, pull_request] env: BRANCH_NAME: ${{ github.head_ref || github.ref_name }} jobs: build: name: Build all runs-on: windows-2025 steps: - uses: actions/checkout@v4 name: Read repository - name: Set up Node.js 22 uses: actions/setup-node@v4 with: node-version: 22 cache: 'npm' - name: Get package.json info id: info uses: jaywcjlove/github-action-package@main - name: Prepare dependencies run: npm i env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build assets run: npm run parcel-build env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Build Win32 installer run: npm exec electron-builder -- --x64 --config.extraMetadata.versionBuild="${{ steps.info.outputs.version }}+${{ github.sha }}" --config.win.artifactName="Twinkle.Tray.v${{ steps.info.outputs.version }}.exe" --publish="never" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: actions/upload-artifact@v4 name: Upload Win32 installer with: name: twinkle-tray-exe-${{ steps.info.outputs.version }}-${{ github.sha }} path: dist/*.exe - name: Get current date id: date uses: Kaven-Universe/github-action-current-date-time@v1 with: format: "YYYY.1MMDD.1HHmm" - name: Build x64 AppX if: ${{ env.BRANCH_NAME == 'master' || env.BRANCH_NAME == 'ci-test' }} run: npm exec electron-builder -- --x64 --win appx --config.npmRebuild=false --config.extraMetadata.versionBuild="${{ steps.info.outputs.version }}+${{ github.sha }}" --config.extraMetadata.version=${{ steps.date.outputs.time }} --config.extraMetadata.name=twinkle-tray-appx --config.win.artifactName="Twinkle.Tray.v${{ steps.info.outputs.version }}-store.appx" --publish="never" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: actions/upload-artifact@v4 name: Upload x64 AppX if: ${{ env.BRANCH_NAME == 'master' || env.BRANCH_NAME == 'ci-test' }} with: name: twinkle-tray-appx-x64-${{ steps.info.outputs.version }}-${{ github.sha }} path: dist/*-store.appx - name: Build ARM64 Modules if: ${{ env.BRANCH_NAME == 'master' || env.BRANCH_NAME == 'ci-test' }} run: npx electron-rebuild --arch arm64 --types "prod" - name: Build ARM64 AppX if: ${{ env.BRANCH_NAME == 'master' || env.BRANCH_NAME == 'ci-test' }} run: npm exec electron-builder -- --arm64 --win appx --config.extraMetadata.versionBuild="${{ steps.info.outputs.version }}+${{ github.sha }}" --config.extraMetadata.version=${{ steps.date.outputs.time }} --config.extraMetadata.name=twinkle-tray-appx --config.win.artifactName="Twinkle.Tray.v${{ steps.info.outputs.version }}-store-arm64.appx" --config.npmRebuild=false --publish="never" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: actions/upload-artifact@v4 name: Upload ARM64 AppX if: ${{ env.BRANCH_NAME == 'master' || env.BRANCH_NAME == 'ci-test' }} with: name: twinkle-tray-appx-arm64-${{ steps.info.outputs.version }}-${{ github.sha }} path: dist/*-store-arm64.appx ================================================ FILE: .gitignore ================================================ # dependencies node_modules/ # production build/ dist/ # misc .cache .DS_Store .env.local .env.development.local .env.test.local .env.production.local npm-debug.log* yarn-debug.log* yarn-error.log* .idea .log logs/ *.pfx .env cache/ debug.log bin/ ================================================ FILE: .sassrc ================================================ { silenceDeprecations: ["legacy-js-api"] } ================================================ FILE: .vscode/settings.json ================================================ { "files.associations": { "algorithm": "cpp", "array": "cpp", "atomic": "cpp", "bit": "cpp", "cctype": "cpp", "charconv": "cpp", "chrono": "cpp", "clocale": "cpp", "cmath": "cpp", "compare": "cpp", "complex": "cpp", "concepts": "cpp", "condition_variable": "cpp", "coroutine": "cpp", "csignal": "cpp", "cstdarg": "cpp", "cstddef": "cpp", "cstdint": "cpp", "cstdio": "cpp", "cstdlib": "cpp", "cstring": "cpp", "ctime": "cpp", "cwchar": "cpp", "deque": "cpp", "exception": "cpp", "format": "cpp", "forward_list": "cpp", "fstream": "cpp", "functional": "cpp", "initializer_list": "cpp", "iomanip": "cpp", "ios": "cpp", "iosfwd": "cpp", "iostream": "cpp", "istream": "cpp", "iterator": "cpp", "limits": "cpp", "list": "cpp", "locale": "cpp", "map": "cpp", "memory": "cpp", "mutex": "cpp", "new": "cpp", "numeric": "cpp", "optional": "cpp", "ostream": "cpp", "queue": "cpp", "ratio": "cpp", "shared_mutex": "cpp", "sstream": "cpp", "stdexcept": "cpp", "stop_token": "cpp", "streambuf": "cpp", "string": "cpp", "system_error": "cpp", "thread": "cpp", "tuple": "cpp", "type_traits": "cpp", "typeinfo": "cpp", "unordered_map": "cpp", "utility": "cpp", "vector": "cpp", "xfacet": "cpp", "xhash": "cpp", "xiosbase": "cpp", "xlocale": "cpp", "xlocbuf": "cpp", "xlocinfo": "cpp", "xlocmes": "cpp", "xlocmon": "cpp", "xlocnum": "cpp", "xloctime": "cpp", "xmemory": "cpp", "xstddef": "cpp", "xstring": "cpp", "xtr1common": "cpp", "xtree": "cpp", "xutility": "cpp" } } ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019 Xander Frangos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================

Twinkle Tray brightness slider logo

Twinkle Tray

Latest release Total downloads Translations

Twinkle Tray enables brightness control on external displays in Windows 10 & 11. Even though Windows is capable of adjusting the backlight on most monitors, it doesn't support external monitors natively. Windows also lacks any options to manage the brightness of multiple displays. This app inserts a new icon into your system tray, where you can click to have instant access to the brightness levels of all compatible displays. Win 10 brightness slider ## Features - Adds brightness sliders to the system tray, similar to the built-in Windows volume flyout. - Seamlessly blends in with Windows 10 and Windows 11. Uses your Personalization settings to match your taskbar. - Can automatically change monitor brightness depending on the time of day or when idle. - Bind hotkeys to adjust the brightness of specific or all displays. - Normalize backlight across different monitors. - Control DDC/CI features such as contrast. - Starts up with Windows. ### Design & Personalization Twinkle Tray will automatically adjust the look and feel to match your Windows version and preferences. Additional options are available to select the Windows version and theme of your choice. Win 11 brightness slider ## Download **Download the lastest version from [twinkletray.com](https://twinkletray.com/) or the [Releases page](https://github.com/xanderfrangos/twinkle-tray/releases).** Get Twinkle Tray brightness slider from the Microsoft Store ## Install via Package Manager ### Windows Package Manager ```powershell winget install xanderfrangos.twinkletray ``` ### Chocolatey (unofficial) [Chocolatey](https://chocolatey.org/) users can download and install Twinkle Tray from Chocolatey's Community Repository by installing the `twinkle-tray` package: ```powershell choco install twinkle-tray ``` To upgrade to the latest approved package version, run the following command: ```powershell choco upgrade twinkle-tray ``` **This package is not maintained at this repository**. Please do not create issues relating to the package here. Instead, go to the [package page](https://community.chocolatey.org/packages/twinkle-tray) and follow the [Package Triage Process](https://docs.chocolatey.org/en-us/community-repository/users/package-triage-process). ### Scoop (unofficial) [Scoop](https://scoop.sh/) users can download and install Twinkle Tray from Scoop's Extras bucket by installing the `twinkle-tray` package: ```sh scoop bucket add extras scoop install extras/twinkle-tray ``` To upgrade to the latest approved package version, run the following command: ```sh scoop update twinkle-tray ``` **This package is not maintained at this repository**. Please do not create issues relating to the package here. Instead, go to [ScoopInstallers/Extras](https://github.com/ScoopInstaller/Extras) and search for an existing [issue](https://github.com/ScoopInstaller/Extras/issues?q=is%3Aissue+twinkle-tray) or [discussion](https://github.com/ScoopInstaller/Extras/discussions?discussions_q=twinkle-tray) and create a new [issue](https://github.com/ScoopInstaller/Extras/issues/new/choose) or [discussion](https://github.com/ScoopInstaller/Extras/discussions/new/choose) if one does not already exist. ## Usage - Download from the [Releases page](https://github.com/xanderfrangos/twinkle-tray/releases) and run the installer EXE. - Once installation has finished, you should see the Twinkle Tray icon in your system tray. - Click the icon to bring up the Adjust Brightness flyout. - Click away to hide the flyout. - Right-click the system tray icon to quit. ## Compatibility Twinkle Tray uses DDC/CI and WMI to communicate with your monitors. Most monitors offer DDC/CI compatibility, but it may be off by default. Make sure you have the appropriate option(s) enabled on your monitor so that it can work with Twinkle Tray. Refer to your monitor's user manual for more information. **Known issues:** - The AMD Radeon Control Panel can interfere with Twinkle Tray. Ensure "Custom Colors" is not enabled. - VGA/DVI may not be compatible. - USB/Thunderbolt/Surface docks with HDMI or DisplayPort may not be compatible. - DDC/CI features such as brightness control and power state may cause certain models of monitors to behave poorly. This applies to any DDC/CI software, not just Twinkle Tray. If some of your monitors are not being detected, please see [this page](https://github.com/xanderfrangos/twinkle-tray/wiki/Display-Detection-&-Support-Issues) for troubleshooting steps. ## Command Line Arguments Twinkle Tray (v1.13.0+) supports requesting brightness changes from the command line. Twinkle Tray must already be running. One monitor argument and one brightness argument are required. Multiple arguments will override each other. For example: `"%LocalAppData%\Programs\twinkle-tray\Twinkle Tray.exe" --MonitorNum=1 --Offset=-30` will adjust monitor number 1 by -30 brightness. ### Supported args: - `--List` List all displays. *(available in v1.14.0+)* - `--MonitorNum` Select monitor by number. Starts at 1. *Example: `--MonitorNum=2`* - `--MonitorID` Select monitor by internal ID. Partial or whole matches accepted. *Example: `--MonitorID="UID2353"`* - `--All` Flag to select all monitors. - `--Set` Set brightness percentage. *Example: `--Set=95`* - `--Offset` Adjust brightness percentage. *Example: `--Offset=-20`* - `--VCP` Send a specific DDC/CI VCP code and value instead of brightness. The first part is the VCP code (decimal or hexadecimal), and the second is the value. *Example: `--VCP="0xD6:5"`* *(available in v1.14.4+)* - `--Overlay` Flag to show new brightness levels in the overlay *Example: `--Overlay`* - `--Panel` Flag to show new brightness levels in the panel *Example: `--Panel`* *If you are using the Microsoft Store version of Twinkle Tray, you can access Twinkle Tray using the alias `Twinkle-Tray.exe` (v1.17.1+).* ## Localization Thanks to [several contributors](https://github.com/xanderfrangos/twinkle-tray/graphs/contributors), Twinkle Tray is localized for multiple languages. If you'd like to create or update a localization, see [this page](https://github.com/xanderfrangos/twinkle-tray/wiki/Localization-files) for details. Special thanks to [Weblate](https://weblate.org/) for allowing free use of their service. #### Localization progress Translation status ## Build Instructions If you wish to run a development build of Twinkly Tray: - Download or clone. - Install the build tools for [`node-gyp`](https://github.com/nodejs/node-gyp#installation), if not already installed. You may already have these from installing NodeJS. - Run `npm install`. - Run `npm run build` to build an executable or `npm start` to run a development build. *Note: Twinkle Tray must be built on Windows.* ## Special Thanks Twinkle Tray was built using frameworks & libraries such as [Electron](https://electronjs.org/), [Node.js](https://nodejs.org/), [node-ddcci](https://github.com/hensm/node-ddcci), and [win32-displayconfig](). Thanks to Weblate for allowing free use of their service, along with the many contributors to the localizations of Twinkle Tray. The app would not be nearly as popular without all of your help. And thank you for the many donations, small and large, over the years. ## License Copyright © 2020 Xander Frangos Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: package.json ================================================ { "name": "twinkle-tray", "version": "1.17.2", "description": "Manage the brightness of monitors from your system tray", "main": "src/electron.js", "scripts": { "start": "electron . --dev", "parcel": "node src/parcel.js --mode dev", "parcel-build": "node src/parcel.js --mode build", "clean": "npm ci", "dev": "electron . --dev", "electron-build": "electron-builder --x64", "postinstall": "electron-builder install-app-deps", "appx": "npm run parcel-build && electron-builder --x64 -w appx -c.extraMetadata.name=twinkle-tray-appx -c.win.artifactName=\"${productName} v${version}-store.${ext}\"", "appx-unsigned": "npm run parcel-build && electron-builder --x64 -w appx -c.appx.publisher=\"CN=AppModelSamples, OID.2.25.311729368913984317654407730594956997722=1\" -c.extraMetadata.name=twinkle-tray-appx -c.win.artifactName=\"${productName} v${version}-unsigned.${ext}\"", "portable": "npm run parcel-build && electron-builder --x64 -w zip -c.extraMetadata.name=twinkle-tray-portable -c.win.artifactName=\"${productName} v${version}-portable.${ext}\" -c.win.compression=normal", "arm64": "npm run parcel-build && electron-builder --arm64 -c.extraMetadata.name=twinkle-tray-arm64 -c.win.artifactName=\"${productName} v${version}-arm64.${ext}\" -c.win.compression=normal", "rebuild-ddcci-dev": "npm rebuild @hensm/ddcci", "appx-arm64": "npm run parcel-build && electron-builder --arm64 -w appx -c.extraMetadata.name=twinkle-tray-appx -c.win.artifactName=\"${productName} v${version}-store-arm64.${ext}\"", "build": "npm ci & npm run parcel-build && npm run electron-build", "build-all": "npm run build && npm run appx && npm run appx-arm64", "test-wmibridge": "node src/modules/wmi-bridge/example.js" }, "keywords": [ "electron", "react", "brightness", "set-brightness", "windows" ], "author": "Xander Frangos", "license": "MIT", "dependencies": { "@hensm/ddcci": "file:src/modules/node-ddcci", "@paymoapp/active-window": "file:src/modules/node-active-window", "acrylic": "file:src/modules/acrylic", "color": "^4.2.3", "ga4-mp": "^1.0.3", "global-mouse-events": "^1.2.0", "markdown-to-jsx": "^7.5.0", "stackblur-canvas": "^2.7.0", "studio-display-control": "^0.2.0", "suncalc": "^1.9.0", "tt-windows-utils": "file:src/modules/tt-windows-utils", "win32-displayconfig": "file:src/modules/win32-displayconfig", "windows-accent-colors": "^1.0.1", "windows-hdr": "file:src/modules/windows-hdr", "wmi-bridge": "file:src/modules/wmi-bridge", "wmi-client": "^0.5.0" }, "optionalDependencies": { "native-reg": "^1.1.1" }, "build": { "productName": "Twinkle Tray", "appId": "com.xanderfrangos.twinkle-tray", "compression": "normal", "electronLanguages": ["en-US"], "directories": { "buildResources": "resources" }, "files": [ "README.md", "src/electron.js", "src/panel-preload.js", "src/Translate.js", "src/settings-preload.js", "src/intro-preload.js", "src/monitor-rules.json", "src/localization/*", "src/Utils.js", "src/Monitors.js", "src/wmi-bridge-test.js", "src/vcp-codes.js", "src/assets/tray-icons/dark/*.ico", "src/assets/tray-icons/light/*.ico", "build/*", "!node_modules/@hensm/ddcci/build", "node_modules/@hensm/ddcci/build/Release/ddcci.node", "!src/modules/node-ddcci/build", "src/modules/node-ddcci/build/Release/ddcci.node", "!node_modules/node-addon-api/doc", "!node_modules/win32-displayconfig/node_modules*", "!node_modules/global-mouse-events/node_modules", "!node_modules/electron-acrylic-window/node_modules", "!node_modules/tt-windows-utils/node_modules", "!node_modules/windows-accent-colors/node_modules", "!node_modules/**/node-gyp/*", "!node_modules/**/*.ipdb", "!node_modules/**/*.pdb", "!node_modules/**/*.iobj", "!node_modules/**/*.obj", "!node_modules/**/*.lib", "!node_modules/**/*.h", "!node_modules/**/*.md", "!node_modules/**/*.c", "!node_modules/**/*.map", "!node_modules/**/*.log", "!node_modules/**/*.tlog", "!node_modules/**/*.vcxproj", "!node_modules/**/*.filters", "!node_modules/**/wmic_centos_x64", "!node_modules/**/wmic_ubuntu_x64", "!node_modules/sharp/vendor/*", "!node_modules/wmi-bridge/bin/*", "!node_modules/native-reg/prebuilds/*", "node_modules/native-reg/prebuilds/${platform}-${arch}/*", "!node_modules/native-reg/src/*", "!node_modules/acrylic/bin/**/*.node", "!node_modules/tt-windows-utils/bin/**/*.node", "!node_modules/win32-displayconfig/bin/**/*.node", "!node_modules/@paymoapp/active-window/module/*", "!node_modules/@paymoapp/active-window/src/*", "!node_modules/@paymoapp/active-window/build/Release/obj/*", "!node_modules/@paymoapp/active-window/*.json", "node_modules/@paymoapp/active-window/package.json", "!node_modules/iconv-lite", "!node_modules/cacache/*", "!node_modules/path-scurry/*", "!node_modules/tar/*", "!node_modules/@isaacs/*", "!node_modules/are-we-there-yet", "!node_modules/make-fetch-happen/*", "!node_modules/@npmcli/*", "!node_modules/node-gyp/*", "!node_modules/glob", "!node_modules/@pkgjs", "!node_modules/minizlib/*", "!node_modules/usb/libusb", "!node_modules/usb/prebuilds/*", "node_modules/usb/prebuilds/${platform}-${arch}/*" ], "extraResources": [ "node_modules\\wmi-client\\lib\\*", "node_modules\\wmi-client\\scripts\\*", "node_modules\\wmi-client\\index.js", "node_modules\\wmi-client\\package.json", "node_modules\\wmi-client\\.jscsrc" ], "asar": true, "asarUnpack": [ "node_modules\\wmi-client\\**\\*", "node_modules\\sharp\\**\\*", "**\\*.node", "src\\assets\\tray-icons\\dark\\*.ico", "src\\assets\\tray-icons\\light\\*.ico", "src\\assets\\logo.ico" ], "win": { "target": [ "nsis" ], "artifactName": "${productName} v${version}.${ext}", "icon": "src/assets/logo.ico", "legalTrademarks": "Xander Frangos" }, "appx": { "publisherDisplayName": "Xander Frangos", "applicationId": "TwinkleTray", "displayName": "Twinkle Tray", "identityName": "38002AlexanderFrangos.TwinkleTray", "publisher": "CN=B8E9A58B-32A7-4C6C-A474-D4BE2A3CEAD8", "showNameOnTiles": false, "backgroundColor": "#6b479c", "addAutoLaunchExtension": true, "customExtensionsPath": "resources/appx/extensions.xml" }, "nsis": { "deleteAppDataOnUninstall": true, "include": "resources/nsis/installer.nsh", "warningsAsErrors": false } }, "devDependencies": { "@babel/core": "^7.23.6", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/preset-env": "^7.23.6", "@babel/preset-react": "^7.23.3", "@babel/runtime": "^7.23.6", "bindings": "1.5.0", "cross-env": "^7.0.3", "electron": "^39.2.6", "electron-builder": "26.3.2", "node-addon-api": "^8.2.2", "node-gyp": "^12.1.0", "parcel-bundler": "^1.12.5", "react": "18.3.1", "react-beautiful-dnd": "^13.1.1", "react-dom": "18.3.1", "sass": "^1.54.0" }, "overrides": { "node-gyp": "$node-gyp", "bindings@<1.5.0": "1.5.0", "node-addon-api@<8.2.2": "8.2.2", "node-active-window": { "node-gyp": "$node-gyp", "bindings": "$bindings", "node-addon-api": "$node-addon-api" } } } ================================================ FILE: resources/appx/extensions.xml ================================================ ================================================ FILE: resources/nsis/installer.nsh ================================================ !macro customUnInstall DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "electron.app.Twinkle Tray" !macroend ================================================ FILE: src/Monitors.js ================================================ const tag = "\x1b[47m M \x1b[0m"; const oLog = console.log console.log = (...args) => { args.unshift(tag); oLog(...args) } console.log("Monitors.js starting. If you see this again, something bad happened!") const w32disp = require("win32-displayconfig"); const wmibridge = require("wmi-bridge"); const hdr = require("windows-hdr"); const { exec } = require('child_process'); require("os").setPriority(0, require("os").constants.priority.PRIORITY_BELOW_NORMAL) let lastDDCCIList = [] let lastRefresh = {} let lastWin32 = {} let lastWMI = {} let lastHDR = {} function deepCopy(obj) { try { return JSON.parse(JSON.stringify(obj)) } catch(e) { return false } } process.on('message', async (data) => { try { if (data.type === "refreshMonitors") { if(data.clearCache) { vcpCache = {} monitorReports = {} monitorReportsRaw = {} } refreshMonitors(data.fullRefresh, data.ddcciType).then((results) => { lastRefresh = deepCopy(results) process.send({ type: 'refreshMonitors', monitors: results }) }) } else if (data.type === "brightness") { setBrightness(data.brightness, data.id) } else if (data.type === "sdr") { setSDRBrightness(data.brightness, data.id) } else if (data.type === "settings") { settings = data.settings // Overrides if (settings?.disableAppleStudio) appleStudioUnavailable = true; if (settings?.disableWMIC) wmicUnavailable = true; if (settings?.disableWMI) wmiFailed = true; if (settings?.disableWin32) win32Failed = true; } else if (data.type === "ddcBrightnessVCPs") { ddcBrightnessVCPs = data.ddcBrightnessVCPs // Update brightnessType for all monitors when user changes VCP settings if (monitors) { for (const hwid2 in monitors) { if (monitors[hwid2].type === "ddcci") { const hwid = monitors[hwid2].hwid if (hwid) { if (ddcBrightnessVCPs[hwid[1]]) { // Custom VCP code set - use it (already parsed as int in electron.js) const vcpCode = ddcBrightnessVCPs[hwid[1]] if (!isNaN(vcpCode) && vcpCode >= 0 && vcpCode <= 0xFF) { monitors[hwid2].brightnessType = vcpCode } else { // Invalid VCP code, fall back to default monitors[hwid2].brightnessType = 0x10 } } else { // No custom VCP - reset to default (0x10 = 16) monitors[hwid2].brightnessType = 0x10 } } } } } } else if (data.type === "localization") { localization = data.localization } else if (data.type === "vcp") { setVCP(data.monitor, data.code, data.value) } else if (data.type === "flushvcp") { vcpCache = {} monitorReports = {} monitorReportsRaw = {} ddcci._clearDisplayCache() } else if (data.type === "wmi-bridge-ok") { canUseWmiBridge = data.value } else if (data.type === "getVCP") { getDDCCI() const vcp = await checkVCP(data.monitor, data.code) process.send({ type: `getVCP::${data.monitor}::${data.code}`, monitor: data.monitor, code: data.code, value: vcp }) } else if (data.type === "getReport") { process.send({ type: `getReport`, report: { lastDDCCIList, lastWMI, lastWin32, lastHDR, monitorsAppleStudio, monitorReports, monitorReportsRaw, lastRefresh, settings } }) } } catch (e) { console.log(e) } }) let isDev = (process.argv.indexOf("--isdev=true") >= 0) let skipTest = (process.argv.indexOf("--skiptest=true") >= 0) let monitors = false let monitorNames = [] let monitorsAppleStudio = {} let monitorsWin32 = {} let monitorReports = {} let monitorReportsRaw = {} let settings = { order: [] } let localization = {} let canUseWmiBridge = false let ddcBrightnessVCPs = {} let busyLevel = 0 refreshMonitors = async (fullRefresh = false, ddcciType = "default", alwaysSendUpdate = false) => { try { if ((busyLevel > 0 && !fullRefresh) || (busyLevel > 0 && fullRefresh)) { console.log("Thread busy. Cancelling refresh.") return false } busyLevel = (fullRefresh ? 2 : 1) if (!monitors || fullRefresh) { const foundMonitors = await getAllMonitors(determineDDCCIMethod()) monitors = foundMonitors } else { let startTime = process.hrtime() // DDC/CI try { if (settings?.getDDCBrightnessUpdates) { if(!getDDCCI()) { ddcci._refresh(determineDDCCIMethod(), true, !settings.disableHighLevel) } for (const hwid2 in monitors) { if (monitors[hwid2].type === "ddcci" && monitors[hwid2].brightnessType) { const monitor = await getBrightnessDDC(monitors[hwid2]) monitors[hwid2] = monitor } } console.log(`getBrightnessDDC() Total: ${process.hrtime(startTime)[1] / 1000000}ms`) } } catch (e) { console.log("\x1b[41m" + "getBrightnessDDC() failed!" + "\x1b[0m", e) } // WMIC (Windows 10) if (!wmicUnavailable) { try { startTime = process.hrtime.bigint() const wmiBrightness = await getBrightnessWMIC() console.log(`getBrightnessWMIC() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) if (wmiBrightness) { updateDisplay(monitors, wmiBrightness.hwid[2], wmiBrightness) // If Win32 doesn't find the internal display, hide it. if (settings?.hideClosedLid && Object.keys(monitorsWin32).indexOf(wmiBrightness.hwid[2]) < 0) { updateDisplay(monitors, wmiBrightness.hwid[2], { type: "none" }) } } } catch (e) { console.log("\x1b[41m" + "getBrightnessWMIC() failed!" + "\x1b[0m", e) } } // WMI if (canUseWmiBridge && !wmiFailed && wmicUnavailable) { try { startTime = process.hrtime.bigint() const wmiBrightness = await getBrightnessWMI() if (wmiBrightness) { updateDisplay(monitors, wmiBrightness.hwid[2], wmiBrightness) // If Win32 doesn't find the internal display, hide it. if (settings?.hideClosedLid && Object.keys(monitorsWin32).indexOf(wmiBrightness.hwid[2]) < 0) { updateDisplay(monitors, wmiBrightness.hwid[2], { type: "none" }) } } console.log(`getBrightnessWMI() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) } catch (e) { console.log("\x1b[41m" + "getBrightnessWMI() failed!" + "\x1b[0m", e) } } // Apple Studio displays if (!appleStudioUnavailable) { try { startTime = process.hrtime.bigint() monitorsAppleStudio = await getStudioDisplay(monitors); console.log(`getStudioDisplay() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) } catch (e) { console.log("\x1b[41m" + "getStudioDisplay() failed!" + "\x1b[0m", e) } } // HDR if (!settings?.disableHDR) { try { startTime = process.hrtime.bigint() monitorsHDR = await getHDRDisplays(monitors); console.log(`getHDRDisplays() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) } catch (e) { console.log("\x1b[41m" + "getHDRDisplays() failed!" + "\x1b[0m", e) } } // Hide internal if (settings?.hideClosedLid) { const wmiMonitor = Object.values(monitors).find(mon => mon.type === "wmi") if (wmiMonitor && !monitorsWin32[wmiMonitor.hwid[2]]) { updateDisplay(monitors, wmiMonitor.hwid[2], { type: "none" }) } } } } catch (e) { console.log(e) } busyLevel = 0 return monitors } getAllMonitors = async (ddcciMethod = "default") => { const foundMonitors = {} let startTime = process.hrtime.bigint() let fullStartTime = process.hrtime.bigint() // List via WMIC (Windows 10) if (!wmicUnavailable) { try { const monitorsWMIC = await getMonitorsWMIC() console.log(`getMonitorsWMIC() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) for (const hwid2 in monitorsWMIC) { const monitor = monitorsWMIC[hwid2] updateDisplay(foundMonitors, hwid2, monitor) } } catch (e) { console.log("\x1b[41m" + "getMonitorsWMIC() failed!" + "\x1b[0m", e) } } // List via WMI if (canUseWmiBridge && !wmiFailed && wmicUnavailable) { try { const monitorsWMI = await getMonitorsWMI() console.log(`getMonitorsWMI() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) for (const hwid2 in monitorsWMI) { const monitor = monitorsWMI[hwid2] updateDisplay(foundMonitors, hwid2, monitor) } } catch (e) { console.log("\x1b[41m" + "getMonitorsWMI() failed!" + "\x1b[0m", e) } } else if (wmiFailed) { console.log("getMonitorsWMI() skipped due to previous failure.") } // List via Win32 (more details) if (!win32Failed) { try { startTime = process.hrtime.bigint() monitorsWin32 = await getMonitorsWin32() console.log(`getMonitorsWin32() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) for (const hwid2 in monitorsWin32) { const monitor = monitorsWin32[hwid2] updateDisplay(foundMonitors, hwid2, monitor) } } catch (e) { console.log("\x1b[41m" + "getMonitorsWin32() failed!" + "\x1b[0m", e) } } else { console.log("getMonitorsWin32() skipped due to previous failure.") } // List Apple Studio displays if (!appleStudioUnavailable) { try { startTime = process.hrtime.bigint() monitorsAppleStudio = await getStudioDisplay(foundMonitors); console.log(`getStudioDisplay() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) } catch (e) { console.log("\x1b[41m" + "getStudioDisplay() failed!" + "\x1b[0m", e) } } else { console.log("getStudioDisplay() skipped due to previous failure.") } // DDC/CI Brightness + Features try { startTime = process.hrtime.bigint() const featuresList = await getFeaturesDDC(ddcciMethod, false) for (const hwid2 in featuresList) { const monitor = featuresList[hwid2] const { features, id, hwid, vcpCodes, path, ddcciSupported, highLevelSupported } = monitor const brightnessType = await determineBrightnessVCPCode(id) let ddcciInfo = { id: id, key: hwid2, hwid, path, ddcciSupported, highLevelSupported, features: features, vcpCodes: vcpCodes, type: ((ddcciSupported || highLevelSupported?.brightness) && brightnessType ? "ddcci" : "none"), min: 0, max: 100, brightnessType: brightnessType, brightnessValues: (features[brightnessType] ? features[brightnessType] : [50, 100]) } let brightness; if(!settings.disableHighLevel && monitor.highLevelSupported?.brightness && !(brightnessType > 0x10)) { brightness = await getHighLevelBrightness(id) } else { brightness = await checkVCP(id, parseInt(brightnessType)) } // Force lower max brightness for testing if(brightness?.[1]) { if(settings.debugForceBrightnessMax) brightness[1] = settings.debugForceBrightnessMax } if(brightness) { ddcciInfo.brightnessValues = brightness features[vcpStr(brightnessType)] = brightness } ddcciInfo.brightnessRaw = ddcciInfo.brightnessValues[0] ddcciInfo.brightnessMax = ddcciInfo.brightnessValues[1] // Get normalization info ddcciInfo = applyRemap(ddcciInfo) // Unnormalize brightness ddcciInfo.brightness = normalizeBrightness(ddcciInfo.brightnessRaw, true, ddcciInfo.min, ddcciInfo.max) updateDisplay(foundMonitors, hwid2, ddcciInfo) } console.log(`getFeaturesDDC() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) } catch (e) { console.log("\x1b[41m" + "getFeaturesDDC() failed!" + "\x1b[0m", e) } if (!wmicUnavailable) { try { startTime = process.hrtime.bigint() const wmiBrightness = await getBrightnessWMIC() console.log(`getBrightnessWMIC() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) if (wmiBrightness) { updateDisplay(foundMonitors, wmiBrightness.hwid[2], wmiBrightness) // If Win32 doesn't find the internal display, hide it. if (settings?.hideClosedLid && Object.keys(monitorsWin32).indexOf(wmiBrightness.hwid[2]) < 0) { updateDisplay(foundMonitors, wmiBrightness.hwid[2], { type: "none" }) } } } catch (e) { console.log("\x1b[41m" + "getBrightnessWMIC() failed!" + "\x1b[0m", e) } } // WMI Brightness if (canUseWmiBridge && !wmiFailed && wmicUnavailable) { try { startTime = process.hrtime.bigint() const wmiBrightness = await getBrightnessWMI() console.log(`getBrightnessWMI() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) if (wmiBrightness) { updateDisplay(foundMonitors, wmiBrightness.hwid[2], wmiBrightness) // If Win32 doesn't find the internal display, hide it. if (settings?.hideClosedLid && Object.keys(monitorsWin32).indexOf(wmiBrightness.hwid[2]) < 0) { updateDisplay(foundMonitors, wmiBrightness.hwid[2], { type: "none" }) } } } catch (e) { console.log("\x1b[41m" + "getBrightnessWMI() failed!" + "\x1b[0m", e) } } else if (wmiFailed) { console.log("getBrightnessWMI() skipped due to previous failure.") } // HDR if (!settings.disableHDR) { try { startTime = process.hrtime.bigint() monitorsHDR = await getHDRDisplays(foundMonitors); console.log(`getHDRDisplays() Total: ${(startTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) } catch (e) { console.log("\x1b[41m" + "getHDRDisplays() failed!" + "\x1b[0m", e) } } // Hide internal if (settings?.hideClosedLid) { const wmiMonitor = Object.values(foundMonitors).find(mon => mon.type === "wmi") if (wmiMonitor && !monitorsWin32[wmiMonitor.hwid[2]]) { updateDisplay(foundMonitors, wmiMonitor.hwid[2], { type: "none" }) } } // Finally, fix names/num try { let idx = 0 for (const hwid2 in foundMonitors) { if (!foundMonitors[hwid2].name) foundMonitors[hwid2].name = `${localization.GENERIC_DISPLAY_SINGLE} ${idx + 1}`; foundMonitors[hwid2].num = idx; idx++ } } catch (e) { console.log("\x1b[41m" + "Fixing names failed!" + "\x1b[0m", e) } console.log(`getAllMonitors() total: ${(fullStartTime - process.hrtime.bigint()) / BigInt(-1000000)}ms`) try { console.log(`Monitors found: ${Object.keys(foundMonitors)}`) } catch (e) { } return foundMonitors } function determineDDCCIMethod() { let ddcciMethod = (isFastFine ? "fast" : "accurate") const savedMethod = settings?.preferredDDCCIMethod const ddcciMethodValues = ["fast", "accurate", "no-validation", "legacy"] if(savedMethod && ddcciMethodValues.indexOf(savedMethod) >= 0) { ddcciMethod = savedMethod } return ddcciMethod } let appleStudioUnavailable = false getStudioDisplay = async (monitors) => { try { const sdctl = require("studio-display-control") const displays = {} let count = 0 for (const display of sdctl.getDisplays()) { const serial = await display.getSerialNumber(); const hwid = [ "\\\\?\\DISPLAY", "APPAE3A", `APLSTD-${serial}-NUM${count}` ] updateDisplay(monitors, hwid[2], { name: "Apple Studio Display", type: "studio-display", key: hwid[2], id: `\\\\?\\${hwid[0]}#${hwid[1]}#${hwid[2]}`, hwid, serial, brightness: await display.getBrightness() }); displays[hwid[2]] = display count++ } return displays } catch (e) { console.log("\x1b[41m" + "getStudioDisplay(): failed to access Studio Display" + "\x1b[0m", e) } return {} } setStudioDisplayBrightness = async (serial, brightness) => { try { const sdctl = require("studio-display-control") for (const monitor of sdctl.getDisplays()) { const s = await monitor.getSerialNumber(); if (s === serial) { await monitor.setBrightness(brightness); } } } catch (e) { console.log("\x1b[41m" + "setStudioDisplayBrightness(): failed to set brightness" + "\x1b[0m", e) } } getHDRDisplays = async (monitors) => { try { const displays = hdr.getDisplays() lastHDR = displays for(const display of displays) { const hwid = display.path.split("#") const newDisplay = { key: hwid[2], id: display.path, hwid, sdrNits: display.nits, sdrLevel: parseInt((display.nits - 80) / 4), hdr: (display.hdrActive ? "active" : display.hdrEnabled ? "supported" : "unsupported") } if(display.name) { newDisplay.name = display.name } updateDisplay(monitors, hwid[2], newDisplay); displays[hwid[2]] = display } } catch(e) { console.log("\x1b[41m" + "getHDRDisplays(): failed to access displays" + "\x1b[0m", e) } return monitors } let wmiFailed = false getMonitorsWMI = () => { return new Promise(async (resolve, reject) => { const foundMonitors = {} try { const timeout = setTimeout(() => { wmiFailed = true; console.log("getMonitorsWMI Timed out."); reject({}) }, 4000) const wmiMonitors = await wmibridge.getMonitors(); if (wmiMonitors.failed) { // Something went wrong console.log("\x1b[41m" + "Recieved FAILED response from getMonitors()" + "\x1b[0m") clearTimeout(timeout) resolve(foundMonitor) } else { // Sort through results for (let monitorHWID in wmiMonitors) { const monitor = wmiMonitors[monitorHWID] if (!monitor.InstanceName) continue; let hwid = readInstanceName(monitor.InstanceName) hwid[2] = hwid[2].split("_")[0] const wmiInfo = { id: `\\\\?\\${hwid[0]}#${hwid[1]}#${hwid[2]}`, key: hwid[2], hwid: hwid, serial: monitor.SerialNumberID } if (monitor.UserFriendlyName !== null && monitor.UserFriendlyName !== "") { wmiInfo.name = monitor.UserFriendlyName } foundMonitors[hwid[2]] = wmiInfo } clearTimeout(timeout) } } catch (e) { console.log(`getMonitorsWMI: Failed to get all monitors.`) console.log(e) } lastWMI = deepCopy(foundMonitors) resolve(foundMonitors) }) } let win32Failed = false getMonitorsWin32 = () => { let foundDisplays = {} return new Promise(async (resolve, reject) => { try { const timeout = setTimeout(() => { win32Failed = true; console.log("getMonitorsWin32 Timed out."); reject({}) }, 4000) let displays = [] const displayConfig = await w32disp.extractDisplayConfig() // Filter results for (const display of displayConfig) { // Must be an active display if(display.inUse) { displays.push(display) } } // Prepare results for (const monitor of displays) { const hwid = monitor.devicePath.split("#") hwid[2] = hwid[2].split("_")[0] const win32Info = { id: `${hwid[0]}#${hwid[1]}#${hwid[2]}`, key: hwid[2], connector: monitor.outputTechnology, hwid: hwid, sourceID: monitor.sourceConfigId?.id, scaling: monitor.scaling, bounds: monitor.sourceMode } if (monitor.displayName?.length > 0) { win32Info.name = monitor.displayName; } foundDisplays[hwid[2]] = win32Info } // Return prepared results clearTimeout(timeout) } catch (e) { console.log(`getMonitorsWin32: Failed to get all monitors. (L2)`, e) } lastWin32 = deepCopy(foundDisplays) resolve(foundDisplays) }) } getFeaturesDDC = (ddcciMethod = "accurate") => { const monitorFeatures = {} return new Promise(async (resolve, reject) => { try { const timeout = setTimeout(() => { console.log("getFeaturesDDC Timed out."); reject({}) }, 80000) getDDCCI() await wait(10) // Sometimes the handles returned are NULL, so we should try again. let tmpDdcciMonitors = ddcci.getAllMonitors(ddcciMethod, true, !settings.disableHighLevel) if(tmpDdcciMonitors) { let doRetry = false for(const monitor of tmpDdcciMonitors) { if(monitor.handleIsValid === false) { doRetry = monitor break } } if(doRetry) { console.log(`DDC/CI results contain a null handle (${doRetry?.deviceKey}). Trying again.`) await wait(200) tmpDdcciMonitors = ddcci.getAllMonitors(ddcciMethod, true, !settings.disableHighLevel) for(const monitor of tmpDdcciMonitors) { if(monitor.handleIsValid === false) { console.log(`DDC/CI results still contain a null handle (${doRetry?.deviceKey}). Continuing anyway.`) break } } } } const ddcciMonitors = tmpDdcciMonitors lastDDCCIList = ddcciMonitors for (let monitor of ddcciMonitors) { const id = monitor.deviceKey const featureTimeout = setTimeout(() => { console.log("getFeaturesDDC Timed out on monitor:", id); reject({}) }, 15000) const hwid = id.split("#") let features = {} // Apply capabilities report, if available. if(monitor.capabilities && !monitorReports[id]) { monitorReports[id] = monitor.capabilities } if(monitor.ddcciSupported) { await wait(10) features = await checkMonitorFeatures(id, false, ddcciMethod) } monitorFeatures[hwid[2]] = { id: `${hwid[0]}#${hwid[1]}#${hwid[2]}`, hwid, features, ddcciSupported: monitor.ddcciSupported, highLevelSupported: { brightness: monitor.hlBrightnessSupported, contrast: monitor.hlContrastSupported }, path: monitor.fullName, vcpCodes: (monitorReports[id] ? monitorReports[id] : {} ) } clearTimeout(featureTimeout) } clearTimeout(timeout) } catch (e) { console.log(`getFeaturesDDC: Failed to get features.`) console.log(e) } resolve(monitorFeatures) }) } checkMonitorFeatures = async (monitor, skipCache = false, ddcciMethod = "accurate") => { return new Promise(async (resolve, reject) => { const features = {} try { const hwid = monitor.split("#") // Detect valid VCP codes for display if not already available try { if(ddcciMethod === "accurate" && !monitorReports[monitor]) { const reportRaw = ddcci.getCapabilitiesRaw(monitor) if(reportRaw) { monitorReportsRaw[monitor] = reportRaw const report = ddcci._parseCapabilitiesString(reportRaw) if(report && Object.keys(report)?.length > 0) { monitorReports[monitor] = report } } } } catch(e) { console.log("Couldn't get capabilities report for monitor " + monitor) } let getAllValues = false if(getAllValues && monitorReports[monitor]) { for(const code in monitorReports[monitor]) { features[vcpStr(code)] = await checkVCP(monitor, code) } } else { // Get custom DDC/CI features const settingsFeatures = settings?.monitorFeatures?.[hwid[1]] if(settingsFeatures) { for(const vcp in settingsFeatures) { if(ddcBrightnessVCPs[hwid[1]] && vcp == ddcBrightnessVCPs[hwid[1]]) { continue; // Skip if custom brightness } if(settingsFeatures[vcp]) { features[vcpStr(vcp)] = await checkVCPIfEnabled(monitor, parseInt(vcp), vcp, skipCache) } } } // Capabilities report allows us to skip this for unsupported codes, generally features["0x10"] = await checkVCPIfEnabled(monitor, 0x10, "luminance", skipCache) features["0x13"] = await checkVCPIfEnabled(monitor, 0x13, "brightness", skipCache) features["0x12"] = await checkVCPIfEnabled(monitor, 0x12, "contrast", skipCache) features["0xD6"] = await checkVCPIfEnabled(monitor, 0xD6, "powerState", skipCache) features["0x60"] = await checkVCPIfEnabled(monitor, 0x60, "inputControls", skipCache) features["0x62"] = await checkVCPIfEnabled(monitor, 0x62, "volume", skipCache) } } catch (e) { console.log(e) } resolve(features) }) } determineBrightnessVCPCode = async (monitor) => { const hwid = monitor.split("#") if(ddcBrightnessVCPs?.[hwid[1]]) { return parseInt(ddcBrightnessVCPs[hwid[1]]) } if(await checkIfVCPSupported(monitor, 0x10)) { return 0x10 // luminance } if(await checkIfVCPSupported(monitor, 0x13)) { return 0x13 // brightness } if(await checkIfVCPSupported(monitor, 0x6B)) { return 0x6b // backlight level white } if(await checkIfVCPSupported(monitor, 0x12)) { return 0x12 // contrast } return false } getBrightnessWMI = () => { // Request WMI monitors. return new Promise(async (resolve, reject) => { try { const timeout = setTimeout(() => { console.log("getBrightnessWMI Timed out."); reject(false) }, 4000) const monitor = await wmibridge.getBrightness(); if (monitor.failed) { // Something went wrong clearTimeout(timeout) resolve(false) } else { let hwid = readInstanceName(monitor.InstanceName) hwid[2] = hwid[2].split("_")[0] let wmiInfo = { id: `\\\\?\\${hwid[0]}#${hwid[1]}#${hwid[2]}`, brightness: monitor.Brightness, hwid: hwid, min: 0, max: 100, type: 'wmi', } // Get normalization info wmiInfo = applyRemap(wmiInfo) // Unnormalize brightness wmiInfo.brightnessRaw = monitor.Brightness wmiInfo.brightness = normalizeBrightness(wmiInfo.brightness, true, wmiInfo.min, wmiInfo.max) clearTimeout(timeout) resolve(wmiInfo) } } catch (e) { console.log(e) resolve(false) } }) } getBrightnessDDC = (monitorObj) => { return new Promise(async (resolve, reject) => { let monitor = Object.assign({}, monitorObj) try { const timeout = setTimeout(() => { console.log("getBrightnessDDC Timed out."); reject({}) }, 8000) const ddcciPath = monitor.hwid.join("#") // If brightness is not supported, stop if (!monitor?.brightnessType) { clearTimeout(timeout) resolve(monitor) return false } // Determine / get brightness let brightnessValues = await checkVCP(ddcciPath, monitor.brightnessType) // If something goes wrong and there are previous values, use those if (!brightnessValues) { console.log(`\x1b[41mNO BRIGHTNESS VALUES AVAILABLE FOR ${monitorObj.hwid[1]}\x1b[0m`) if (monitor.brightnessRaw !== undefined && monitor.brightnessMax !== undefined) { console.log("\x1b[41mUSING PREVIOUS VALUES\x1b[0m") brightnessValues = [monitor.brightnessRaw, monitor.brightnessMax] } else if (vcpCache[monitor] && vcpCache[monitor]["vcp_" + 0x10]) { console.log("\x1b[41mUSING VCP CACHE\x1b[0m") brightnessValues = vcpCache[monitor]["vcp_" + 0x10]; } else { console.log("CATASTROPHIC FAILURE", monitor) // Catastrophic failure. Revert to defaults. brightnessValues = [50, 100] } } monitor.brightness = brightnessValues[0] * (100 / (brightnessValues[1] || 100)) monitor.brightnessMax = (brightnessValues[1] || 100) monitor.brightnessRaw = brightnessValues[0] // Raw value from DDC/CI. Not normalized or adjusted. // Get normalization info monitor = applyRemap(monitor) // Unnormalize brightness monitor.brightness = normalizeBrightness(monitor.brightness, true, monitor.min, monitor.max) // Get custom DDC/CI features const settingsFeatures = settings?.monitorFeatures?.[monitor.hwid[1]] if(settingsFeatures) { for(const vcp in settingsFeatures) { if(vcp == monitor.brightnessType) { continue; // Skip brightness } if(settingsFeatures[vcp]) { monitor.features[vcpStr(vcp)] = await checkVCP(monitor.id, parseInt(vcp)) } } } clearTimeout(timeout) resolve(monitor) } catch (e) { console.log("updateBrightnessDDC: Couldn't get DDC/CI brightness.", e) resolve(monitorObj) } }) } updateDisplay = (monitors, hwid2, info = {}) => { if (!monitors[hwid2]) { monitors[hwid2] = { id: null, key: null, num: null, brightness: 50, brightnessMax: 100, brightnessRaw: 50, type: "none", connector: "unknown", min: 0, max: 100, hwid: [], name: null, serial: null } } Object.assign(monitors[hwid2], info) return true } function setSDRBrightness(brightness, id) { if(settings.disableHDR) return false; try { console.log("sdr", brightness, id) return hdr.setSDRBrightness(id, (brightness * 0.01 * 400) + 80) } catch(e) { console.log(`Couldn't update SDR brightness! [${id}]`, e); return false } } function setBrightness(brightness, id) { try { if (id) { let monitor = Object.values(monitors).find(mon => mon.id?.indexOf(id) >= 0) if(monitor) { monitor.brightness = brightness // Check if user has set a custom brightness VCP code for this monitor const hasCustomBrightnessVCP = monitor.hwid && ddcBrightnessVCPs[monitor.hwid[1]] if (monitor.type == "studio-display") { setStudioDisplayBrightness(monitor.serial, brightness) } else if(!settings.disableHighLevel && monitor.highLevelSupported?.brightness && !hasCustomBrightnessVCP) { setHighLevelBrightness(monitor.hwid.join("#"), brightness) } else { setVCP(monitor.hwid.join("#"), monitor.brightnessType, brightness) } // Update tracked brightness values const brightnessRaw = parseInt(brightness) monitor.brightness = brightnessRaw * (100 / (monitor.brightnessMax || 100)) monitor.brightnessRaw = brightnessRaw if(monitor.brightnessValues) monitor.brightnessValues[0] = brightnessRaw; } } else { let monitor = Object.values(monitors).find(mon => mon.type == "wmi") monitor.brightness = brightness monitor.brightnessRaw = brightness if (!canUseWmiBridge || wmiFailed) { // If native WMI is disabled, fall back to old method exec(`powershell.exe -NoProfile (Get-WmiObject -Namespace root\\wmi -Class WmiMonitorBrightnessMethods).wmisetbrightness(0, ${brightness})"`) } else { // Set brightness via native WMI wmibridge.setBrightness(brightness); } } } catch (e) { console.log(`Couldn't update brightness! [${id}]`); console.log(monitors) console.log(e) } } let vcpCache = {} async function checkVCPIfEnabled(monitor, code, setting, skipCache = false) { const vcpString = vcpStr(code) if(!code || code == "0x0") return false; try { const hwid = monitor.split("#") const userEnabledFeature = settings?.monitorFeatures?.[hwid[1]]?.[vcpString] const isInReport = monitorReports[monitor]?.[vcpString] ? true : false const hasReport = monitorReports[monitor] && Object.keys(monitorReports[monitor])?.length > 0 ? true : false if (hasReport && !isInReport) return false; // If we previously saw that a feature was supported, we shouldn't have to check again. if ((!skipCache || !userEnabledFeature) && vcpCache[monitor] && vcpCache[monitor]["vcp_" + vcpString]) return vcpCache[monitor]["vcp_" + vcpString]; const vcpResult = await checkVCP(monitor, code) return vcpResult } catch (e) { console.log(`Error reading VCP code (if enabled) ${vcpString} for ${monitor}`, e) // Since it failed, let's check for an existing value first if(vcpCache[monitor]?.["vcp_" + vcpString]) { return vcpCache[monitor]["vcp_" + vcpString] } // Cached value can't be used, so we return false return false } } async function checkIfVCPSupported(monitor, code) { const vcpString = vcpStr(code) if(!code || code == "0x0") return false; try { const isInReport = monitorReports[monitor]?.[vcpString] ? true : false const hasReport = monitorReports[monitor] && Object.keys(monitorReports[monitor])?.length > 0 ? true : false if (hasReport && !isInReport) return false; // If we previously saw that a feature was supported, we shouldn't have to check again. if (vcpCache[monitor] && vcpCache[monitor]["vcp_" + vcpString]) return true; const vcpResult = await checkVCPIfEnabled(monitor, code) return (vcpResult ? true : false) } catch (e) { console.log(`Error checking VCP code support ${vcpString} for ${monitor}`, e) return false } } async function checkVCP(monitor, code, skipCacheWrite = false) { const vcpString = vcpStr(code) if(!code || code == "0x0") return false; try { let result = ddcci._getVCP(monitor, parseInt(vcpString)) if (code === 96) return ddcci.getMonitorInputs(monitor) if (!skipCacheWrite) { if (!vcpCache[monitor]) vcpCache[monitor] = {}; vcpCache[monitor]["vcp_" + vcpString] = result } if(settings.debugForceBrightnessMax && vcpString == "0x10") result[1] = settings.debugForceBrightnessMax; // Force lower max brightness for testing await wait(parseInt(settings?.checkVCPWaitMS || 20)) return result } catch (e) { let reason = e if(e.message.indexOf("the I2C bus") > 0) reason = "I2C bus error"; if(e.message.indexOf("does not support") > 0) reason = "VCP code unsupported"; console.log(`Error reading VCP code ${vcpString} for ${monitor}. Reason: ${reason}`) // Since it failed, let's check for an existing value first if(vcpCache[monitor]?.["vcp_" + vcpString]) { return vcpCache[monitor]["vcp_" + vcpString] } // Cached value can't be used, so we return false return false } } async function setVCP(monitor, code, value) { if(busyLevel > 0) while(busyLevel > 0) { await wait(100) } // Wait until no longer busy try { const vcpString = vcpStr(code) let result = ddcci._setVCP(monitor, code, (value * 1)) if (vcpCache[monitor]?.["vcp_" + vcpString]) { vcpCache[monitor]["vcp_" + vcpString][0] = (value * 1) } const hwid = monitor.split("#") if(monitors[hwid[2]]?.features?.[vcpString]) { monitors[hwid[2]].features[vcpString][0] = parseInt(value) } return result } catch (e) { return false } } async function getHighLevelBrightness(monitor) { try { let result = ddcci._getHighLevelBrightness(monitor) return result } catch (e) { console.log(e) return false } } async function setHighLevelBrightness(monitor, value) { if(busyLevel > 0) while(busyLevel > 0) { await wait(100) } // Wait until no longer busy try { let result = ddcci._setHighLevelBrightness(monitor, value) return result } catch (e) { console.log(e) return false } } function normalizeBrightness(brightness, unnormalize = false, min = 0, max = 100) { return brightness // Disabled because it wasn't working // Clean this up later // Really // Do it let level = brightness if (level > 100) level = 100; if (level < 0) level = 0; if (min > 0 || max < 100) { let out = level if (!unnormalize) { // Normalize out = (min + ((level / 100) * (max - min))) } else { // Unnormalize out = ((level - min) * (100 / (max - min))) } if (out > 100) out = 100; if (out < 0) out = 0; return Math.round(out) } else { return level } } function applyRemap(monitor) { if (settings.remaps) { for (let remapName in settings.remaps) { if (remapName == monitor.name || remapName == monitor.id) { let remap = settings.remaps[remapName] monitor.min = remap.min monitor.max = remap.max // Stop if using new scheme if (remapName == monitor.id) return monitor; } } } if (typeof monitor.min === "undefined") monitor.min = 0; if (typeof monitor.max === "undefined") monitor.max = 100; return monitor } function readInstanceName(insName) { return (insName ? insName.replace(/&/g, '&').split("\\") : undefined) } function parseWMIString(str) { if (str === null) return str; let hexed = str.replace('{', '').replace('}', '').replace(/;0/g, ';32') var decoded = ''; var split = hexed.split(';') for (var i = 0; (i < split.length); i++) decoded += String.fromCharCode(parseInt(split[i], 10)); decoded = decoded.trim() return decoded; } let ddcci = false function getDDCCI() { if (ddcci) return false; try { ddcci = require("@hensm/ddcci"); if(isDev) ddcci._setLogLevel(2); return true; } catch (e) { console.log('Couldn\'t start DDC/CI', e); return false; } } let wmicUnavailable = false let wmi = false // WMIC function getWMIC() { if (wmi) return true; let WmiClient = false if (!require('fs').existsSync(process.env.SystemRoot + "\\System32\\Wbem\\WMIC.exe")) { console.log("\x1b[41mWARNING: WMIC unavailable! Using WMI Bridge instead.\x1b[0m") wmicUnavailable = true return false; } try { if (isDev) { WmiClient = require('wmi-client'); } else { let path = process.argv.find((val) => { return (val.indexOf("--apppath=") >= 0) }).substring(10) WmiClient = require(require('path').join(path, '../node_modules/wmi-client')); } wmi = new WmiClient({ host: 'localhost', namespace: '\\\\root\\WMI' }); return true; } catch (e) { console.log('Couldn\'t start WMI', e); wmicUnavailable = true return false; } } getWMIC(); // Request Monitors via WMIC. (Windows 10 only) getMonitorsWMIC = () => { return new Promise((resolve, reject) => { const wmiOK = getWMIC(); if (!wmiOK) { resolve(false); return false; } wmi.query('SELECT * FROM WmiMonitorID', function (err, result) { let foundMonitors = {} if (err != null) { resolve(false) } else if (result) { // Apply names for (let monitor of result) { if (!monitor.InstanceName) continue; let hwid = readInstanceName(monitor.InstanceName) hwid[2] = hwid[2].split("_")[0] const wmiInfo = { id: `\\\\?\\${hwid[0]}#${hwid[1]}#${hwid[2]}`, key: hwid[2], hwid: hwid, serial: parseWMIString(monitor.SerialNumberID) } if (monitor.UserFriendlyName !== null && monitor.UserFriendlyName !== "") { wmiInfo.name = parseWMIString(monitor.UserFriendlyName) } foundMonitors[hwid[2]] = wmiInfo } resolve(foundMonitors) } else { resolve(foundMonitors) } }); }) } // Request WMI brightness via WMIC. (Windows 10 only) const getBrightnessWMIC = async () => { return new Promise((resolve, reject) => { try { const wmiOK = getWMIC(); if (!wmiOK) { resolve(false); return {}; } wmi.query('SELECT * FROM WmiMonitorBrightness', function (err, result) { if (err != null) { resolve(false) } else if (result) { for (let monitor of result) { let hwid = readInstanceName(monitor.InstanceName) hwid[2] = hwid[2].split("_")[0] let wmiInfo = { id: `\\\\?\\${hwid[0]}#${hwid[1]}#${hwid[2]}`, brightness: monitor.CurrentBrightness, hwid: hwid, min: 0, max: 100, type: 'wmi', } // Get normalization info wmiInfo = applyRemap(wmiInfo) // Unnormalize brightness wmiInfo.brightnessRaw = wmiInfo.brightness wmiInfo.brightness = normalizeBrightness(wmiInfo.brightness, true, wmiInfo.min, wmiInfo.max) resolve(wmiInfo) } resolve(false) } else { reject(false) } }); } catch (e) { console.log(e) resolve(false) } }) } function wait(ms = 2000) { return new Promise(resolve => { setTimeout(() => { resolve(true); }, ms); }); } function vcpStr(code) { return `0x${parseInt(code).toString(16).toUpperCase()}` } testDDCCIMethods = async () => { let fastIsFine = false try { if(skipTest) { console.log("Skipping DDC/CI test...") return false } console.log("Testing DDC/CI methods...") getDDCCI() let startTime = process.hrtime.bigint() const accurateResults = ddcci.getAllMonitors("accurate", false) const accurateIDs = [] const accurateFeatures = [] for(const monitor of accurateResults) { if(monitor.ddcciSupported) { accurateIDs.push(monitor.deviceKey) accurateFeatures[monitor.deviceKey] = await checkMonitorFeatures(monitor.deviceKey) } } const endTimeAcc = (startTime - process.hrtime.bigint()) / BigInt(-1000000) wait(50) vcpCache = {} monitorReports = {} monitorReportsRaw = {} ddcci._clearDisplayCache() startTime = process.hrtime.bigint() const fastResults = ddcci.getAllMonitors("fast", false) const fastIDs = [] const fastFeatures = [] for(const monitor of fastResults) { if(monitor.ddcciSupported) { fastIDs.push(monitor.deviceKey) fastFeatures[monitor.deviceKey] = await checkMonitorFeatures(monitor.deviceKey) } } const endTimeFast = (startTime - process.hrtime.bigint()) / BigInt(-1000000) fastIsFine = true let failReason if(fastResults.length !== accurateResults.length) { fastIsFine = false failReason = "Display counts don't match!" } else { for(const id of accurateIDs) { if(fastIDs.indexOf(id) === -1) { fastIsFine = false failReason = "Didn't find ID: " + id } if(JSON.stringify(fastFeatures[id]) != JSON.stringify(accurateFeatures[id])) { failReason = "Features don't match: " + id } } } console.log("-------------- DDC/CI Tests --------------") console.log(`Accurate results took: ${endTimeAcc}ms`) console.log(`Fast results took: ${endTimeFast}ms`) console.log("Is fast fine?: " + fastIsFine) if(failReason) console.log("Reason: " + fastIsFine); if(!failReason) console.log(`Monitors: ${fastResults.length} | DDCCI: ${fastIDs.length}`); console.log("------------------------------------------") wait(50) } catch(e) { console.log("Error testing DDC/CI methods: ", e) } vcpCache = {} monitorReports = {} monitorReportsRaw = {} ddcci._clearDisplayCache() return fastIsFine } let isFastFine = true testDDCCIMethods().then(result => { isFastFine = result if(!skipTest) { process.send({ type: 'ddcciModeTestResult', value: isFastFine }) } process.send({ type: 'ready' }) }) ================================================ FILE: src/Translate.js ================================================ class Translate { constructor(localizationData = {}, fallbackData = {}) { this.localizationData = localizationData this.fallbackData = fallbackData // getString shorthand this.t = this.getString this.h = this.getHTML } setLocalizationData(data = {}, fallback = {}) { this.localizationData = data this.fallbackData = fallback } makeTranslation(string, args = []) { let outString = string for (let i = 1; i <= args.length; i++) { outString = outString.replace(`{{${i}}}`, args[i - 1]) } return outString } getString(key, ...args) { if (this.localizationData[key] !== undefined && this.localizationData[key] !== "") { return this.makeTranslation(this.localizationData[key], args) } else if (this.fallbackData[key] !== undefined & this.fallbackData[key] !== "") { return this.makeTranslation(this.fallbackData[key], args) } else { return "" } } getHTML(key, ...args) { return this.getString(key, args) } } module.exports = Translate ================================================ FILE: src/TranslateReact.js ================================================ import Translate from "./Translate" import React from "react"; class TranslateReact extends Translate { getHTML(key, ...args) { if (this.localizationData[key] !== undefined) { return () } else if (this.fallbackData[key] !== undefined) { return () } else { return key } } } module.exports = TranslateReact ================================================ FILE: src/Utils.js ================================================ const path = require('path'); const fs = require('fs') function udpSendCommand(type, data, port = 14715, key) { return new Promise((resolve, reject) => { const client = require('dgram').createSocket('udp4') const udpTimeout = setTimeout(() => { clearTimeout(udpTimeout) reject("No response") }, 1000) client.on('message', (message, connection) => { resolve(message?.toString()) }) client.send(JSON.stringify({ type, data, key }), port, "localhost", err => { if (err) { reject('Failed to send command') } }) }) } function pipeSendCommand(type, data, port = 14715, key) { return new Promise((resolve, reject) => { const cmdTimeout = setTimeout(() => { clearTimeout(cmdTimeout) reject("No response") }, 1000) const client = require('net').connect('\\\\.\\pipe\\twinkle-tray\\cmds') client.on('data', function(message) { resolve(message?.toString()) }) try { client.write(JSON.stringify({ type, data, key })) } catch(e) { reject('Failed to send command:', e) } }) } module.exports = { unloadModule: (name) => { try { if (require.cache[require.resolve(name)]) { delete require.cache[require.resolve(name)] console.log(`Unloaded module: ${name}`) } } catch (e) { console.log(`Couldn't unload module: ${name}`) } }, wait(ms = 2000) { return new Promise(resolve => { setTimeout(() => { resolve(true); }, ms); }); }, processArgs: (commandLine) => { let validArgs = {} commandLine.forEach(argRaw => { const arg = argRaw.toLowerCase(); // Use UDP if (arg.indexOf("--udp") === 0) { validArgs.UseUDP = true } // Get display by index if (arg.indexOf("--list") === 0) { validArgs.List = true } // Get display by index if (arg.indexOf("--monitornum=") === 0) { validArgs.MonitorNum = (arg.substring(13) * 1) } // Get display by ID (partial or whole) if (arg.indexOf("--monitorid=") === 0) { validArgs.MonitorID = arg.substring(12) } // Run on all displays if (arg.indexOf("--all") === 0 && arg.length === 5) { validArgs.All = true } // Use absolute brightness if (arg.indexOf("--set=") === 0) { validArgs.Brightness = (arg.substring(6) * 1) validArgs.BrightnessType = "set" } // Use relative brightness if (arg.indexOf("--offset=") === 0) { validArgs.Brightness = (arg.substring(9) * 1) validArgs.BrightnessType = "offset" } // Use time adjustments if (arg.indexOf("--usetime") === 0) { validArgs.UseTime = true } // DDC/CI command if (arg.indexOf("--vcp=") === 0 && arg.indexOf(":")) { validArgs.VCP = true } // Show overlay if (arg.indexOf("--overlay") === 0) { validArgs.ShowOverlay = true } // Show panel if (arg.indexOf("--panel") === 0) { validArgs.ShowPanel = true } }) return validArgs }, async handleProcessedArgs(args = {}, knownDisplaysPath, settingsPath) { let failed const settings = JSON.parse(fs.readFileSync(settingsPath)) if (args.ShowPanel) { console.log(`Showing panel`) } else if (args.List) { //const displays = getKnownDisplays(knownDisplaysPath) const useUDP = (args.UseUDP ? true : false) const response = await (useUDP ? udpSendCommand : pipeSendCommand)("list", false, settings.udpPortActive, settings.udpKey) let displays = {} try { displays = JSON.parse(response || "") } catch(e) { console.log("Error parsing response") } Object.values(displays).forEach(display => { console.log(` \x1b[36mMonitorNum:\x1b[0m ${display.num} \x1b[36mMonitorID:\x1b[0m ${display.key} \x1b[36mName:\x1b[0m ${display.name} \x1b[36mBrightness:\x1b[0m ${display.brightness} \x1b[36mType:\x1b[0m ${display.type}`) }) failed = false; return true; } else { if (!(args.MonitorID !== undefined || args.MonitorNum !== undefined || args.All || args.UseTime)) { console.log("\x1b[41mMissing monitor argument.\x1b[0m") failed = true } if (args.Brightness === undefined && !args.VCP && !args.UseTime) { console.log("\x1b[41mMissing brightness argument.\x1b[0m") failed = true } } if (failed) { console.log(` Supported args: \x1b[36m--List\x1b[0m List all displays. \x1b[36m--MonitorNum\x1b[0m Select monitor by number. Starts at 1. \x1b[2mExample: --MonitorNum=2\x1b[0m \x1b[36m--MonitorID\x1b[0m Select monitor by internal ID. Partial or whole matches accepted. \x1b[2mExample: --MonitorID="UID2353"\x1b[0m \x1b[36m--All\x1b[0m Flag to update all monitors. \x1b[2mExample: --All\x1b[0m \x1b[36m--Set\x1b[0m Set brightness percentage. \x1b[2mExample: --Set=95\x1b[0m \x1b[36m--Offset\x1b[0m Adjust brightness percentage. \x1b[2mExample: --Offset=-20\x1b[0m \x1b[36m--UseTime\x1b[0m Adjust brightness using Time of Day Adjustments. \x1b[2mExample: --UseTime\x1b[0m \x1b[36m--VCP\x1b[0m Send a specific DDC/CI VCP code and value instead of brightness. The first part is the VCP code (decimal or hexadecimal), and the second is the value. \x1b[2mExample: --VCP="0xD6:5"\x1b[0m \x1b[36m--Overlay\x1b[0m Flag to show brightness levels in the overlay \x1b[2mExample: --Overlay\x1b[0m \x1b[36m--Panel\x1b[0m Flag to show brightness levels in the panel \x1b[2mExample: --Panel\x1b[0m `) } else { console.log("OK") } }, vcpMap: { 0x10: "luminance", 0x13: "brightness", 0x12: "contrast", 0xD6: "powerState", 0x62: "volume" }, upgradeAdjustmentTimes, getVersionValue, lerp, parseTime, getCalibratedValue } function upgradeAdjustmentTimes(times = []) { const newTimes = [] times.forEach(time => { if (time.time) { newTimes.push(time) return } const newTime = { brightness: (time.brightness ? time.brightness : 50), monitors: (time.monitors ? time.monitors : 50), time: "00:00" } // Convert to 24H const hourInt = parseInt(time.hour) const fixedHour = hourInt + (hourInt == 12 ? (time.am.toLowerCase() == "pm" ? 0 : -12) : (time.am.toLowerCase() == "pm" ? 12 : 0)) newTime.time = (fixedHour < 10 ? "0" + fixedHour : fixedHour) + ":" + (time.minute < 10 ? "0" + time.minute : time.minute) newTimes.push(newTime) }) return newTimes } // Convert version to a numeric value (v1.2.3 = 10020003) function getVersionValue(version = 'v1.0.0') { let out = version.split('-')[0].replace("v", "").split(".") out = (out[0] * 10000 * 10000) + (out[1] * 10000) + (out[2] * 1) return parseInt(out) } function lerp(start, finish, perc) { return start * (1 - perc) + finish * perc } function parseTime(time) { return parseInt((time.split(":")[0] * 60) + (time.split(":")[1] * 1)) } // Get known displays from file, along with current displays function getKnownDisplays(knownDisplaysPath) { let known try { // Load known displays DB known = fs.readFileSync(knownDisplaysPath) known = JSON.parse(known) } catch (e) { known = {} } return known } /** * Maps a value (0–100) using calibration points. * By default, maps input to output. Can also reverse map output back to input. * * @param {number} value - The value to map (expected range: 0–100). * @param {Array<{input: number, output: number}>} calibrationPoints - * An array of calibration points. * Example: [{input: 15, output: 30}, {input: 50, output: 60}] * @param {boolean} reverse - If true, maps output to input. Default is false (input to output). * @returns {number} - The mapped value. */ function getCalibratedValue(value, calibrationPoints = [], reverse = false) { // Ensure value is within 0–100 value = Math.max(0, Math.min(100, value)); // Add default start and end points if not provided const points = calibrationPoints.slice(); // Handle min/max values if those points haven't been provided let hasMin = false; let hasMax = false; for (const point of points) { point.input = Math.max(0, Math.min(100, point.input)); if (point.input === 0) hasMin = true; if (point.input === 100) hasMax = true; } if (!hasMin) { points.unshift({ input: 0, output: 0 }); } if (!hasMax) { points.push({ input: 100, output: 100 }); } // Sort points by input value points.sort((a, b) => a.input - b.input); if (reverse) { // Reverse mapping: output -> input // Find the two points between which the output falls for (let i = 0; i < points.length - 1; i++) { const p1 = points[i]; const p2 = points[i + 1]; // Check if output falls between these two points const minOutput = Math.min(p1.output, p2.output); const maxOutput = Math.max(p1.output, p2.output); if (value >= minOutput && value <= maxOutput) { // Linear interpolation in reverse if (p2.output === p1.output) { // If outputs are the same, return the midpoint input return (p1.input + p2.input) / 2; } const ratio = (value - p1.output) / (p2.output - p1.output); return p1.input + ratio * (p2.input - p1.input); } } // Fallback return value; } else { // Forward mapping: input -> output if (value === 0 && points.length > 0 && points[0].input === 0) { return points[0].output; } // Find the two points between which the input falls for (let i = 0; i < points.length - 1; i++) { const p1 = points[i]; const p2 = points[i + 1]; if (value >= p1.input && value <= p2.input) { // Linear interpolation const ratio = (value - p1.input) / (p2.input - p1.input); return p1.output + ratio * (p2.output - p1.output); } } // Fallback return value; } } ================================================ FILE: src/components/BrightnessPanel.jsx ================================================ import React, { memo, useEffect, useMemo, useState } from "react"; import Slider from "./Slider"; import DDCCISliders from "./DDCCISliders" import HDRSliders from "./HDRSliders"; import TranslateReact from "../TranslateReact" import getMonitorName from "../utils/BrightnessPanel/getMonitorName"; const BrightnessPanel = memo(function BrightnessPanel() { const [state, setState] = useState({ monitors: [], linkedLevelsActive: false, names: {}, update: false, sleeping: false, updateProgress: 0, isRefreshing: window.isRefreshing }) const [doBackgroundEvent, setDoBackgroundEvent] = useState(false) const [levelsChanged, setLevelsChanged] = useState(false) const [init, setInit] = useState(false) const [lastLevels, setLastLevels] = useState([]) const [T] = useState(new TranslateReact({}, {})) const numMonitors = useMemo(() => { let localNumMonitors = 0 for (let key in state.monitors) { if ((state.monitors[key].type != "none" || state.monitors[key].hdr === "active") && !(window.settings?.hideDisplays?.[key] === true)) localNumMonitors++; } return localNumMonitors }, [state.monitors]) let updateInterval = null let panelHeight = -1 // Enable/Disable linked levels const toggleLinkedLevels = () => { const linkedLevelsActive = (state.linkedLevelsActive ? false : true) setState(prev => ({ ...prev, linkedLevelsActive })) window.sendSettings({ linkedLevelsActive }) } // Handle changes const handleChange = (level, slider) => { const monitors = { ...state.monitors } const sliderMonitor = monitors[slider.props.hwid] if (numMonitors && state.linkedLevelsActive) { // Update all monitors (linked) for (let key in monitors) { const monitor = monitors[key] monitor.brightness = level } setState(prev => ({ ...prev, monitors })) setLevelsChanged(true) if (state.updateInterval === 999) syncBrightness() } else if (numMonitors > 0) { // Update single monitor if (sliderMonitor) sliderMonitor.brightness = level; setState(prev => ({ ...prev, monitors })) setLevelsChanged(true) if (state.updateInterval === 999) syncBrightness() } window.pauseMonitorUpdates() } // Update monitor info const recievedMonitors = (e) => { let newMonitors = { ...e.detail } setLastLevels([]) // Reset panel height so it's recalculated panelHeight = -1 setState(prev => ({ ...prev, monitors: newMonitors })) // Delay initial adjustments if (!init) setTimeout(() => { setInit(true) }, 333) } const updateMinMax = (inMonitors = false) => { if (numMonitors > 0) { let newMonitors = Object.assign((inMonitors ? inMonitors : state.monitors), {}) for (let key in newMonitors) { for (let remap in state.remaps) { if (newMonitors[key].name == remap) { newMonitors[key].min = state.remaps[remap].min newMonitors[key].max = state.remaps[remap].max } } } setLevelsChanged(true) if (inMonitors) { return inMonitors } else { setState(prev => ({ ...prev, monitors: newMonitors })) setDoBackgroundEvent(true) } } } // Update settings const recievedSettings = (e) => { const settings = e.detail const linkedLevelsActive = (settings.linkedLevelsActive ?? false) const sleepAction = (settings.sleepAction ?? "none") const updateInterval = (settings.updateInterval || 500) * 1 const remaps = (settings.remaps || {}) const names = (settings.names || {}) setLevelsChanged(true) setState(prev => ({ ...prev, linkedLevelsActive, remaps, names, updateInterval, sleepAction })) resetBrightnessInterval() updateMinMax() setDoBackgroundEvent(true) } const recievedUpdate = (e) => { const update = e.detail setState(prev => ({ ...prev, update })) } const recievedSleep = (e) => { setState(prev => ({ ...prev, sleeping: e.detail })) } // Send new brightness to monitors, if changed const syncBrightness = () => { const monitors = state.monitors if (init && levelsChanged && (window.showPanel || doBackgroundEvent) && numMonitors) { setDoBackgroundEvent(false) setLevelsChanged(false) try { for (let idx in monitors) { if (monitors[idx].type != "none" && monitors[idx].brightness != lastLevels[idx]) { window.updateBrightness(monitors[idx].id, monitors[idx].brightness) } } } catch (e) { console.error("Could not update brightness") } } } const resetBrightnessInterval = () => { if (updateInterval) clearInterval(updateInterval) updateInterval = setInterval(() => syncBrightness(), (state.updateInterval || 500)) } const handleIsRefreshingUpdate = (e) => setState(prev => ({ ...prev, isRefreshing: e.detail })) const handleUpdateProgress = (e) => setState(prev => ({ ...prev, updateProgress: e.detail.progress })) useEffect(() => { resetBrightnessInterval() return () => { clearInterval(updateInterval) } }, [state.monitors, numMonitors, doBackgroundEvent, levelsChanged, init]) useEffect(() => { window.addEventListener("monitorsUpdated", (e) => recievedMonitors(e)) window.addEventListener("settingsUpdated", (e) => recievedSettings(e)) window.addEventListener("localizationUpdated", (e) => T.setLocalizationData(e.detail.desired, e.detail.default)) window.addEventListener("updateUpdated", (e) => recievedUpdate(e)) window.addEventListener("sleepUpdated", (e) => recievedSleep(e)) window.addEventListener("isRefreshing", (e) => handleIsRefreshingUpdate(e)) if (window.isAppX === false) { window.addEventListener("updateProgress", (e) => handleUpdateProgress(e)) } // Update brightness every interval, if changed window.requestSettings() window.requestMonitors() window.ipc.send('request-localization') window.reactReady = true return () => { window.removeEventListener("monitorsUpdated") window.removeEventListener("settingsUpdated") window.removeEventListener("localizationUpdated") window.removeEventListener("updateUpdated") window.removeEventListener("sleepUpdated") window.removeEventListener("isRefreshing") window.removeEventListener("updateProgress") } }, []) useEffect(() => { const height = window.document.getElementById("panel").offsetHeight if (panelHeight != height) { panelHeight = height window.sendHeight(height) } }) const getMonitors = () => { if (!state.monitors || numMonitors == 0) { if (state.isRefreshing) { return (
{T.t("GENERIC_DETECTING_DISPLAYS")}
) } return (
{T.t("GENERIC_NO_COMPATIBLE_DISPLAYS")}
) } else { if (state.linkedLevelsActive) { // Combine all monitors let lastValidMonitor for(const key in state.monitors) { const monitor = state.monitors[key] if(monitor.type == "wmi" || monitor.type == "studio-display" || (monitor.type == "ddcci" && monitor.brightnessType) || monitor.hdr === "active") { lastValidMonitor = monitor } } if (lastValidMonitor) { const monitor = lastValidMonitor return ( ) } return (
{T.t("GENERIC_NO_COMPATIBLE_DISPLAYS")}
) } else { // Show all valid monitors individually const sorted = Object.values(state.monitors).slice(0).sort((a, b) => { const aSort = (a.order === undefined ? 999 : a.order * 1) const bSort = (b.order === undefined ? 999 : b.order * 1) return aSort - bSort }) let useFeatures = false // Check if we should use the extended DDC/CI layout or simple layout for (const { hwid } of sorted) { const monitorFeatures = window.settings?.monitorFeatures?.[hwid[1]] for (const vcp in monitorFeatures) { if (vcp == "0x10" || vcp == "0x13" || vcp == "0xD6") { continue; // Skip if brightness or power state } const feature = monitorFeatures[vcp] if (feature) { // Feature is active // Now we check if there are any settings active for the feature const featureSettings = window.settings.monitorFeaturesSettings?.[hwid[1]] if (!(featureSettings?.[vcp]?.linked)) { // Isn't linked useFeatures = true } } } } return sorted.map((monitor) => { if ((monitor.type == "none" && monitor.hdr !== "active") || window.settings?.hideDisplays?.[monitor.key] === true) { return (
) } else { if (monitor.type == "wmi" || monitor.type == "studio-display" || (monitor.type == "ddcci" && monitor.brightnessType) || monitor.hdr === "active") { let hasFeatures = true let featureCount = 0 const monitorFeatures = window.settings?.monitorFeatures?.[monitor.hwid[1]] const features = ["0x12", "0xD6", "0x62"] if (monitor.features) { features.forEach(f => { // Check monitor features if (monitor.features[f] && monitor.features[f].length > 1) { // Check that user has enabled feature if (monitorFeatures && monitorFeatures[f]) { // Track feature hasFeatures = true featureCount++ } } }) } let showHDRSliders = false if((monitor.hdr === "active" || window.settings?.hdrDisplays?.[monitor.key]) && !(window.settings?.sdrAsMainSliderDisplays?.[monitor.key])) { // Has HDR slider enabled hasFeatures = true useFeatures = true showHDRSliders = true } const powerOff = () => { window.ipc.send("sleep-display", monitor.hwid.join("#")) monitor.features["0xD6"][0] = (monitor.features["0xD6"][0] >= 4 ? 1 : settings.ddcPowerOffValue) } const showPowerButton = () => { const customFeatureEnabled = window.settings?.monitorFeaturesSettings?.[monitor?.hwid[1]]?.["0xD6"] if (monitorFeatures?.["0xD6"] && (monitor.features?.["0xD6"] || customFeatureEnabled)) { return (
{(monitor.features?.["0xD6"][0] >= 4 ? T.t("PANEL_LABEL_TURN_ON") : T.t("PANEL_LABEL_TURN_OFF"))}
) } } // Check if it's an HDR display and only supports SDR brightness adjustment. const isHDROnlySDR = (monitor.hdr === "active" || monitor.hdr === "supported") && monitor.type === "none"; if (!useFeatures || !hasFeatures) { // For HDR displays that only support SDR, the HDR slider is displayed directly instead of the regular brightness slider. if (isHDROnlySDR) { return (
{getMonitorName(monitor, state.names)}
{ showPowerButton() }
) } return (
) } else { return (
{(monitor.type == "wmi" ? : )}
{getMonitorName(monitor, state.names)}
{showPowerButton()}
{/* For HDR displays that only support SDR, hide the regular brightness slider. */} { !isHDROnlySDR && (
)} {showHDRSliders ? : null}
) } } } }) } } } return (
{T.t("PANEL_TITLE")}
{ numMonitors > 1 &&
} { window.settings.sleepAction !== "none" &&
}
{state.sleeping ? (
) : getMonitors()} { (state.update && state.update.show) ?
{T.t("PANEL_UPDATE_AVAILABLE")} ({state.update.version})
: (state.update && state.update.downloading) &&
{state.updateProgress}%
}
) }) export default BrightnessPanel ================================================ FILE: src/components/DDCCISliders.jsx ================================================ import React from "react" import { useObject } from "../hooks/useObject" import Slider from "./Slider" export default function DDCCISliders(props) { const { monitor, monitorFeatures } = props const defaultValues = {} for (const vcp in monitor?.features) { defaultValues[vcp] = vcp === "0x60" ? monitor?.features?.[vcp] ?? 0 : monitor?.features?.[vcp]?.[0] ?? 0 } const [values, setValues] = useObject(defaultValues) const inputsData = { 1: "VGA-1", 2: "VGA-2", 3: "DVI-1", 4: "DVI-2", 5: "Composite video 1", 6: "Composite video 2", 7: "S-Video-1", 8: "S-Video-2", 9: "Tuner-1", 10: "Tuner-2", 11: "Tuner-3", 12: "Component video (YPrPb/YCrCb) 1", 13: "Component video (YPrPb/YCrCb) 2", 14: "Component video (YPrPb/YCrCb) 3", 15: "DisplayPort-1", 16: "DisplayPort-2", 17: "HDMI-1", 18: "HDMI-2" } const changeInputsState = (code) => { const a = [code, [...values["0x60"][1]]] setValues({ ["0x60"]: a }) } let extraHTML = [] const featureSettings = window.settings?.monitorFeaturesSettings?.[monitor?.hwid[1]] if (monitor?.features) { let i = 0 for (const vcp in monitor.features) { i++ if (vcp == "0x10" || vcp == "0x13" || vcp == "0xD6") { continue; // Skip if brightness or power state } const feature = monitor.features[vcp] if (feature && monitorFeatures?.[vcp] && !(featureSettings?.[vcp]?.linked)) { // Feature has a value, is enabled, and not linked if (vcp === "0x12") { // Contrast extraHTML.push(
{ setValues({ [vcp]: val }); setVCP(monitor.id, parseInt(vcp), val * (monitor.features[vcp][1] / 100)) }} scrollAmount={props.scrollAmount} />
) } else if (vcp === "0x62") { // Volume extraHTML.push(
{ setValues({ [vcp]: val }); setVCP(monitor.id, parseInt(vcp), val * (monitor.features[vcp][1] / 100)) }} scrollAmount={props.scrollAmount} />
) } else if (vcp === "0x60") { // Input extraHTML.push(
{values["0x60"][1].map(e => )}
) } else { // Custom const settings = featureSettings?.[vcp] ?? {} let icon if (settings?.iconType === "windows" && settings?.icon) { icon = () } else if (settings?.iconType === "text" && settings?.iconText) { icon = ({settings.iconText}) } else { // Default icon = () } extraHTML.push(
{icon}
{ setValues({ [vcp]: val }); setVCP(monitor.id, parseInt(vcp), val * (monitor.features[vcp][1] / 100)) }} scrollAmount={props.scrollAmount} />
) } } } } return ( <> {extraHTML} ) } function setVCP(monitor, code, value) { window.dispatchEvent(new CustomEvent("setVCP", { detail: { monitor, code, value } })) } ================================================ FILE: src/components/HDRSliders.jsx ================================================ import React, { useState } from "react" import { useObject } from "../hooks/useObject" import Slider from "./Slider" export default function HDRSliders(props) { const { monitor, name, hdrFeatures } = props const [sdrLevel, setSDRLevel] = useState(monitor?.sdrLevel) let extraHTML = [] // SDR Brightness extraHTML.push(
SDR
{ setSDRLevel( val ); setSDRBrightness(monitor.id, parseInt(val)) }} scrollAmount={props.scrollAmount} />
) return ( <> {extraHTML} ) } function setSDRBrightness(monitor, value) { window.ipc.send("set-sdr-brightness", { monitor, value }) } ================================================ FILE: src/components/IntroWindow.jsx ================================================ import React, { PureComponent } from "react"; import TranslateReact from "../TranslateReact" import AppLogo from "../assets/logo.png" import IntroVideo from "../assets/intro-video.mp4" let T = new TranslateReact({}, {}) export default class IntroWindow extends PureComponent { constructor(props) { super(props) } componentDidMount() { window.addEventListener("localizationUpdated", (e) => { T.setLocalizationData(e.detail.desired, e.detail.default); this.forceUpdate() }) window.ipc.send('request-localization') } render() { return (
{T.t("INTRO_TITLE")}

{T.t("INTRO_INSTRUCTIONS")}

{T.t("GENERIC_CLOSE")}
); } } ================================================ FILE: src/components/MonitorFeatures.jsx ================================================ import React, { useState, useEffect } from "react" import { useObject } from "../hooks/useObject" import { SettingsOption, SettingsChild } from "./SettingsOption"; import Slider from "./Slider" import VCP from "../vcp-codes" const ignoreCodes = ["0x10", "0x12", "0x13", "0x62", "0xD6", "0x60"] const deleteIcon = () export default function MonitorFeatures(props) { const { monitor, name, monitorFeatures, T, onChange } = props let extraHTML = [] const inputsData = { 1: "VGA-1", 2: "VGA-2", 3: "DVI-1", 4: "DVI-2", 5: "Composite video 1", 6: "Composite video 2", 7: "S-Video-1", 8: "S-Video-2", 9: "Tuner-1", 10: "Tuner-2", 11: "Tuner-3", 12: "Component video (YPrPb/YCrCb) 1", 13: "Component video (YPrPb/YCrCb) 2", 14: "Component video (YPrPb/YCrCb) 3", 15: "DisplayPort-1", 16: "DisplayPort-2", 17: "HDMI-1", 18: "HDMI-2" } if (monitor.ddcciSupported && Object.keys(monitor.features || {}).length > 0) { // Brightness (with VCP Code Selection in expanded section) if (monitor.features["0x10"]) { const currentBrightnessVCP = window.settings?.userDDCBrightnessVCPs?.[monitor?.hwid?.[1]] || "" extraHTML.push( ) } // Contrast if (monitor.features["0x12"]) { const vcp = "0x12" const settings = window.settings?.monitorFeaturesSettings?.[monitor?.hwid[1]]?.[vcp] const enabled = monitorFeatures?.["0x12"]; extraHTML.push( { props?.toggleFeature(monitor.hwid[1], vcp) }} checked={(enabled ? true : false)} data-checked={(enabled ? true : false)} type="checkbox" /> }> ) } // Volume if (monitor.features["0x62"]) { const vcp = "0x62" const settings = window.settings?.monitorFeaturesSettings?.[monitor?.hwid[1]]?.[vcp] const enabled = monitorFeatures?.["0x62"]; extraHTML.push( { props?.toggleFeature(monitor.hwid[1], vcp) }} checked={(enabled ? true : false)} data-checked={(enabled ? true : false)} type="checkbox" /> }> ) } // Input if (monitor.features["0x60"] && Array.isArray(monitor.features["0x60"]) && monitor.features["0x60"][1]) { const vcp = "0x60" const settings = window.settings?.monitorFeaturesSettings?.[monitor?.hwid[1]]?.[vcp] const enabled = monitorFeatures?.["0x60"]; extraHTML.push( { props?.toggleFeature(monitor.hwid[1], vcp) }} checked={(enabled ? true : false)} data-checked={(enabled ? true : false)} type="checkbox" /> }>
{(Array.isArray(monitor.features["0x60"][1]) ? monitor.features["0x60"][1] : [])?.map(e =>
{inputsData[e]}
)}
⚠️ {T.t("GENERIC_DDC_WARNING")}
}>
) } // Power State if (monitor.features["0xD6"]) { const vcp = "0xD6" const enabled = monitorFeatures?.["0xD6"]; extraHTML.push( { props?.toggleFeature(monitor.hwid[1], vcp) }} checked={(enabled ? true : false)} data-checked={(enabled ? true : false)} type="checkbox" /> }> ) } const deleteFeature = vcp => { if (monitorFeatures[vcp] != undefined) { delete window.settings?.monitorFeatures[monitor.hwid[1]][vcp] } if (window.settings?.monitorFeaturesSettings?.[monitor?.hwid[1]]?.[vcp] !== undefined) { delete window.settings?.monitorFeaturesSettings?.[monitor?.hwid[1]]?.[vcp] } window.sendSettings({ monitorFeatures: window.settings?.monitorFeatures, monitorFeaturesSettings: window.settings?.monitorFeaturesSettings }) } // Custom Features for (const vcp in monitorFeatures) { if (ignoreCodes.indexOf(vcp) === -1 && monitorFeatures[vcp] !== undefined) { const settings = window.settings?.monitorFeaturesSettings?.[monitor?.hwid[1]]?.[vcp] const enabled = monitorFeatures?.[vcp]; const name = (settings?.iconType === "text" && settings?.iconText?.length ? settings.iconText : "Custom Feature") const icon = (settings?.iconType === "windows" && settings?.icon ? settings.icon : "E9E9") extraHTML.push(
deleteFeature(vcp)}>{deleteIcon}
{ props?.toggleFeature(monitor.hwid[1], vcp) }} checked={(enabled ? true : false)} data-checked={(enabled ? true : false)} type="checkbox" />
}>
) } } // VCP code list if (monitor.vcpCodes && typeof monitor.vcpCodes === 'object' && Object.values(monitor.vcpCodes).length) { const list = [] for (const code in monitor.vcpCodes) { list.push(
{code}: {findVCPCodeName(code) || "???"} { monitor.vcpCodes[code].length ?
{T.t("SETTINGS_FEATURES_VCP_EXPECTED")}: {monitor.vcpCodes[code].toString()}
: "" }
) } if (list) { extraHTML.push(
⚠️ {T.t("SETTINGS_FEATURES_VCP_LIST_DESC")}

{list}
) } } extraHTML.push(

{ props.onAddFeature() }} className="button">+ {T.t("SETTINGS_FEATURES_ADD")}

) } else { extraHTML.push(

{T.t("SETTINGS_FEATURES_UNSUPPORTED")}

) } return (

{monitor.name}
{extraHTML}
) } function MonitorFeaturesSettings(props) { const { enabled, settings, hwid, vcp, onChange, T } = props //if(!enabled) return (<>); const [settingsObj, updateSettings] = useObject(Object.assign({ icon: "e897", iconType: "windows", iconText: "", iconPath: "", min: 0, max: 100, maxVisual: 100, linked: false }, settings)) const onChangeHandler = (settingName, value) => { try { updateSettings({ [settingName]: value }) if (!window.settings.monitorFeaturesSettings[hwid]) { window.settings.monitorFeaturesSettings[hwid] = {} } if (!window.settings.monitorFeaturesSettings[hwid][vcp]) { window.settings.monitorFeaturesSettings[hwid][vcp] = {} } window.settings.monitorFeaturesSettings[hwid][vcp][settingName] = value if (onChange) onChange(settingName, value); } catch (e) { console.log(e) } } const iconType = (
) const icon = (
) const iconText = (
onChangeHandler("iconText", e.target.value)} placeholder={T.t("GENERIC_SLIDER_NAME")} />
) const iconSettings = (
{iconType} {settingsObj.iconType === "windows" ? icon : null} {settingsObj.iconType === "text" ? iconText : null}
) return (
{ignoreCodes.indexOf(vcp) === -1 ? iconSettings : null}
onChangeHandler("min", value)} level={settingsObj.min} scrolling={false} height={"short"} icon={false} /> onChangeHandler("max", value)} level={settingsObj.max} scrolling={false} height={"short"} icon={false} />
onChangeHandler("linked", e.target.checked)} checked={(settingsObj.linked ? true : false)} data-checked={(settingsObj.linked ? true : false)} type="checkbox" />
{T.t("SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS")}

onChangeHandler("maxVisual", value)} level={settingsObj.maxVisual ?? 100} scrolling={false} height={"short"} icon={false} />
) } /** * Component for setting a custom VCP code for brightness control. * * This component allows the user to specify a custom VCP (Virtual Control Panel) code * for controlling monitor brightness. The expected format for VCP codes is a hexadecimal * string (e.g., "0x10", "0x6B"). The setting is persisted in the application's settings * under `userDDCBrightnessVCPs` and applied immediately via `window.sendSettings`. * * @param {Object} props - Component props * @param {string} props.hwid - Hardware ID of the monitor * @param {string} props.currentBrightnessVCP - Current custom VCP code (hex string like "0x10") * @param {Object} props.T - Translation object */ function BrightnessFeatureSettings(props) { const { hwid, currentBrightnessVCP, T } = props const [vcpInput, setVcpInput] = useState(currentBrightnessVCP) // Sync input value when settings change externally useEffect(() => { setVcpInput(currentBrightnessVCP) }, [currentBrightnessVCP]) const handleVCPChange = (e) => { const value = e.target.value.trim() setVcpInput(value) const newUserVCPs = Object.assign({}, window.settings?.userDDCBrightnessVCPs || {}) if (value === "") { delete newUserVCPs[hwid] } else { // Validate the input is a valid hex VCP code (0x00-0xFF) const parsed = parseInt(value, 16) if (isNaN(parsed) || parsed < 0 || parsed > 0xFF) { // Invalid input - don't save, just update the input field return } newUserVCPs[hwid] = value } window.sendSettings({ userDDCBrightnessVCPs: newUserVCPs }) } return (

{T.t("SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO")}

{T.t("SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC")}

) } const windowsIcons = [ "e897", "e706", "e70c", "e71d", "e727", "e733", "e734", "e73a", "e772", "e767", "e760", "e761", "e781", "e783", "e793", "e794", "e7a1", "e7b3", "e7e8", "e7f4", "e7f7", "e82f", "e836", "ea61", "ea80", "eb67", "ebaa", "edb1", "edb5", "f08c", "f093", "f094", "f095", "f096", "f0ce", "f1db", "f1e8", "f4a5", "f736", "f78b", "f785", "f78d", "f0b2", "e8be", "e88e", "e839", "e7fc", "e78b", "e713", "eb9f", "ed39", "ed3a" ] function WindowsIconsOptions(props) { return windowsIcons.map(icon => { return () }) } function findVCPCodeName(code) { for (const name in VCP) { if (VCP[name] == code) { return name } } return false } ================================================ FILE: src/components/MonitorInfo.jsx ================================================ import React, { useState, useEffect } from "react" import Slider from "./Slider" import TranslateReact from "../TranslateReact" export default function MonitorInfo(props) { const { monitor, name } = props const [brightness, setBrightness] = useState(monitor?.features?.["0x10"] ? monitor?.features?.["0x10"][0] : 50) const [contrast, setContrast] = useState(monitor?.features?.["0x12"] ? monitor?.features?.["0x12"][0] : 50) const [volume, setVolume] = useState(monitor?.features?.["0x62"] ? monitor?.features?.["0x62"][0] : 50) const [powerState, setPowerState] = useState(monitor?.features?.["0xD6"] ? monitor?.features?.["0xD6"][0] : 50) const [sdr, setSDR] = useState(monitor.sdrLevel >= 0 ? monitor.sdrLevel : 50) const [manualVCP, setManualVCP] = useState("") const [manualValue, setManualValue] = useState("") const [T] = useState(new TranslateReact({}, {})) let extraHTML = [] useEffect(() => { window.addEventListener("localizationUpdated", (e) => T.setLocalizationData(e.detail.desired, e.detail.default)) window.ipc.send('request-localization') return () => { } }, []) if (props.debug === true) { extraHTML.push(

Raw Brightness: {(monitor.type == "none" ? "Not supported" : monitor.brightnessRaw)}
Features: {(monitor.type == "ddcci" && monitor.features ? JSON.stringify(monitor.features) : "Unsupported")}
Order: {(monitor.order ? monitor.order : "0")}
Key: {monitor.key}
ID: {monitor.id}
Connection Type: {monitor.connector}

) } // Brightness if (monitor?.features?.["0x10"]) { extraHTML.push(
{ setBrightness(val); setVCP(monitor.id, 0x10, val * (monitor.features["0x10"][1] / 100)) }} scrolling={false} />
) } // Contrast if (monitor?.features?.["0x12"]) { extraHTML.push(
{ setContrast(val); setVCP(monitor.id, 0x12, val * (monitor.features["0x12"][1] / 100)) }} scrolling={false} />
) } // Volume if (monitor?.features?.["0x62"]) { extraHTML.push(
{ setVolume(val); setVCP(monitor.id, 0x62, val * (monitor.features["0x62"][1] / 100)) }} scrolling={false} />
) } // Power State if (monitor?.features?.["0xD6"]) { extraHTML.push(
{ setPowerState(val); setVCP(monitor.id, 0xD6, val) }} scrolling={false} />
) } // Manual VCP extraHTML.push(
{ setManualVCP(e.target.value) }} /> { setManualValue(e.target.value) }} /> setVCP(monitor.id, parseInt(manualVCP), parseInt(manualValue))}>Send VCP
) // SDR test extraHTML.push(
SDR
{ setSDR(val); setSDRBrightness(monitor.id, val) }} scrolling={false} />
) return (

{monitor.name}

{T.t("SETTINGS_MONITORS_DETAILS_NAME")}: {name}
{T.t("SETTINGS_MONITORS_DETAILS_INTERNAL_NAME")}: {monitor.hwid[1]}
{T.t("SETTINGS_MONITORS_DETAILS_COMMUNICATION")}: {getDebugMonitorType((monitor.type === "ddcci" && monitor.highLevelSupported?.brightness ? "ddcci-hl" : monitor.type))}
{T.t("SETTINGS_MONITORS_DETAILS_BRIGHTNESS")}: {(monitor.type == "none" ? T.t("GENERIC_NOT_SUPPORTED") : monitor.brightness)}
{T.t("SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS")}: {(monitor.type !== "ddcci" ? T.t("GENERIC_NOT_SUPPORTED") : monitor.brightnessMax)}
{T.t("SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION")}: {(monitor.type == "none" ? T.t("GENERIC_NOT_SUPPORTED") : monitor.min + " - " + monitor.max)}
{T.t("SETTINGS_MONITORS_DETAILS_HDR")}: {(monitor.hdr == "active" ? T.t("GENERIC_ACTIVE") : monitor.hdr == "supported" ? T.t("GENERIC_SUPPORTED") : T.t("GENERIC_UNSUPPORTED"))}

{extraHTML}
) } function setVCP(monitor, code, value) { window.dispatchEvent(new CustomEvent("setVCP", { detail: { monitor, code, value } })) } function setSDRBrightness(monitor, value) { window.dispatchEvent(new CustomEvent("set-sdr-brightness", { detail: { monitor, value } })) } function getDebugMonitorType(type) { if (type == "none") { return (<>None ) } else if (type == "ddcci") { return (<>DDC/CI ) } else if (type == "ddcci-hl") { return (<>DDC/CI (HL) ) } else if (type == "wmi") { return (<>WMI ) } else if (type == "studio-display") { return (<>Studio Display ) } else { return (<>Unknown ({type}) ) } } ================================================ FILE: src/components/SafeRender.jsx ================================================ import React from "react"; export default class SafeRender extends React.Component { constructor(props) { super(props); this.state = { hasError: false, error: "" }; } static getDerivedStateFromError(error) { return { hasError: true, error: error }; } componentDidCatch(error, errorInfo) { console.log(error) this.setState({ hasError: true, error: error, errorInfo: errorInfo?.componentStack }) } render() { if (this.state.hasError) { return (
Error: {JSON.stringify(this.state.error)}
{this.state.errorInfo}
); } return <>{this.props?.children}; } } ================================================ FILE: src/components/SettingsOption.jsx ================================================ import React, { useState, useEffect } from "react" import SafeRender from "./SafeRender" export function SettingsOption(props) { const [expanded, setExpanded] = useState((props.startExpanded ?? false)) const title = (props.title ?
{props.title}
: null) const icon = (props.icon ?
: null) const description = (props.description ?
{props.description}
: null) const elem = (props.content ?
{props.content}
: null) const input = (props.input ?
{props.input}
: null) const className = `settings-option-elem ${props.className ?? ""}` return (
{icon}
{title} {description} {elem}
{input}
setExpanded(!expanded)}>
{props.children}
) } export function SettingsChild(props) { const title = (props.title ?
{props.title}
: null) const icon = (props.icon ?
: null) const description = (props.description ?
{props.description}
: null) const elem = (props.content ?
{props.content}
: null) const children = (props.children ?
{props.children}
: null) const input = (props.input ?
{props.input}
: null) const className = `settings-child-elem ${props.className ?? ""}` return Array.isArray(props.children) ?
{children}
:
{icon}
{title} {description} {elem} {children}
{input}
} ================================================ FILE: src/components/SettingsWindow.jsx ================================================ /* Hi, If you're reading this, you probably want to know how this component works. This component is not good. Mistakes were made. It's a horrible bowl of spaghetti. Run while you still can. */ import React, { PureComponent } from "react"; import Titlebar from './Titlebar' import Slider from "./Slider"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import Markdown from 'markdown-to-jsx'; import TranslateReact from "../TranslateReact" import MonitorInfo from "./MonitorInfo" import MonitorFeatures from "./MonitorFeatures" import { SettingsOption, SettingsChild } from "./SettingsOption"; import SafeRender from "./SafeRender"; import DefaultIcon from "../assets/tray-icons/dark/icon@4x.png" import MDL2Icon from "../assets/tray-icons/dark/mdl2@4x.png" import FluentIcon from "../assets/tray-icons/dark/fluent@4x.png" function vcpStr(code) { return `0x${parseInt(code).toString(16).toUpperCase()}` } const uuid = () => crypto.randomUUID() const reorder = (list, startIndex, endIndex) => { const result = Array.from(list); const [removed] = result.splice(startIndex, 1); result.splice(endIndex, 0, removed); return result; }; const getItemStyle = (isDragging, draggableStyle) => ({ userSelect: "none", background: isDragging ? "rgba(122, 122, 122, 0.2)" : "none", ...draggableStyle }); const monitorSort = (a, b) => { const aSort = (a.order === undefined ? 999 : a.order * 1) const bSort = (b.order === undefined ? 999 : b.order * 1) return aSort - bSort } const deleteIcon = () const cleanUpKeyboardKeys = (inKey, inCode = false) => { let key = inKey let code = inCode if (key.length == 1) { key = key.toUpperCase() } switch (key) { case "Meta": key = "Super"; break; case " ": key = "Space"; break; case "ArrowUp": key = "Up"; break; case "ArrowDown": key = "Down"; break; case "ArrowLeft": key = "Left"; break; case "ArrowRight": key = "Right"; break; case "+": key = "Plus"; break; case "-": key = "Minus"; break; } if (code >= 96 && code <= 105) key = "num" + (code - 96); switch (code) { case 106: key = "nummult"; break; case 107: key = "numadd"; break; case 109: key = "numsub"; break; case 110: key = "numdec"; break; case 111: key = "numdiv"; break; } return key; } const defaultAction = { type: "set", target: "brightness", monitors: {}, allMonitors: false, value: 0, values: [0], id: uuid() } let T = new TranslateReact({}, {}) export default class SettingsWindow extends PureComponent { constructor(props) { super(props) this.state = { rawSettings: {}, activePage: "general", theme: 'default', openAtLogin: false, brightnessAtStartup: true, monitors: [], remaps: [], names: [], hotkeys: [], adjustmentTimes: [], linkedLevelsActive: false, updateInterval: (window.settings.updateInterval || 500), downloadingUpdate: false, checkForUpdates: false, adjustmentTimeIndividualDisplays: false, languages: [], analytics: false, useAcrylic: true, scrollShortcut: true, updateProgress: 0, extendedDDCCI: { contrast: 50, volume: 50, powerState: 0 }, windowHistory: [], showAddFeatureOverlay: false, addFeatureMonitor: "", addFeatureValue: "", addFeatureError: false } this.numMonitors = 0 this.downKeys = {} this.lastLevels = [] this.onDragEnd = this.onDragEnd.bind(this); this.sendSettingsTimeout = false this.sendSettingsValues = {} this.settingsPageRef = React.createRef() this.addFeatureInputRef = React.createRef() this.addFeatureOKRef = React.createRef() this.addFeatureCancelRef = React.createRef() } sendSettingsThrottle = (newSetting = {}) => { this.sendSettingsValues = Object.assign(this.sendSettingsValues, newSetting) if (this.sendSettingsTimeout) { clearTimeout(this.sendSettingsTimeout) } this.sendSettingsTimeout = setTimeout(() => { window.sendSettings(Object.assign({}, this.sendSettingsValues)) this.sendSettingsValues = {} }, 2000) } componentDidMount() { window.addEventListener("monitorsUpdated", this.recievedMonitors) window.addEventListener("settingsUpdated", this.recievedSettings) window.addEventListener("localizationUpdated", (e) => { this.setState({ languages: e.detail.languages }); T.setLocalizationData(e.detail.desired, e.detail.default)}); window.addEventListener("windowHistory", e => this.setState({ windowHistory: e.detail })) if (window.isAppX === false) { window.addEventListener("updateUpdated", (e) => { const version = e.detail this.setState({ releaseURL: (window.isAppX ? "ms-windows-store://pdp/?productid=9PLJWWSV01LK" : version.releaseURL), latest: version.version, downloadURL: version.downloadURL, changelog: version.changelog, error: (version.error != undefined ? version.error : false) }) if (e.detail.error == true) { this.setState({ downloadingUpdate: false }) } }) window.addEventListener("updateProgress", (e) => { this.setState({ updateProgress: e.detail.progress }) }) window.checkForUpdates() } window.ipc.send('get-window-history') window.ipc.send("sendSettingsWindowPos") window.ipc.send('request-localization') window.reactReady = true } onDragEnd(result) { // dropped outside the list if (!result.destination) { return; } const sorted = Object.values(this.state.monitors).slice(0).sort(monitorSort) const items = reorder( sorted, result.source.index, result.destination.index ); let order = [] let idx = 0 for (let monitor of items) { this.state.monitors[monitor.key].order = idx order.push({ id: monitor.id, order: idx }) idx++ } this.setState({ order }); window.sendSettings({ order }) } getRemap = (name) => { if (this.state.remaps[name] === undefined) { return { isFallback: true, min: 0, max: 100, calibration: [] } } return this.state.remaps[name] } minMaxChanged = (value, slider) => { const name = slider.props.monitorID let remaps = Object.assign({}, this.state.remaps) if (remaps[name] === undefined) { remaps[name] = { min: 0, max: 100, calibration: [] } } if (slider.props.type == "min") { remaps[name].min = value // Keep within 10%, cap if (remaps[name].min > remaps[name].max - 10) { remaps[name].max = remaps[name].min + 10 } if (remaps[name].max > 100) { remaps[name].max = 100 } if (remaps[name].min > remaps[name].max - 10) { remaps[name].min = remaps[name].max - 10 } } else if (slider.props.type == "max") { remaps[name].max = value // Keep within 10%, cap if (remaps[name].min > remaps[name].max - 10) { remaps[name].min = remaps[name].max - 10 } if (remaps[name].min < 0) { remaps[name].min = 0 } if (remaps[name].min > remaps[name].max - 10) { remaps[name].max = remaps[name].min + 10 } } const oldData = JSON.stringify(this.state.remaps); const newData = JSON.stringify(remaps); const hasChanged = (oldData == newData ? false : true); //if(!hasChanged) return false; this.setState({ remaps }) window.sendSettings({ remaps }) } themeChanged = (event) => { this.setState({ theme: event.target.value }) window.sendSettings({ theme: event.target.value }) } updateIntervalChanged = (event) => { this.setState({ updateInterval: event.target.value * 1 }) window.sendSettings({ updateInterval: event.target.value * 1 }) } sleepActionChanged = (event) => { window.sendSettings({ sleepAction: event.target.value }) } monitorNameChange = (e, f) => { const idx = e.currentTarget.dataset.key this.state.names[window.allMonitors[idx].id] = e.currentTarget.value this.forceUpdate() window.sendSettings({ names: this.state.names }) } getMonitorName = (monitor, renames) => { if (Object.keys(renames).indexOf(monitor.id) >= 0 && renames[monitor.id] != "") { return renames[monitor.id] + ` (${monitor.name})` } else { return monitor.name } } getSidebar = () => { const items = [ { id: "general", label: T.t("SETTINGS_SIDEBAR_GENERAL"), icon: "" }, { id: "monitors", label: T.t("SETTINGS_SIDEBAR_MONITORS"), icon: "" }, { id: "features", label: T.t("SETTINGS_SIDEBAR_FEATURES"), icon: "" }, { id: "time", label: T.t("SETTINGS_SIDEBAR_TIME"), icon: "" }, { id: "hotkeys", label: T.t("SETTINGS_SIDEBAR_HOTKEYS"), icon: "" }, { id: "updates", label: T.t("SETTINGS_SIDEBAR_UPDATES"), icon: "" }, { id: "debug", label: "Debug", icon: "", type: "debug" } ] return items.map((item, index) => { return (
{ this.setState({ activePage: item.id }); window.currentSettingsPage = item.id; this.scrollToTop(); window.reloadReactMonitors(); window.requestMonitors(); }}>
{item.label || `Item ${index}`}
) }) } getLanguages = () => { if (this.state.languages && this.state.languages.length > 0) { return this.state.languages.map((value, index) => { return () }) } } scrollToTop = () => { try { this.settingsPageRef.current.scrollTop = 0 } catch(e) { } } getUpdate = () => { if (window.isAppX) { return (

{ window.openURL("ms-store") }}>{T.t("SETTINGS_UPDATES_MS_STORE")}

) } else { if (this.state.latest && this.state.latest != window.version) { return (

{T.t("SETTINGS_UPDATES_AVAILABLE") + ` (${this.state.latest})`}

{this.state.latest}

{this.state.changelog}

{this.getUpdateButton()}
) } else if (this.state.latest) { return (

{T.t("SETTINGS_UPDATES_NONE_AVAILABLE")}

{this.state.changelog}
) } } } getUpdateButton = () => { if (this.state.downloadingUpdate) { return (

{T.t("SETTINGS_UPDATES_DOWNLOADING")}

) } else { return ( { window.getUpdate(); this.setState({ downloadingUpdate: true }) }}>{T.t("SETTINGS_UPDATES_DOWNLOAD", this.state.latest)}) } } getMinMaxMonitors = () => { if (this.state.monitors == undefined || Object.keys(this.state.monitors).length == 0) { return (
{T.t("GENERIC_NO_COMPATIBLE_DISPLAYS")}

) } else { return Object.values(this.state.monitors).map((monitor, index) => { if (monitor.type == "none") { return (
) } else { // New method, by ID let remap = this.getRemap(monitor.id) // Old method, by name if (remap.isFallback) { remap = this.getRemap(monitor.name) } return (
} /> { this.getMonitorCalibration(monitor.id) }
this.addCalibrationPoint(monitor.id)}>+ {T.t("GENERIC_CALIBRATION_POINT")}
} />
) } }) } } getMonitorCalibration = (monitorID) => { const pointsElems = [] const remap = this.getRemap(monitorID) if(remap) for(const pointIdx in remap.calibration) { const point = remap.calibration[pointIdx] pointsElems.push(
this.updateCalibrationPoint(monitorID, pointIdx, "input", value)} scrolling={false} height={"short"} />
this.updateCalibrationPoint(monitorID, pointIdx, "output", value)} scrolling={false} height={"short"} />
this.deleteCalibrationPoint(monitorID, pointIdx)}>{ deleteIcon } {T.t("GENERIC_DELETE")}
) } return pointsElems } addCalibrationPoint = (monitorID) => { if (this.state.remaps[monitorID] === undefined) { this.state.remaps[monitorID] = { min: 0, max: 100, calibration: [] } } const remap = this.getRemap(monitorID) if(remap) { if(!remap.calibration) remap.calibration = []; remap.calibration.push({ input: 0, output: 100 }) this.setState({ remaps: { ...this.state.remaps } }) window.sendSettings({ remaps: this.state.remaps }) } } updateCalibrationPoint = (monitorID, pointIdx, field, value) => { const remap = this.getRemap(monitorID) if(remap && remap.calibration[pointIdx]) { remap.calibration[pointIdx][field] = value this.setState({ remaps: { ...this.state.remaps } }) window.sendSettings({ remaps: this.state.remaps }) } } deleteCalibrationPoint = (monitorID, pointIdx) => { const remap = this.getRemap(monitorID) if(remap && remap.calibration[pointIdx]) { remap.calibration.splice(pointIdx, 1) this.setState({ remaps: { ...this.state.remaps } }) window.sendSettings({ remaps: this.state.remaps }) } } getRenameMonitors = () => { if (this.state.monitors == undefined || Object.keys(this.state.monitors).length == 0) { return ({T.t("GENERIC_NO_COMPATIBLE_DISPLAYS")}

} />) } else { return Object.values(this.state.monitors).map((monitor, index) => { if (monitor.type == "none") { return null } else { return ( )} /> ) } }) } } getReorderMonitors = () => { if (this.state.monitors == undefined || this.numMonitors == 0) { return (
{T.t("GENERIC_NO_COMPATIBLE_DISPLAYS")}

) } else { const sorted = Object.values(this.state.monitors).slice(0).sort(monitorSort) return ( {(provided, snapshot) => (
{sorted.map((monitor, index) => { if (monitor.type == "none") { return (
) } else { return ( {(provided, snapshot) => (
{getMonitorName(monitor, this.state.names)}
)}
) } })} {provided.placeholder}
)}
) } } updateAdjustmentTime(time, idx) { this.state.adjustmentTimes[idx] = Object.assign({}, time) window.sendSettings({ adjustmentTimes: this.state.adjustmentTimes.slice() }) this.forceUpdate() } getAdjustmentTimes = () => { if (this.state.adjustmentTimes == undefined || this.state.adjustmentTimes.length == 0) { return (
) } else { const times = window.getSunCalcTimes(window.settings.adjustmentTimeLatitude, window.settings.adjustmentTimeLongitude) const lat = parseFloat(window.settings.adjustmentTimeLatitude) ?? 0 const long = parseFloat(window.settings.adjustmentTimeLongitude) ?? 0 const canShowSunCalc = ((lat > 0 || lat < 0) && (long > 0 || long < 0)) return this.state.adjustmentTimes.map((time, index) => { let timeElem = ( { this.setAdjustmentTimeValue(index, e.target.value) }} value={time.time}> ) if (time.useSunCalc) { timeElem = ( ) } return ( {timeElem} { this.state.adjustmentTimes.splice(index, 1) this.forceUpdate() this.adjustmentTimesUpdated() }} /> } input={
{ time.useSunCalc = e.target.checked this.updateAdjustmentTime(time, index) }} checked={time.useSunCalc ?? false} data-checked={time.useSunCalc ?? false} type="checkbox" />
{T.t("SETTINGS_TIME_USE_SUN_POSITION")}
}> {this.getAdjustmentTimesMonitors(time, index)}
) }) } } getAdjustmentTimesMonitors = (time, index) => { if (this.state.adjustmentTimeIndividualDisplays) { return Object.values(this.state.monitors).map((monitor, idx) => { if (monitor.type == "none") { return (
) } else { let level = time.brightness if (this.state.adjustmentTimes[index] && this.state.adjustmentTimes[index].monitors && this.state.adjustmentTimes[index].monitors[monitor.id] >= 0) { level = this.state.adjustmentTimes[index].monitors[monitor.id] } else { // No value set, use shared value this.state.adjustmentTimes[index].monitors[monitor.id] = level this.adjustmentTimesUpdated() } return ( { this.getAdjustmentTimesMonitorsChanged(index, monitor, value) }} level={level} scrolling={false} />) } }) } else { return ( { this.state.adjustmentTimes[index].brightness = value; this.forceUpdate(); this.adjustmentTimesUpdated() }} scrolling={false} />) } } getAdjustmentTimesMonitorsChanged = (index, monitor, value) => { if (this.state.adjustmentTimes[index].monitors === undefined) { this.state.adjustmentTimes[index].monitors = {} } this.state.adjustmentTimes[index].monitors[monitor.id] = value this.forceUpdate(); this.adjustmentTimesUpdated() } setAdjustmentTimeValue = (index, arr) => { for (let i in arr) { if (i < 2 && isNaN(arr[i])) return false; } this.state.adjustmentTimes[index].time = arr //this.forceUpdate() this.adjustmentTimesUpdated() } getHotkeyList = () => { const deleteHotkeyAction = (idx, actionIdx) => { try { this.state.hotkeys[idx].actions.splice(actionIdx, 1) window.sendSettings({ hotkeys: this.state.hotkeys.slice() }) this.forceUpdate() } catch(e) { console.log(e) } } return this.state.hotkeys?.map?.((hotkey, idx) => { return ( { e.preventDefault() let key = cleanUpKeyboardKeys(e.key, e.keyCode) if (this.downKeys[key] === undefined) { this.downKeys[key] = true; hotkey.accelerator = Object.keys(this.downKeys).join('+') this.updateHotkey(hotkey, idx); } return false } } onKeyUp={(e) => { delete this.downKeys[cleanUpKeyboardKeys(e.key, e.keyCode)] }} /> { this.downKeys = {} hotkey.accelerator = "" this.updateHotkey(hotkey, idx); }} /> {this.getHotkeyStatusIcon(hotkey)} } expandable={true} input={ this.deleteHotkey(idx)}>{ deleteIcon } {T.t("GENERIC_DELETE")} }> { hotkey.actions?.map((action, actionIdx) => { return ( this.updateHotkeyAction(updatedAction, idx, actionIdx)} onDelete={() => { deleteHotkeyAction(idx, actionIdx) }} monitors={this.state.monitors} monitorNames={this.state.names} /> ) }) } { if(!hotkey.actions?.length) { hotkey.actions = [] } hotkey.actions.push(Object.assign({}, defaultAction)) this.updateHotkey(hotkey, idx) }}>+ {T.t("SETTINGS_HOTKEY_ADD_ACTION")} ) }) } getHotkeyStatusIcon = hotkey => { if (hotkey?.active) { return (
) } else { return (
) } } updateHotkey(hotkey, idx) { this.state.hotkeys[idx] = Object.assign({}, hotkey) window.sendSettings({ hotkeys: this.state.hotkeys.slice() }) this.forceUpdate() } updateHotkeyAction(action, idx, actionIdx) { this.state.hotkeys[idx].actions[actionIdx] = Object.assign({}, action) window.sendSettings({ hotkeys: this.state.hotkeys.slice() }) this.forceUpdate() } deleteHotkey(idx) { this.state.hotkeys.splice(idx, 1) window.sendSettings({ hotkeys: this.state.hotkeys.slice() }) this.forceUpdate() } getInfoMonitors = () => { if (this.state.monitors == undefined || Object.keys(this.state.monitors).length == 0) { return (
{T.t("GENERIC_NO_COMPATIBLE_DISPLAYS")}

) } else { return Object.values(this.state.monitors).map((monitor, index) => { let brightness = monitor.brightness let brightnessMax = monitor.brightnessMax if (monitor.type == "ddcci" && !monitor.brightnessType) { brightness = "???" brightnessMax = "???" } return (

{monitor.name}

{T.t("SETTINGS_MONITORS_DETAILS_NAME")}: {getMonitorName(monitor, this.state.names)}
{T.t("SETTINGS_MONITORS_DETAILS_INTERNAL_NAME")}: {monitor.hwid[1]}
{T.t("SETTINGS_MONITORS_DETAILS_COMMUNICATION")}: {this.getDebugMonitorType((monitor.type === "ddcci" && monitor.highLevelSupported?.brightness ? "ddcci-hl" : monitor.type))}
{T.t("SETTINGS_MONITORS_DETAILS_BRIGHTNESS")}: {(monitor.type == "none" ? T.t("GENERIC_NOT_SUPPORTED") : brightness)}
{T.t("SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS")}: {(monitor.type !== "ddcci" ? T.t("GENERIC_NOT_SUPPORTED") : brightnessMax)}
{T.t("SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION")}: {(monitor.type == "none" ? T.t("GENERIC_NOT_SUPPORTED") : monitor.min + " - " + monitor.max)}
{T.t("SETTINGS_MONITORS_DETAILS_HDR")}: {(monitor.hdr == "active" ? T.t("GENERIC_ACTIVE") : monitor.hdr == "supported" ? T.t("GENERIC_SUPPORTED") : T.t("GENERIC_UNSUPPORTED"))}

) }) } } getDebugMonitors = () => { if (this.state.monitors == undefined || Object.keys(this.state.monitors).length == 0) { return (
{T.t("GENERIC_NO_COMPATIBLE_DISPLAYS")}

) } else { return Object.values(this.state.monitors).map((monitor, index) => { return ( ) }) } } getFeaturesMonitors = () => { try { const onChange = () => { window.sendSettings({ monitorFeaturesSettings: JSON.parse(JSON.stringify(window.settings.monitorFeaturesSettings)) }) } if (this.state.monitors == undefined || Object.keys(this.state.monitors).length == 0) { return (
{T.t("GENERIC_NO_COMPATIBLE_DISPLAYS")}

) } else { return Object.values(this.state.monitors).map((monitor, index) => { const features = this.state?.rawSettings.monitorFeatures[monitor.hwid[1]] return ( { this.setState({ showAddFeatureOverlay: true, addFeatureMonitor: monitor.hwid[1], addFeatureValue: "", addFeatureError: false }, () => { this.addFeatureInputRef.current.focus() }) }} /> ) }) } } catch (e) { } } getHDRMonitors = () => { try { if (this.state.monitors == undefined || Object.keys(this.state.monitors).length == 0) { return () } else { return Object.values(this.state.monitors).map((monitor, index) => { return ( { this.setHDRMonitor(e.target.checked, monitor) }} checked={(this.state.rawSettings?.hdrDisplays?.[monitor.key] ? true : false)} data-checked={(this.state.rawSettings?.hdrDisplays?.[monitor.key] ? true : false)} type="checkbox" /> } /> ) }) } } catch (e) { console.log(e) } } getSDRMonitorsSettings = () => { try { if (this.state.monitors == undefined || Object.keys(this.state.monitors).length == 0) { return () } else { return Object.values(this.state.monitors).map((monitor, index) => { return ( { this.setSDRMonitor(e.target.checked, monitor) }} checked={(this.state.rawSettings?.sdrAsMainSliderDisplays?.[monitor.key] ? true : false)} data-checked={(this.state.rawSettings?.sdrAsMainSliderDisplays?.[monitor.key] ? true : false)} type="checkbox" /> } /> ) }) } } catch (e) { console.log(e) } } setHDRMonitor = (value, monitor) => { const hdrDisplays = Object.assign({}, this.state.rawSettings?.hdrDisplays) hdrDisplays[monitor.key] = value this.setSetting("hdrDisplays", hdrDisplays) } setSDRMonitor = (value, monitor) => { const sdrDisplays = Object.assign({}, this.state.rawSettings?.sdrAsMainSliderDisplays) sdrDisplays[monitor.key] = value this.setSetting("sdrAsMainSliderDisplays", sdrDisplays) } getHideMonitors = () => { try { if (this.state.monitors == undefined || Object.keys(this.state.monitors).length == 0) { return () } else { return Object.values(this.state.monitors).map((monitor, index) => { return ( { this.setHideMonitor(e.target.checked, monitor) }} checked={(this.state.rawSettings?.hideDisplays?.[monitor.key] ? true : false)} data-checked={(this.state.rawSettings?.hideDisplays?.[monitor.key] ? true : false)} type="checkbox" /> } /> ) }) } } catch (e) { console.log(e) } } setHideMonitor = (value, monitor) => { const hideDisplays = Object.assign({}, this.state.rawSettings?.hideDisplays) hideDisplays[monitor.key] = value this.setSetting("hideDisplays", hideDisplays) } toggleFeature = (monitor, featureRaw) => { const feature = `0x${parseInt(featureRaw).toString(16).toUpperCase()}` if (feature === "0x10" || feature === "0x13") return false; // Skip brightness if (feature === "0x" || feature === "0xNaN") return false; // Skip invalid const newFeatures = Object.assign({}, this.state.rawSettings.monitorFeatures) if (!newFeatures[monitor]) newFeatures[monitor] = {}; newFeatures[monitor][feature] = (newFeatures[monitor][feature] ? false : true); window.sendSettings({ monitorFeatures: newFeatures }) } getDebugMonitorType = (type) => { if (type == "none") { return (<>None ) } else if (type == "ddcci") { return (<>DDC/CI ) } else if (type == "ddcci-hl") { return (<>DDC/CI (HL) ) } else if (type == "wmi") { return (<>WMI ) } else if (type == "studio-display") { return (<>Studio Display ) } else { return (<>Unknown ({type}) ) } } getSkipRestoreMonitors = () => { try { if (this.state.monitors == undefined || Object.keys(this.state.monitors).length == 0) { return () } else { return Object.values(this.state.monitors).map((monitor, index) => { return ( { this.setSkipRestoreMonitor(e.target.checked, monitor) }} checked={(this.state.rawSettings?.userSkipReapply?.indexOf(monitor.hwid[1]) >= 0 ? true : false)} data-checked={(this.state.rawSettings?.userSkipReapply?.indexOf(monitor.hwid[1]) >= 0 ? true : false)} type="checkbox" /> } /> ) }) } } catch (e) { console.log(e) } } setSkipRestoreMonitor = (value, monitor) => { const userSkipReapply = this.state.rawSettings?.userSkipReapply const index = this.state.rawSettings?.userSkipReapply?.indexOf(monitor.hwid[1]) if(index >= 0 && !value) { userSkipReapply.splice(index, 1) } else if(index === -1 && value) { userSkipReapply.push(monitor.hwid[1]) } this.setSetting("userSkipReapply", userSkipReapply) } // Update monitor info recievedMonitors = (e) => { let newMonitors = Object.assign(e.detail, {}) this.lastLevels = [] let numMonitors = 0 for (let key in newMonitors) { if (newMonitors[key].type != "none") numMonitors++; } this.numMonitors = numMonitors this.setState({ monitors: newMonitors }) } // Update settings recievedSettings = (e) => { const settings = e.detail const openAtLogin = settings.openAtLogin const brightnessAtStartup = settings.brightnessAtStartup const linkedLevelsActive = (settings.linkedLevelsActive || false) const updateInterval = (settings.updateInterval || 500) * 1 const remaps = (settings.remaps || {}) const names = (settings.names || {}) const adjustmentTimes = (settings.adjustmentTimes || {}) const killWhenIdle = (settings.killWhenIdle || false) const order = (settings.order || []) const checkTimeAtStartup = (settings.checkTimeAtStartup || false) const checkForUpdates = (settings.checkForUpdates || false) const adjustmentTimeIndividualDisplays = (settings.adjustmentTimeIndividualDisplays || false) const language = (settings.language || "system") const hotkeys = (settings.hotkeys || []) const hotkeyPercent = (settings.hotkeyPercent || 10) const analytics = settings.analytics const useAcrylic = settings.useAcrylic const scrollShortcut = settings.scrollShortcut this.setState({ rawSettings: (Object.keys(settings).length > 0 ? settings : this.state.rawSettings), openAtLogin, brightnessAtStartup, linkedLevelsActive, remaps, updateInterval, names, adjustmentTimes, killWhenIdle, order, checkTimeAtStartup, checkForUpdates, adjustmentTimeIndividualDisplays, language, hotkeys, hotkeyPercent, analytics, useAcrylic, scrollShortcut }, () => { this.forceUpdate() }) } isSection = (name) => { if (this.state.activePage == name) { return true } else { return false } } isIcon = (icon) => (this.state.rawSettings.icon === icon ? true : false) addAdjustmentTime = () => { this.state.adjustmentTimes.push({ brightness: 50, time: "12:30", monitors: {}, useSunCalc: false, sunCalc: "sunrise" }) this.forceUpdate() this.adjustmentTimesUpdated() } adjustmentTimesUpdated = () => { this.setState({ adjustmentTimes: this.state.adjustmentTimes.slice(0) }) this.sendSettingsThrottle({ adjustmentTimes: this.state.adjustmentTimes.slice(0) }) //window.sendSettings({ adjustmentTimes: this.state.adjustmentTimes }) } setSetting = (setting, sentVal) => { let value = sentVal; if (sentVal === "on") value = true; if (sentVal === "off") value = false; const newState = {} newState[setting] = value this.setState({...newState, ...{rawSettings: {...this.state.rawSettings, ...{[setting]: value} } } }) window.sendSettings(newState) } renderToggle = (setting, showText = true, textSide = "right", inverse = false) => { const isActive = (this.state.rawSettings?.[setting] ? true : false) const isVisiblyActive = (inverse ? !isActive : isActive) return (
{ this.setSetting(setting, e.target.checked) }} checked={isActive} data-checked={isVisiblyActive} type="checkbox" />
{(isVisiblyActive ? T.t("GENERIC_ON") : T.t("GENERIC_OFF"))}
) } render() { return (
{T.t("SETTINGS_GENERAL_TITLE")}
{ this.setState({ language: e.target.value }) window.sendSettings({ language: e.target.value }) }}> {this.getLanguages()} )} /> )} /> this.setSetting("windowsStyle", e.target.value)}> )} />
window.sendSettings({ icon: "icon" })}>
window.sendSettings({ icon: "mdl2" })}>
window.sendSettings({ icon: "fluent" })}>
)} /> ' + T.t("SETTINGS_GENERAL_ANALYTICS_LINK") + '')} input={this.renderToggle("analytics")} />
{T.t("SETTINGS_GENERAL_TROUBLESHOOTING")}
' + T.t("SETTINGS_GENERAL_ANALYTICS_LINK") + '')} expandable={true}> { this.setSetting("preferredDDCCIMethod", (e.target.checked ? "legacy" : "accurate")) }} checked={(this.state.rawSettings.preferredDDCCIMethod == "legacy")} data-checked={(this.state.rawSettings.preferredDDCCIMethod == "legacy")} type="checkbox" />
{((this.state.rawSettings.preferredDDCCIMethod == "legacy") ? T.t("GENERIC_ON") : T.t("GENERIC_OFF"))}
} /> this.setSetting("defaultOverlayType", e.target.value)}> } expandable={true}>

{T.t("SETTINGS_GENERAL_DIS_OVERLAY_TITLE")}: {T.t("SETTINGS_GENERAL_DIS_OVERLAY_DESC")}
{T.t("SETTINGS_GENERAL_ON_OVERLAY_TITLE")}: {T.t("SETTINGS_GENERAL_ON_OVERLAY_DESC")}
{T.t("SETTINGS_GENERAL_FORCE_OVERLAY_TITLE")}: {T.t("SETTINGS_GENERAL_FORCE_OVERLAY_DESC")}

{this.getSkipRestoreMonitors()} window.ipc.send('save-report')}>{T.t("SETTINGS_GENERAL_REPORT_TITLE")}} /> {T.t("SETTINGS_GENERAL_RESET_BUTTON")}} />
{T.t("SETTINGS_TIME_TITLE")}

{T.t("SETTINGS_TIME_DESC")}

{this.getAdjustmentTimes()}

+ {T.t("SETTINGS_TIME_ADD")}

this.setSetting("adjustmentTimeLatitude", e.target.value)} style={{width: "100%", boxSizing: "border-box"}} />
this.setSetting("adjustmentTimeLongitude", e.target.value)} style={{width: "100%", boxSizing: "border-box"}} />
{/* I'll write better CSS later, I promise. */}
window.ipc.send("get-coordinates")} value={T.t("SETTINGS_TIME_SUN_GET")} style={{lineHeight:"1.3",padding:(document.body.dataset.isWin11 === 'true' ? "9px" : "8px"),marginLeft:"6px"}} />
this.setSetting("adjustmentTimeSpeed", e.target.value)}> } />
{T.t("SETTINGS_TIME_IDLE_TITLE")}
this.setSetting("detectIdleTimeMinutes", e.target.value)} />
this.setSetting("detectIdleTimeSeconds", e.target.value)} />
} />
{T.t("GENERIC_ALL_DISPLAYS")}
{this.getInfoMonitors()}
)} /> {this.getHideMonitors()} {this.getRenameMonitors()} {this.getReorderMonitors()}
} /> {this.getSDRMonitorsSettings()}
{T.t("SETTINGS_MONITORS_NORMALIZE_TITLE")}

{T.t("SETTINGS_MONITORS_NORMALIZE_DESC")}

{T.t("SETTINGS_MONITORS_CALIBRATION_DESC")}

{this.getMinMaxMonitors()}
{T.t("SETTINGS_SIDEBAR_FEATURES")}

{T.t("SETTINGS_FEATURES_DESCRIPTION")}

{this.getFeaturesMonitors()}
{ this.setState({ ddcPowerOffValue: parseInt(e.target.value) }) window.sendSettings({ ddcPowerOffValue: parseInt(e.target.value) }) }}> }> ⚠️ {T.t("SETTINGS_FEATURES_POWER_WARNING")}} />
{T.t("SETTINGS_GENERAL_SCROLL_TITLE")}
{ this.state.rawSettings.scrollShortcutAmount = parseInt(e.target.value) window.sendSettings({ scrollShortcutAmount: parseInt(e.target.value) }) this.forceUpdate() }} /> } />
{T.t("SETTINGS_HOTKEYS_TOD_TITLE")}
}> {T.t("SETTINGS_HOTKEYS_TOD_NOTE")} { (this.state.rawSettings?.sleepAction === "ddcci" || this.state.rawSettings?.sleepAction === "ps_ddcci" ? (

⚠️ {T.t("GENERIC_DDC_WARNING")}
) : null) }
} />

{T.t("SETTINGS_PROFILES_TITLE")}

{T.t("SETTINGS_PROFILES_DESC")}

{this.state.rawSettings?.profiles?.map((profile, idx) => { profile[key] = value sendSettings({ profiles: this.state.rawSettings?.profiles }) this.forceUpdate() }} onDelete={ () => { this.state.rawSettings?.profiles.splice(idx, 1) sendSettingsImmediate({ profiles: this.state.rawSettings?.profiles }) this.forceUpdate() } } />)}

addNewProfile(this.state)}>+ {T.t("SETTINGS_PROFILES_ADD")}

{T.t("SETTINGS_UPDATES_TITLE")}

{T.h("SETTINGS_UPDATES_VERSION", '' + (window.version ? `${window.version}${window.versionTag && window.versionBuild ? ` (${window.versionBuild})` : ""}` : "not available") + '')}

{this.getUpdate()}
{ window.sendSettings({ branch: e.target.value }) }}> } />
{ window.requestMonitors(true) }}>Refresh Monitors window.ipc.send('flush-vcp-cache')}>Clear Cache}> window.ipc.send('save-report')}>Generate Report} /> window.ipc.send('open-settings-file')}>Open Settings} expandable={true} forceExpandable={true}>

{JSON.stringify(this.state.rawSettings, undefined, 2)}

{JSON.stringify(window.allMonitors, undefined, 2)}
Other
this.setSetting("udpPortStart", e.target.value)} />} /> { window.sendSettings({ preferredDDCCIMethod: e.target.value }) }}> } /> {this.getHDRMonitors()} this.setSetting("idleRestoreSeconds", e.target.value)} /> } /> this.setSetting("wakeRestoreSeconds", e.target.value)} /> } /> this.setSetting("hardwareRestoreSeconds", e.target.value)} /> } /> this.setSetting("checkVCPWaitMS", e.target.value)} /> } /> this.setSetting("scrollFlyoutAmount", e.target.value)} /> } />

{T.t("SETTINGS_FEATURES_ADD_DESC")}

this.setState({ addFeatureValue: e.target.value })} onKeyUp={e => { if (e.which === 13 && this.state.addFeatureValue) { // Enter this.addFeatureOKRef.current.click() } else if (e.which === 27) { // Escape this.addFeatureCancelRef.current.click() } }} />

{T.t("SETTINGS_FEATURES_ADD_EXISTS")}

this.setState({ showAddFeatureOverlay: false })} /> { let isActive = false const vcp = vcpStr(this.state.addFeatureValue) try { isActive = this.state.rawSettings.monitorFeatures[this.state.addFeatureMonitor][vcp]; } catch (e) { } if (isActive) { this.setState({ addFeatureError: true }) } else { this.setState({ showAddFeatureOverlay: false }) this.toggleFeature(this.state.addFeatureMonitor, vcp) } }} />
); } } function addNewProfile(state) { if (!state.rawSettings?.profiles) return false; const id = uuid() const profile = { id, uuid: uuid(), name: "", overlayType: "normal", setBrightness: false, monitors: {}, showInMenu: false } state.rawSettings.profiles.push(profile) sendSettings({ profiles: state.rawSettings.profiles }) } function getProfileMonitors(monitors, profile, onChange) { return Object.values(monitors).map((monitor, idx) => { if (monitor.type == "none") { return (null) } else { let level = (profile.monitors?.[monitor.id] ?? 50) return ( { profile.monitors[monitor.id] = level onChange(profile, monitor.id, level) }} level={level} scrolling={false} />) } }) } function getMonitorName(monitor, renames) { if (Object.keys(renames).indexOf(monitor.id) >= 0 && renames[monitor.id] != "") { return renames[monitor.id] + ` (${monitor.name})` } else { return monitor.name } } function AppProfile(props) { const { profile, updateValue, onDelete, monitors } = props if (!profile.monitors) profile.monitors = {}; return ( updateValue("name", e.target.value)} style={{width:"100%"}}>} expandable={true} input={{ deleteIcon } {T.t("GENERIC_DELETE")}} className="appProfileItem win10-has-background" key={profile.id}>
{ updateValue("setBrightness", e.target.checked) }} checked={profile.setBrightness} data-checked={profile.setBrightness} type="checkbox" />
{T.t("SETTINGS_PROFILES_BRIGHTNESS_TOGGLE")}
{(profile.setBrightness ? getProfileMonitors(monitors, profile, profile => updateValue("monitors", profile.monitors)) : null)}
{(profile.setBrightness ? (
{ updateValue("showInMenu", e.target.checked) }} checked={profile.showInMenu} data-checked={profile.showInMenu} type="checkbox" />
{T.t("SETTINGS_PROFILES_SHOW_MENU")}
) : null)} } />
{T.t("SETTINGS_PROFILES_TRIGGER_TITLE")} ({T.t("GENERIC_OPTIONAL")})

{T.t("SETTINGS_PROFILES_APP_DESC")}

updateValue("path", e.target.value)} style={{width:"100%"}}>

{T.t("SETTINGS_PROFILES_OVERLAY_DESC")}

} />
) } function SettingsPage(props) { if (props.current === props.id) { return (
{props.children}
) } return null } function ActionItem(props) { const { action, monitors, monitorNames } = props const showDisplaysList = (action.type != "off" && action.type != "refresh") const getHotkeyMonitors = () => { try { if(action.allMonitors) return (null) if (monitors == undefined || Object.keys(monitors).length == 0) { return (
{T.t("GENERIC_NO_COMPATIBLE_DISPLAYS")}
) } else { return Object.values(monitors).map((monitor, index) => { if(monitor.type === "none") return null; return (
{ if (!action.monitors) action.monitors = {}; action.monitors[monitor.id] = e.target.checked props.onChange?.(action) }} checked={(action.monitors?.[monitor.id] ? true : false)} data-checked={(action.monitors?.[monitor.id] ? true : false)} type="checkbox" />
{getMonitorName(monitor, monitorNames)}
) }) } } catch (e) { console.log(e) } } const getHotkeyInput = () => { if (action.type === "off") { return (

{T.t("SETTINGS_HOTKEY_OFF_WARN")}

) } else if (action.type === "refresh") { return null } else { let selectBoxValue = action.target if (!(selectBoxValue === "brightness" || selectBoxValue === "sdr" || selectBoxValue === "contrast" || selectBoxValue === "volume" || selectBoxValue === "powerState")) { selectBoxValue = "vcp" } const selectBox = (
) const singleValue = () => (
{ const value = e.target.value action.value = value ?? 0 props.onChange?.(action) }} />
) const listOfValues = () => (
{action.values?.map((value, idx2) => { return (
{ const value = e.target.value action.values[idx2] = value ?? 0 props.onChange?.(action) }} /> {idx2 ? ( { action.values.splice(idx2, 1) props.onChange?.(action) }} value={T.t("GENERIC_DELETE")} /> ) : null}
) })}

{ action.values.push([0]) props.onChange?.(action) }}>+ {T.t("SETTINGS_HOTKEY_ADD_VALUE")}

) return ( <>
{selectBox}
{ action.target = e.target.value props.onChange?.(action) }} />
{action.type === "cycle" ? listOfValues() : singleValue()} ) } } return (
{ props.onDelete ? :
{props.title ?? T.t("SETTINGS_HOTKEY_ACTION")}
}
{ action.allMonitors = e.target.checked props.onChange?.(action) }} checked={action.allMonitors} data-checked={action.allMonitors} type="checkbox" />
{T.t("GENERIC_ALL_DISPLAYS")}
{getHotkeyMonitors()}
{getHotkeyInput()}
) } ================================================ FILE: src/components/Slider.jsx ================================================ import React from "react"; import { useEffect, Component } from "react" import PropTypes from 'prop-types'; export default class Slider extends Component { firingEvent = false handleChange = (event) => { if(event.target.value !== this.props.level) this.setState({ level: this.cap(event.target.value) }, this.fireChange) } handleWheel = (event) => { if (this.props.scrolling === false) return false; this.setState({ level: this.cap((this.state.level * 1) + Math.round(event.deltaY * -1 * 0.01 * (this.props.scrollAmount ?? 1))) }, this.fireChange) } fireChange = () => { if (this.firingEvent === false && this.props.onChange && typeof this.props.onChange == "function") { this.firingEvent = true this.props.onChange(this.cap(this.state.level) * 1, this) this.firingEvent = false } } getName = () => { if (this.props.name) { return (
{(this.props.monitortype == "wmi" ? : )}
{this.props.name}
{this.props.afterName}
) } } cap = (level) => { const min = (this.props.min || 0) * 1 const max = (this.props.max || 100) * 1 let capped = level * 1 if (level < min) { capped = min } else if (level > max) { capped = max } return capped } progressStyle = () => { const min = (this.props.min || 0) * 1 const max = (this.props.max || 100) * 1 const level = this.cap((this.props.level || 0) * 1) return { width: (0 + (((level - min) * (100 / (max - min))))) + "%" } } constructor(props) { super(props); this.state = { level: this.cap((this.props.level === undefined ? 50 : this.props.level)), } //this.fireChange() } componentDidUpdate(oldProps) { if (oldProps.max != this.props.max || oldProps.min != this.props.min) { this.setState({ level: this.cap(this.props.level) }, this.fireChange()) } } render() { const min = (this.props.min || 0) * 1 const max = (this.props.max || 100) * 1 const level = this.cap(this.props.level) return (
{this.getName()}
); } }; ================================================ FILE: src/components/Titlebar.jsx ================================================ import React from "react"; export default class Titlebar extends React.Component { constructor(props) { super(props) this.state = { active: false } } render() { return (
{this.props.title || ""}
{ window.ipc.send("windowMinimize") }}>
{ window.ipc.send("windowToggleMaximize") }}>
{ window.ipc.send("windowClose")}}>
); } }; ================================================ FILE: src/css/common.scss ================================================ .button { background: var(--button-background); border: 2px solid var(--button-background); line-height: 0; padding: 15px 12px; //margin-top: 10px; display: inline-flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 500; text-decoration: none; .icon { margin-right: 8px; } &:hover { border-color: var(--input-border); } &.disabled { opacity: 0.5; pointer-events: none; } } body[data-is-win11="true"] { .button { background: var(--button-background); color: var(--page-text); border-radius: 6px; border: 0; box-shadow: inset 0 0.25px 0 0.5px var(--button-border), 0 0.5px 1px 0 rgba(0, 0, 0, 0.203); font-weight: 400; box-sizing: border-box; &:hover { background: var(--button-highlight); } &.button-primary { background-color: var(--button-primary-background); color: var(--page-background); &:hover { background-color: var(--button-primary-background-hover); } } &.full-width { width: 100%; } } } ================================================ FILE: src/css/intro.scss ================================================ body, html { background: transparent; } body { padding: 80px; box-sizing: border-box; } .page { background: var(--page-background); color: var(--tray-text); font-family: 'Segoe UI Variable Text', 'Segoe UI';; position: absolute; bottom: 10px; left: 10px; width: calc(100% - 20px); height: calc(100% - 58px); padding: 20px; box-sizing: border-box; border: 1px solid var(--window-border); user-select: none; overflow: visible; text-align: center; box-shadow: 0 3px 12px -8px black; line-height: 1; user-select: none; animation: introIn 1s; @keyframes introIn { 0% { opacity: 0; transform: scale(0.96); } 80% { opacity: 0; transform: scale(0.96); } 100% { opacity: 1; transform: scale(1); } } } $margin: 22px; img { width: 84px; height: 84px; margin: -62px auto 0; } .intro-title { font-size: 18px; font-weight: 700; margin: $margin auto 0; } p { max-width: 320px; margin: $margin auto 0; font-size: 14px; line-height: 20px; } video { margin: $margin auto 0; border: 1px solid rgba(122, 122, 122, 0.25); } .button { background: var(--window-border); border: 2px solid var(--window-border); line-height: 0; padding: 16px 0px; margin: 34px auto 0; display: block; font-size: 16px; width: 200px; cursor: pointer; &:hover { border-color: var(--input-border); } } // Windows 11 style body[data-is-win11="true"] { .page { background-color: var(--page-background); border: 1px solid var(--tray-border); border-radius: 8px; box-shadow: 0 8px 15px -5px rgb(0 0 0 / 75%); } .button { background: var(--button-background); color: var(--page-text); border-radius: 6px; border: 0; box-shadow: inset 0 0.25px 0 0.5px var(--button-border), 0 0.5px 1px 0 rgba(0, 0, 0, 0.203); &:hover { background: var(--button-highlight); } } } ================================================ FILE: src/css/mica.scss ================================================ #mica { position: absolute !important; top: 0; left: 0; width: 100vw; height: 100vh; overflow: hidden; background: var(--mica-base-color); .displays { width: 100vw; height: 100vh; position: relative; overflow: visible; mix-blend-mode: color; visibility: hidden; .blur { position: relative; width: 100%; height: 100%; opacity: 0.3; //filter: blur(100px); } img { display: block; } } .noise { position: absolute; top: 0; left: 0; background: url(../assets/noise.png) 0 0 repeat; width: 100vw; height: 100vh; opacity: 0.017; } } body[data-focused="false"] { #mica .blur { //opacity: 0; } } body[data-use-mica="false"], body[data-is-win11="false"], body[data-transparent="false"] { #mica { display: none; } } ================================================ FILE: src/css/page.scss ================================================ @use "common.scss"; $sidebarWidth: 300px; $sidebarWidthSmall: 44px; html, body { background: transparent; } #settings>.window-base { background: var(--page-background); background: none; color: var(--tray-text); font-family: 'Segoe UI', sans-serif; position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding-top: 0px; box-sizing: border-box; border: 1px solid var(--window-border); user-select: none; overflow: hidden; } #page { overflow: auto; padding: 20px; box-sizing: border-box; height: 100%; background: var(--page-background); padding-top: 30px; flex: 1; max-height: 100vh; min-height: 100vh; border-top: 30px solid var(--page-background); position: relative; top: -30px; } ::-webkit-scrollbar { width: 10px; } /* Track */ ::-webkit-scrollbar-track {} /* Handle */ ::-webkit-scrollbar-thumb { background: rgba(122, 122, 122, 1); } ::-webkit-scrollbar-thumb:window-inactive { background: rgba(122, 122, 122, 0.5); } // Titlebar .window-titlebar { box-sizing: border-box; width: calc(100% - 2px); padding: 0 0px; overflow: visible; flex-shrink: 0; align-items: center; justify-content: center; user-select: none; zoom: 1; line-height: 22px; height: 30px; display: flex; position: static; margin: 1px 0 0 1px; top: 1px; left: 1px; z-index: 100; @media (max-width: 700px) { background: var(--page-background); } .appIcon { width: 16px; height: 16px; background: url('../../src/assets/logo.png') center center no-repeat; background-size: contain; margin-right: 10px; } .titlebar-drag-region { top: 0; left: 0; display: block; position: absolute; width: 100%; height: 30px; z-index: -1; -webkit-app-region: drag } .window-title { font-size: 12px; padding: 0 10px; display: flex; align-items: center; z-index: 4; opacity: 1; transition: opacity 0.2s; @media (max-width: 880px) { opacity: 0; } } .window-controls-container { display: flex; flex-grow: 0; flex-shrink: 0; text-align: center; position: relative; z-index: 3000; -webkit-app-region: no-drag; height: 100%; width: 138px; margin-left: auto; .window-icon-bg { display: inline-block; -webkit-app-region: no-drag; height: 100%; width: 33.34%; &:hover .window-icon { background: var(--titlebar-icon-hover); } &:hover { background-color: rgba(122, 122, 122, .2) } } .window-icon { background: var(--titlebar-icon); height: 100%; width: 100%; -webkit-mask-size: 23.1%; -webkit-mask-size: 10px; } .window-close { -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.279 5.5L11 10.221l-.779.779L5.5 6.279.779 11 0 10.221 4.721 5.5 0 .779.779 0 5.5 4.721 10.221 0 11 .779 6.279 5.5z' fill='%23000'/%3E%3C/svg%3E") no-repeat 50% 50% } .window-unmaximize { -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 8.798H8.798V11H0V2.202h2.202V0H11v8.798zm-3.298-5.5h-6.6v6.6h6.6v-6.6zM9.9 1.1H3.298v1.101h5.5v5.5h1.1v-6.6z' fill='%23000'/%3E%3C/svg%3E") no-repeat 50% 50% } .window-maximize { -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 0v11H0V0h11zM9.899 1.101H1.1V9.9h8.8V1.1z' fill='%23000'/%3E%3C/svg%3E") no-repeat 50% 50% } .window-minimize { -webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 4.399V5.5H0V4.399h11z' fill='%23000'/%3E%3C/svg%3E") no-repeat 50% 50% } .window-icon-bg.window-close-bg:hover { background-color: rgba(232, 17, 35, .9) } .window-icon.window-close:hover { background-color: #fff !important; } } } .window-base-inner { display: flex; } select, input { -webkit-appearance: none; background: var(--page-background); color: var(--tray-text); border: 2px solid var(--input-border); outline: none; padding: 8px; line-height: 1.3; font-size: 14px; font-family: inherit; font-weight: 400; margin-top: 10px; margin-bottom: 15px; box-sizing: border-box; &:hover { border-color: var(--input-border-hover); } &:active { background: var(--input-active-background); } } input[type="text"] { min-width: 235px; } input[type="checkbox"] { width: 50px; padding: 3px; border-radius: 20px; &:before { content: ''; display: block; width: 12px; height: 12px; border-radius: 10px; background: var(--input-border-hover); transform: translateX(0px); transition: transform 0.166s; } &[data-checked="true"] { background: var(--system-accent-color); border-color: var(--system-accent-color); &:before { background: white; transform: translateX(28px); } } } input[type="time"] { padding: 5px 5px 5px 10px; margin-right: 5px; line-height: 1; @media screen and (prefers-color-scheme: dark) { &::-webkit-calendar-picker-indicator { background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNMTEuOTkgMkM2LjQ3IDIgMiA2LjQ4IDIgMTJzNC40NyAxMCA5Ljk5IDEwQzE3LjUyIDIyIDIyIDE3LjUyIDIyIDEyUzE3LjUyIDIgMTEuOTkgMnpNMTIgMjBjLTQuNDIgMC04LTMuNTgtOC04czMuNTgtOCA4LTggOCAzLjU4IDggOC0zLjU4IDgtOCA4eiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48cGF0aCBmaWxsPSIjRkZGRkZGIiBkPSJNMTIuNSA3SDExdjZsNS4yNSAzLjE1Ljc1LTEuMjMtNC41LTIuNjd6Ii8+PC9zdmc+); } } } label { font-size: 14px; display: block; &+p { margin-top: 2px; } } .sectionTitle { font-size: 28px; font-weight: 400; margin-bottom: 20px; line-height: 1; } .sectionSubtitle { font-size: 18px; font-weight: 600; margin-bottom: 10px; line-height: 1; display: flex; .icon { font-size: 22px; font-weight: 400; margin-top: -1px; } div+div { margin-left: 10px; } } .pageSection { padding-bottom: 40px; max-width: 800px; &[data-active] { display: none; } &[data-active="true"] { display: block; } &.debug { user-select: text; } } .monitorItem { max-width: 320px; animation: sliderFadeIn 0.4s; @keyframes sliderFadeIn { 0% { opacity: 0; } 33% { opacity: 0; } 100% { opacity: 1; } } } .monitorItem-list { display: flex; flex-wrap: wrap; gap: 30px; } .adjustmentTimes { padding-top: 5px; .item { padding-top: 20px; margin-top: 20px; border-top: 1px solid var(--page-text-mid); .monitor-item { max-width: 320px; } &+.item {} } select { margin-right: 4px; } } .hotkey-item { padding-top: 20px; margin-top: 20px; border-top: 1px solid var(--page-text-mid); } .detected-vcp-codes { .vcp-code { & + .vcp-code { margin-top: 10px; } } .supported-values { font-size: 16px; opacity: 0.7; overflow-wrap: anywhere; } } p { font-size: 14px; color: var(--page-text-mid); b, strong { color: var(--page-text); } } a { text-decoration: underline; cursor: pointer; color: var(--page-text); &:hover { color: var(--page-text-mid); } } select { appearance: auto; } .icon { font-family: "Segoe MDL2 Assets"; &.red { color: red; } &.green { color: green; } &.vfix { display: inline-block; position: relative; top: 2px; } } .inputToggle-generic { display: flex; flex-direction: row; justify-content: flex-start; align-items: center; .text { font-size: 14px; line-height: 1; margin-top: -5px; margin-left: 8px; } &[data-textside="left"] { input { order: 2; } .text { margin-left: 0; margin-right: 8px; } } } .reorderList { max-width: 360px; width: 100%; border: 1px solid var(--window-border); .sectionSubtitle { padding: 15px; margin: 0; } .no-displays-message { margin: 10px 12px -10px 12px; } } .changelog { white-space: pre-wrap; padding: 10px 20px 20px; margin: 20px 0 5px; border-top: 1px solid var(--page-text-mid); border-bottom: 1px solid var(--page-text-mid); line-height: 0; p, h1, h2, h3, h4, h5, ul, ol { line-height: 1.4; } } .progress-bar { position: relative; width: 100%; height: 5px; max-width: 320px; background: var(--window-border); &>div { position: absolute; top: 0; left: 0; width: 0%; height: 100%; background: var(--system-accent-color); } } .icons-row { display: flex; margin: 3px -5px; } .icon-option { margin: 5px; cursor: pointer; user-select: none; img { width: 32px; padding: 10px; background: #333; background-color: var(--system-accent-dark2); border: 2px solid #333; border-color: var(--system-accent-dark1); filter: saturate(0); } &[data-active="true"] { img { background: var(--system-accent-medium); border-color: var(--system-accent-medium-dark); background-color: var(--system-accent-dark1); border-color: var(--system-accent-light2); filter: saturate(1); } } } .hotkey-monitors { .hotkey-item { margin-top: 30px; } .name {} .row { display: flex; //justify-content: end; align-items: center; line-height: 1; &>* { margin-right: 5px; } } .title {} input[type="text"] { padding: 6px; font-size: 14px; height: auto; box-sizing: border-box; line-height: 1; &:focus { border-color: var(--system-accent-color); } } input[type="button"] { @extend .button; padding: 8px; line-height: 1; } } // DDC/CI Features .feature-row { display: flex; justify-content: flex-start; .monitor-item { flex: 1; } } .feature-icon { display: flex; justify-content: center; align-items: center; font-size: 28px; padding-right: 18px; } .feature-toggle-list { padding-top: 1px; } .feature-toggle-row { display: flex; justify-content: flex-start; align-items: center; padding: 6px 0; input { margin: 0; } } .feature-toggle-set { margin: 0 0 0 -20px; padding: 0 20px; transition: margin 0.3s, padding 0.3s, background 0.3s; background-color: rgba(0,0,0,0); } .feature-toggle-set[data-active="true"] { margin-bottom: 10px; margin-top: 10px; background: var(--page-section-bg); padding: 10px 20px; margin-left: -19px; width: calc(100% - 2px); } .feature-toggle-settings { padding: 0; } .feature-toggle-label { padding-left: 15px; flex: 1; .icon { margin-right: 8px } } .profile-monitors { margin: 13px 0; &:empty { margin: 0; } } .input-row { display: flex; justify-content: flex-start; align-items: stretch; gap: 10px; & > * { //flex: 1; } .field { select { width: 100%; } } input[type="text"], input[type="number"], input[type="button"], input[type="time"], select { margin: 0; width: auto; box-sizing: border-box; height: 40px; } input[type="button"] { width: auto; } label + input, label + select { margin-top: 8px !important; } .monitor-item { flex: 1; & + .monitor-item { margin-top: 0; } } & + .input-row { margin-top: 15px; } } .add-feature-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 99; display: flex; justify-content: center; align-items: center; background-color: rgba(50, 50, 50, 0.95); display: none; &[data-show="true"] { animation: featureToggleSettingsIn 0.3s; display: flex; } .inner { background-color: var(--page-background); padding: 20px; border-radius: 3px; width: 100%; max-width: 500px; } .input-row { justify-content: flex-end; } input[type="text"] { width: 100%; } p { margin-top: 0; } } html body[data-is-win11="true"] { .add-feature-overlay { backdrop-filter: blur(5px); } } .hotkey-combo-input { margin: -10px 0 -12px; } .hotkey-values-list { label { margin-bottom: 8px; } input[type="button"] { margin-left: 8px; } .hotkey-value { margin-bottom: 8px; } } .hotkey-action-fields { flex: 1; display: flex; flex-wrap: wrap; gap: 15px; .input-row { margin-top: 0 !important; } } .hotkey-action-type { select { width: 100%; } } .hotkey-action-code { input { min-width: 220px; } } .hotkey-action-value { input { min-width: 100px; } } .hotkey-action-values { width: 100%; padding-top: 10px; input { min-width: 100px; } } .hotkey-monitors-list { margin: -35px 0px auto 0px; width: 200px; background: rgba(122, 122, 122, .1); padding: 25px; order: 2; border-radius: 4px; } // Sidebar #sidebar { position: relative; top: -30px; left: 0px; width: 300px; padding-top: 30px; height: calc(100vh - 2px - 30px); background: var(--tray-background-base); transition: width 0.2s; overflow: hidden; z-index: 3; display: flex; justify-content: flex-start; flex-direction: column; .item { width: 100%; display: flex; flex-direction: row; justify-items: end; align-items: center; padding: 13px; box-sizing: border-box; line-height: 1; &[data-type="debug"] { margin-top: auto; .icon { opacity: 0.1; } .label { opacity: 0; } &[data-active="true"] { .icon, .label { opacity: 1; } } } .icon { padding-right: 13px; font-size: 18px; opacity: 1; transition: opacity 0.2s; } .label { margin-top: -2px; font-size: 14px; opacity: 1; transition: opacity 0.2s; white-space: pre; } &:hover { background: var(--sidebar-item-hover); } &:active {} &:before { content: ' '; width: 4px; min-width: 4px; height: 23px; display: block; position: relative; left: -13px; transform-origin: 0 50%; transform: scaleX(0); background: var(--system-accent-color); transition: transform 0.2s, opacity 0.2s; opacity: 0; } &[data-active='true'] { &:before { transform: scaleX(1); opacity: 1; } } } @media (max-width: 880px) { width: $sidebarWidthSmall; .item { &:before { margin-right: -4px; } .label { opacity: 0 !important; } } } } body[data-transparent=true][data-acrylic=true] .window-base #sidebar { //--tray-background: var(--tray-background-blur) !important; background: none !important; } // Sun Valley tweaks body[data-fluent-icons="true"] { .window-titlebar .window-controls-container { .window-close { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 11 11'%3E%3Cpath d='M5.5,6.28.94,10.84A.53.53,0,0,1,.55,11a.51.51,0,0,1-.39-.16A.51.51,0,0,1,0,10.45a.53.53,0,0,1,.16-.39L4.72,5.5.16.94A.53.53,0,0,1,0,.55.54.54,0,0,1,0,.33.66.66,0,0,1,.16.16.57.57,0,0,1,.34,0,.52.52,0,0,1,.55,0,.53.53,0,0,1,.94.16L5.5,4.72,10.06.16A.53.53,0,0,1,10.45,0a.46.46,0,0,1,.21,0,.55.55,0,0,1,.3.3.46.46,0,0,1,0,.21.53.53,0,0,1-.16.39L6.28,5.5l4.56,4.56a.53.53,0,0,1,.16.39.52.52,0,0,1,0,.21.57.57,0,0,1-.12.18.52.52,0,0,1-.17.12.54.54,0,0,1-.22,0,.53.53,0,0,1-.39-.16Z'/%3E%3C/svg%3E") no-repeat 50% 50% } .window-unmaximize { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 11 11'%3E%3Cpath d='M1.62,11A1.5,1.5,0,0,1,1,10.87a1.68,1.68,0,0,1-.51-.36A1.68,1.68,0,0,1,.13,10,1.5,1.5,0,0,1,0,9.38V3.82A1.5,1.5,0,0,1,.13,3.2a1.82,1.82,0,0,1,.36-.51A1.68,1.68,0,0,1,1,2.33a1.64,1.64,0,0,1,.62-.13H7.18a1.68,1.68,0,0,1,.62.13,1.57,1.57,0,0,1,.51.36,1.57,1.57,0,0,1,.36.51,1.68,1.68,0,0,1,.13.62V9.38a1.64,1.64,0,0,1-.13.62,1.68,1.68,0,0,1-.36.51,1.82,1.82,0,0,1-.51.36,1.5,1.5,0,0,1-.62.13ZM7.15,9.9a.78.78,0,0,0,.21,0,.55.55,0,0,0,.3-.3.46.46,0,0,0,0-.21V3.85a.49.49,0,0,0,0-.21.55.55,0,0,0-.3-.3.49.49,0,0,0-.21,0H1.65a.46.46,0,0,0-.21,0,.55.55,0,0,0-.3.3.78.78,0,0,0,0,.21v5.5a.65.65,0,0,0,0,.21.55.55,0,0,0,.3.3.65.65,0,0,0,.21,0ZM9.9,3.26a2,2,0,0,0-.18-.84A2.21,2.21,0,0,0,8.54,1.27,2.21,2.21,0,0,0,7.7,1.1H2.29A1.66,1.66,0,0,1,2.54.65,1.66,1.66,0,0,1,2.89.3,1.57,1.57,0,0,1,3.34.08,1.81,1.81,0,0,1,3.85,0H7.7A3.25,3.25,0,0,1,9,.26,3.3,3.3,0,0,1,10,1a3.15,3.15,0,0,1,.71,1A3.3,3.3,0,0,1,11,3.3V7.15a1.81,1.81,0,0,1-.08.51,1.57,1.57,0,0,1-.22.45,1.82,1.82,0,0,1-.8.6Z'/%3E%3C/svg%3E") no-repeat 50% 50% } .window-maximize { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 11 11'%3E%3Cpath d='M1.62,11A1.5,1.5,0,0,1,1,10.87a1.68,1.68,0,0,1-.51-.36A1.68,1.68,0,0,1,.13,10,1.5,1.5,0,0,1,0,9.38V1.62A1.5,1.5,0,0,1,.13,1,1.68,1.68,0,0,1,.49.49,1.68,1.68,0,0,1,1,.13,1.5,1.5,0,0,1,1.62,0H9.38A1.5,1.5,0,0,1,10,.13a1.68,1.68,0,0,1,.51.36,1.68,1.68,0,0,1,.36.51,1.5,1.5,0,0,1,.13.62V9.38a1.5,1.5,0,0,1-.13.62,1.84,1.84,0,0,1-.87.87,1.5,1.5,0,0,1-.62.13ZM9.35,9.9a.65.65,0,0,0,.21,0,.55.55,0,0,0,.3-.3.65.65,0,0,0,0-.21V1.65a.65.65,0,0,0,0-.21.55.55,0,0,0-.3-.3.65.65,0,0,0-.21,0H1.65a.65.65,0,0,0-.21,0,.55.55,0,0,0-.3.3.65.65,0,0,0,0,.21v7.7a.65.65,0,0,0,0,.21.55.55,0,0,0,.3.3.65.65,0,0,0,.21,0Z'/%3E%3C/svg%3E") no-repeat 50% 50% } .window-minimize { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http%3A//www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 11 11'%3E%3Cpath d='M.55,5.5a.46.46,0,0,1-.21,0,.55.55,0,0,1-.3-.3A.46.46,0,0,1,0,5a.52.52,0,0,1,0-.21.71.71,0,0,1,.12-.18.57.57,0,0,1,.18-.12.46.46,0,0,1,.21,0h9.9a.46.46,0,0,1,.21,0,.57.57,0,0,1,.18.12.71.71,0,0,1,.12.18A.52.52,0,0,1,11,5a.46.46,0,0,1,0,.21.55.55,0,0,1-.3.3.46.46,0,0,1-.21,0Z'/%3E%3C/svg%3E") no-repeat 50% 50% } } .icon { font-family: "Segoe Fluent Icons", "Segoe MDL2 Assets"; } } // Windows 11 style body[data-is-win11="true"] { background-color: var(--page-background); width: 100vw; height: 100vh; margin: 0; #settings > .window-base { background-color: var(--page-background); background: none; font-family: 'Segoe UI Variable Text', 'Segoe UI'; } &[data-segoe-u-i-variable="true"] { .window-titlebar .window-title { font-family: "Segoe UI Variable", "Segoe UI"; font-weight: 400; font-size: 12px; } #sidebar .item .label { font-family: "Segoe UI Variable", "Segoe UI"; font-size: 13px; font-weight: 400; } .sectionTitle { font-weight: 500; font-family: "Segoe UI Variable Display", "Segoe UI"; font-size: 28px; } } #sidebar, #page { background: none !important; } #sidebar { padding: 45px 0 15px 15px; padding-top: 45px; height: calc(100vh - 2px - 60px); .item { border-radius: 6px; padding: 8px 10px; margin: 4px 0; line-height: 1; &:before { background-color: var(--system-accent-dark2); border-radius: 10px; left: -10px; @media screen and (prefers-color-scheme: dark) { background-color: var(--system-accent-light2); } } &[data-active='true'] { background: var(--sidebar-item-hover); } &[data-type="debug"] { margin-top: auto; } } } #page { padding-top: 19px; border-top-color: transparent; } .window-titlebar .window-title { position: relative; top: 8px; left: 10px; opacity: 1 !important; } input, select { border-radius: 5px; border-width: 1.5px; background-color: var(--page-section-bg); border-color: var(--button-border); transition: background 0.1s; &[type="text"] { border-bottom: 1px solid var(--page-text-mid); } &[type="range"] { background-color: transparent !important; } &:hover { background-color: var(--button-highlight); } } option { background: white; color: black; } input[type="checkbox"] { width: 44px; border-width: 1.5px; border-radius: 50px; border-color: var(--input-border); &::before { background-color: var(--input-border); transform-origin: center; transform: translateY(-0.2px); } &:hover { &:before { transform: translateY(-0.2px) scale(1.2); } } &[data-checked="true"] { background-color: var(--system-accent-dark2); border-color: var(--system-accent-dark2); @media screen and (prefers-color-scheme: dark) { background-color: var(--system-accent-light2); border-color: var(--system-accent-light2); } &:before { transform: translateX(24px) translateY(-0.2px); background-color: var(--page-background); } &:hover { &:before { transform: translateX(22px) translateY(-0.2px) scale(1.2); } } } } .icon-option img { border-radius: 4px; background-color: #81818145; border-color: var(--button-border); } .icon-option[data-active=true] img { background: var(--system-accent-medium); border-color: var(--system-accent-medium-dark); background-color: var(--system-accent-dark1); border-color: var(--system-accent-light2); } .reorderList { border-color: var(--button-border); border-width: 1.5px; border-width: 0; border-radius: 5px; max-width: none; } .pageSection { padding-bottom: 40px; max-width: 1000px; width: 100%; &.is-panel { background: var(--page-section-bg); border-radius: 4px; padding: 20px; margin-bottom: 20px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); } } .settings-page { display: flex; flex-direction: column; align-items: center; animation: pageSectionIn 0.6s cubic-bezier(0.075, 0.82, 0.165, 1); @keyframes pageSectionIn { 0% { opacity: 0; transform: translateY(90px); } 80% { opacity: 1; } 100% { transform: translateY(0px); } } } ::-webkit-scrollbar-thumb { border-radius: 20px; } &[data-focused="false"] { #mica img { opacity: 0; } } .changelog { border-color: #8181818c; } } #mica { background: none !important; img { transition: opacity 0.5s; opacity: 1; } } body[data-is-win11="false"] { .win11only { display: none; } } body[data-is-win11="true"] { .win10only { display: none; } } .try-catch-failure { user-select: auto; } ================================================ FILE: src/css/panel.scss ================================================ @use "common.scss"; // // Defaults // html, body { background: transparent; min-height: 100vh; overflow: hidden; padding: 0; margin: 0; position: relative; user-select: none; } // // Panel // #root { &>.window-base { background: var(--tray-background); box-shadow: 0.5px 0.5px 0 0.5px var(--tray-border) inset; color: var(--tray-text); font-family: 'Segoe UI Variable Text', 'Segoe UI'; width: 100vw; box-sizing: border-box; padding: 15px 15px 0 15px; position: absolute; top: 0; left: 0; transition: opacity 0s, transform 0s cubic-bezier(0.075, 0.82, 0.165, 1), background-color 0.5s, border-color 0.2s, color 0.2s; transform: translate(0px, 0px); opacity: 1; pointer-events: none; & > div { z-index: 2; position: relative; &#mica { z-index: 1; } } } &[data-visible="true"]>.window-base { pointer-events: all; } &[data-position="TOP"]>.window-base { box-shadow: 0.5px -0.5px 0 0.5px var(--tray-border) inset; top: auto !important; bottom: 0 !important; } &[data-position="LEFT"]>.window-base { box-shadow: -0.5px 0.5px 0 0.5px var(--tray-border) inset; } &[data-position="RIGHT"]>.window-base {} } @media (prefers-reduced-motion: reduce) { #root>.window-base { transition: none !important; } } body[data-acrylic="false"], body[data-transparent="false"], body[data-use-native-animation="false"] { #root { &>.window-base { opacity: 0; pointer-events: none; transform: translateY(120px); } &[data-visible="true"]>.window-base { transition: opacity 0.2s, transform 0.5s cubic-bezier(0.075, 0.82, 0.165, 1), background-color 0.85s, border-color 0.2s, color 0.2s; transform: translateY(0%) !important; opacity: 1; pointer-events: all; } &[data-position="TOP"]>.window-base { border-width: 0 0 1px 1px; transform: translateY(-120px); } &[data-position="LEFT"]>.window-base { border-width: 1px 1px 0 0; transform: translateX(-120px); } &[data-position="RIGHT"]>.window-base { transform: translateX(120px); } } } // // Titlebar // .titlebar { display: flex; justify-content: space-between; align-items: center; user-select: none; margin-bottom: 20px; .title { font-size: 14.5px; font-weight: 400; } .icons { display: flex; font-family: "Segoe MDL2 Assets"; font-size: 22px; div { cursor: pointer; opacity: 0.7; &:hover { opacity: 1; } &[data-active="true"] { color: var(--system-accent-medium); opacity: 1; } } div+div { margin-left: 20px; } } } // // Update bar // .updateBar { display: flex; justify-content: space-between; align-items: center; background: var(--system-accent-color); color: white; padding: 15px; width: 100%; margin: 0px -15px 0px; line-height: 1; .left { font-size: 13px; opacity: 0.8; &.progress { padding-right: 15px; width: 100%; } } .right { display: flex; font-size: 13px; align-items: center; a { cursor: pointer; padding: 1px 5px; margin: 0px 0; font-weight: 500; opacity: 1; &:hover { opacity: 0.8; } &+a { margin-left: 6px; } } .icon { margin-bottom: -1px; } } } .progress-bar { position: relative; width: 100%; height: 5px; max-width: 320px; background: rgba(white, 0.2); &>div { position: absolute; top: 0; left: 0; width: 0%; height: 100%; background: white; } } .icon { font-family: "Segoe MDL2 Assets"; &.icon-text { font-family: inherit !important; font-size: 13px; min-width: 22px; text-align: center; } } .monitor-item { margin: 0 !important; height: 73px; .input--range { //padding-bottom: 15px; } } $overlayBarWidth: 11px; $overlayBarWidthOff: $overlayBarWidth * -0.5; body[data-is-win11="false"] #root { &[data-mode="overlay"] { .input--range .progress { height: $overlayBarWidth; margin-top: $overlayBarWidthOff; } .input--range .range::-webkit-slider-thumb { height: $overlayBarWidth; width: $overlayBarWidth; border-radius: 0; margin-top: 0px; background: white; } .input--range .range::-webkit-slider-runnable-track { height: $overlayBarWidth; background: #6a6a6a; } .titlebar { display: none; } .monitor-item .input--range { padding-bottom: 15px; } .monitor-item { height: 140px; height: 136px; width: 40px; box-sizing: content-box; overflow: visible; position: relative; align-items: flex-start; } &>.window-base { border: none; border: 0px solid var(--tray-border) !important; width: calc(100% - 60px); width: auto; padding: 2px 13px; transition: none !important; display: flex; background: rgba(19, 19, 19, 0.95) !important; box-shadow: none !important; } .monitor-item .name-row .icon { display: none !important; } .input--range { width: 66px; height: $overlayBarWidth; overflow: visible; position: relative; left: 50%; margin-left: -8px; will-change: transform; } .input--range .rangeGroup { flex: none; width: 80px; transform: rotate(-90deg) translate(0.5px, 0.5px); position: relative; top: 53px; left: -33.5px; } .input--range .val { font-size: 13px; width: 40px; padding-right: 4px; color: white; position: absolute; top: 104px; left: -21px; width: 50px; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .monitor-item .name-row .title { display: none; position: absolute; top: 108px; left: 8px; width: 50px; font-size: 10px; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .updateBar, .feature-power-icon, .feature-icon, .feature-row + .feature-row, .monitor-sliders.extended + .monitor-sliders.extended:before { display: none; } .feature-row { height: auto; margin-top: -18px; } } } // Sun Valley tweaks #root[data-fluent-icons="true"] { .titlebar .icons, .icon { font-family: "Segoe Fluent Icons", "Segoe MDL2 Assets"; } &[data-mode="normal"] { .monitor-item .name-row { margin-bottom: 2px; .icon { margin-bottom: -2px; margin-top: -1px; } } } } #root[data-segoe-u-i-variable="true"] { &[data-mode="normal"] { .titlebar .title { font-family: "Segoe UI Variable Small", "Segoe UI"; font-weight: 300; font-size: 13.5px; } .monitor-item .name-row .title { font-family: "Segoe UI Variable Small", "Segoe UI"; font-weight: 300; font-size: 14.5px; } } } // // DDC/CI Features // .feature-row { display: flex; justify-content: flex-start; align-items: center; height: 34px; margin-top: -10px; padding-bottom: 10px; .monitor-item { flex: 1; display: flex; align-items: center; height: auto; .input--range { padding: 0; .val { font-size: 16px; } } } } .feature-inputs { height: 60px; } .feature-icon { display: flex; justify-content: center; align-items: center; font-size: 22px; padding-right: 18px; .text { font-size: 12.5px; } } .feature-power-icon { display: flex; justify-content: center; align-items: center; text-align: center; color: var(--tray-text); justify-self: flex-end; padding: 6px; margin: -5px 0 -6px auto; cursor: pointer; opacity: 0.7; font-size: 14px; &.simple { margin: -8px 0 -4px auto; } &:hover, &:focus { opacity: 1; } span.icon { font-size: 16px !important; font-weight: 400; margin-right: 6px !important; margin-left: -1px !important; font-family: "Segoe MDL2 Assets", "Segoe Fluent Icons"; // Old icon works better at small sizes } } .monitor-sliders.extended { & + .monitor-sliders.extended { &:before { content: ''; display: block; height: 1px; width: 100%; margin: 10px 0 25px; margin-bottom: 0; } } } .feature-row.large .feature-icon { font-size: 32px; } .feature-row.large .monitor-item .input--range .val { font-size: 22px; } .feature-row.large { height: 42px; } // Windows 11 style body[data-is-win11="true"] { #root[data-mode="normal"], #root[data-mode="overlay"] { & > .window-base { display: flex; flex-direction: column; box-shadow: none; border: 1px solid var(--tray-border); border-radius: 8px; overflow: hidden; top: 12px; left: 12px; width: calc(100vw - 24px); padding: 20px; padding-bottom: 0; transform: translateX(220px); box-shadow: inset 0 0 0 1px #c5c5c547, 0 8px 15px -5px rgb(0 0 0 / 75%); box-shadow: 0 8px 15px -5px rgb(0 0 0 / 75%); box-shadow: none; border: none; filter: drop-shadow(0 5px 6px rgb(0 0 0 / 40%)); @media screen and (prefers-color-scheme: dark) { filter: drop-shadow(0 5px 6px rgb(0 0 0 / 45%)); } &:before { pointer-events: none; content: ''; display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; box-shadow: inset 0 0 0 1px #41414144; z-index: 111; border-radius: 8px; @media screen and (prefers-color-scheme: dark) { box-shadow: inset 0 0 0 1px #c5c5c528; } } .titlebar { position: relative; order: 100; margin: 5px 0 1px -19px; padding: 20px; width: calc(100% - 2px); backdrop-filter: brightness(0.97) saturate(1.25); @media screen and (prefers-color-scheme: dark) { backdrop-filter: brightness(0.85) saturate(1.25); } &:before { content: ""; display: block; position: absolute; top: 0; left: 0; width: 100%; height: 1px; background-color: #000000; opacity: 0.14; mix-blend-mode: color; z-index: 2; } .icons { font-size: 18px; } & > * { position: relative; z-index: 2; } } &[data-position="TOP"]>.window-base { transform: translateX(220px); } &[data-position="LEFT"]>.window-base { transform: translateX(-220px); } &[data-position="RIGHT"]>.window-base { transform: translateX(220px); } } } #root[data-mode="overlay"] { & > .window-base { transform: translateY(220px); padding: 12px 15px; filter: drop-shadow(0 5px 5px rgb(0 0 0 / 18%)); @media screen and (prefers-color-scheme: dark) { filter: drop-shadow(0 5px 5px rgb(0 0 0 / 36%)); } } .titlebar, .updateBar { display: none; } #mica { //display: none !important; } .monitor-sliders.extended { height: 28px; & + .monitor-sliders.extended:before { display: none; } & > .monitor-item { display: none !important; } .name-row, .feature-row { display: none; } .feature-row.feature-brightness { display: flex; height: 28px; margin: 0; padding: 0; .feature-icon { padding: 0; width: 26px; justify-content: flex-start; .icon { font-size: 16px !important; padding-right: 0; } } } } .monitor-item { height: auto; display: flex; justify-content: flex-start; align-items: center; height: 28px; .icon { font-size: 15px !important; padding-right: 0; position: relative; top: -2px; } .name-row { width: 26px; .title, .feature-power-icon { display: none; } } .val { width: 32px; font-size: 13px; padding-right: 4px; } .input--range { position: relative; top: -2px; flex: 1; .range { &::-webkit-slider-thumb { opacity: 0; } } } &+.monitor-item { margin-top: 0px !important; } } } #mica { backdrop-filter: brightness(1.15) saturate(1); //mix-blend-mode: color; .displays .blur { opacity: 0.9; @media screen and (prefers-color-scheme: dark) { opacity: 0.53; } } } } ================================================ FILE: src/css/settings-option.scss ================================================ body[data-is-win11="true"], body[data-is-win11="false"] { .settings-option-elem { width: 100%; margin-bottom: 6px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08); background-color: var(--page-section-bg); border-radius: 4px; .parent-panel { display: flex; justify-content: flex-end; align-items: center; padding: 10px; & > .option-icon { width: 40px; text-align: center; box-sizing: border-box; font-size: 20px; padding-left: 4px; } & > .content-area { padding: 10px; margin: 0 auto 0 0; flex: 1; } & > .input-area { padding: 10px; select { margin: 0; } input[type="text"], input[type="number"] { margin: 0; } .inputToggle-generic { input { order: 2; margin-top: 0; margin-bottom: 0; } .text { margin-left: 0; margin-right: 8px; margin-top: 0; } } .icons-row { margin: -7px -5px -11px; } } & > .expand { display: none; width: 60px; margin: 0 -10px; padding-right: 4px; text-align: center; box-sizing: border-box; user-select: none; cursor: pointer; align-self: stretch; justify-content: center; align-items: center; .icon { transition: transform 0.2s; transform: rotate(0deg); transform-origin: 50% 50%; } } } .option-title { font-size: 16px; font-weight: 400; } .option-description { font-size: 12.5px; margin-top: 2px; opacity: 0.75; font-family: "Segoe UI Variable Small", "Segoe UI"; } &[data-expandable="true"] { .expand { display: flex; } .settings-option-children { display: none; } &[data-expanded="true"] { .expand .icon { transform: rotate(-180deg); } .parent-panel { border-radius: 4px 4px 0 0; } .settings-option-children { display: block; overflow: hidden; & > .children-inner { animation: settingsOptionChildrenIn 0.3s; @keyframes settingsOptionChildrenIn { 0% { transform: translateY(-30px); opacity: 0; } 10% { transform: translateY(-30px); opacity: 0; } 100% { transform: translateY(0px); opacity: 1; } } } } } } } .settings-child-elem { margin-top: 1px; &:last-of-type { & > .child-panel { border-radius: 0 0 4px 4px; } } & > .child-panel { display: flex; justify-content: flex-end; align-items: center; border-top: 1px solid var(--button-border); padding: 5px 50px; padding: 5px 20px; margin-top: -1px; & > .option-icon { padding-right: 10px; } & > .content-area { padding: 10px 0px; margin: 0 auto 0 0; flex: 1; .child-option-title { font-size: 14px; } .child-option-description { font-size: 12.5px; margin-top: 2px; opacity: 0.75; font-family: "Segoe UI Variable Small", "Segoe UI"; } } & > .input-area { padding: 10px 0; input[type="text"], input[type="number"] { margin: 0; } .inputToggle-generic { input { order: 2; margin-top: 0; margin-bottom: 0; } .text { margin-left: 0; margin-right: 8px; margin-top: 0; } } } } } } body[data-is-win11="false"] { .pageSection { max-width: 540px; } .settings-option-elem { //margin-bottom: 20px; margin: 0 -10px 20px; box-shadow: none; border-radius: 0; .parent-panel { //display: block; padding: 0; .input-area { .inputToggle-generic { input { order: 0; margin-left: 0; margin-right: 0; } .text { order: 3; margin-left: 8px; } } } } .option-title { font-size: 16px; font-weight: 500; } .option-description { font-size: 13px; margin-top: 2px; opacity: 0.7; font-family: "Segoe UI"; } &[data-expandable="true"][data-force-expandable="false"] { .parent-panel { display: flex; } .settings-option-children { display: block; } .expand { display: none !important; } } } .settings-child-elem { & > .child-panel { padding: 0 10px; & > .content-area, & > .input-area { padding: 7px 0; } } .child-option-title { font-size: 14px; } .child-option-description { font-size: 12.5px; margin-top: 2px; opacity: 0.75; font-family: "Segoe UI"; } } // Show background in Win10 .settings-option-elem.win10-has-background, .settings-option-elem[data-expandable="true"][data-force-expandable="true"] { background-color: var(--tray-background-base); margin-left: 0px; margin-top: 15px; & > .parent-panel { display: flex; padding: 5px 10px; } .settings-child-elem { border-top: 1px solid var(--page-background); padding: 10px 10px 10px 10px; } } // DDC/CI Features .settings-option-elem.monitor-feature-item { background-color: var(--tray-background-base); margin-left: 0px; margin-top: 15px; // Enable/Disable toggle .input-area { order: -1; } // "+ Add Feature" button & + .input-row { display: block; margin-bottom: 20px; p { margin: 0; .button { display: block; width: 100%; padding: 20px; text-align: center; box-sizing: border-box; } } } .option-icon.icon { margin: 0 -8px 0 -5px; } .settings-child-elem { border-top: 1px solid var(--page-background); padding: 10px 10px 10px 10px; } } .win10-stack-input { & > .child-panel { display: block; } } } ================================================ FILE: src/css/slider.scss ================================================ // // Inputs // .input--range { display: flex; flex-direction: row; justify-content: space-between; align-items: center; width: 100%; position: relative; .progress { background: var(--system-accent-medium); height: 2px; width: 100%; position: absolute; top: 50%; left: 0px; margin-top: -1px; pointer-events: none; } .rangeGroup { flex: 2; position: relative; } .range { display: block; appearance: none; width: 100%; background: transparent; border: none; padding: 0; margin: 0 15px 0 0; -webkit-appearance: none; &:hover { &::-webkit-slider-thumb { background: var(--tray-text); } } &::-webkit-progress-value { background-color: var(--system-accent-light); } &:focus { outline: none; } &::-webkit-slider-thumb { -webkit-appearance: none; height: 24px; width: 8px; box-sizing: content-box; border-radius: 20px; background: var(--system-accent-color); margin-top: -12px; z-index: 3; position: relative; } &::-webkit-slider-runnable-track { width: 100%; height: 2px; background: var(--slider-track-color); border-radius: 0px; transition: background-color 0.1s; border-left: 0; border-right: 0; box-sizing: border-box; } &::-webkit-slider-container { padding: 7px 0; } &:focus::-webkit-slider-runnable-track { //background: var(--slider-track-color-focus); } } .val { width: 52px; box-sizing: border-box; -webkit-appearance: none; background: none; outline: none; border: none; font-size: 22px; text-align: center; color: var(--tray-text); font-family: 'Segoe UI Variable Text', 'Segoe UI'; margin: 0; margin-right: -10px; margin-left: 5px; &::-webkit-inner-spin-button, &::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } } &[data-height="short"] { padding-top: 4px; .val { text-align: left; padding: 0 0 0 4px; font-size: 16px; width: 32px; margin-left: 12px; line-height: 1; margin-bottom: -1px; } } } // // Monitors // .no-displays-message { margin-top: 13px; margin-bottom: 13px; } .monitor-item { &+.monitor-item { margin-top: 20px; } .name-row { display: flex; justify-content: flex-start; align-items: center; width: 100%; .title { font-size: 16px; flex: 1; } .icon { font-family: "Segoe MDL2 Assets"; font-size: 22px; margin-right: 10px; margin-bottom: -3px; } } .input--range { opacity: 1; transition: opacity 0.2s 0.05s; } } [data-refreshing="true"] .monitor-item .input--range { pointer-events: none; opacity: 0.35; } // Sun Valley tweaks #root[data-fluent-icons="true"] { .monitor-item .name-row .icon { font-family: "Segoe Fluent Icons", "Segoe MDL2 Assets"; } } // Windows 11 style body[data-is-win11="true"]:not(.ignoreWin11) { .input--range { .progress { height: 4px; border-radius: 50px; margin-top: 0px; background-color: var(--system-accent-dark1); @media screen and (prefers-color-scheme: dark) { background-color: var(--system-accent-light2); } } .rangeGroup { } .range { &:hover { &::-webkit-slider-thumb { } } &::-webkit-progress-value { } &:focus { } &::-webkit-slider-thumb { height: 10px; width: 10px; border-radius: 50px; background-color: var(--system-accent-dark1); margin-top: -3px; transform: scale(1); box-shadow: 0 0 0 4px var(--slider-thumb-border), 0 0.5px 3px 0 rgba(0, 0, 0, 0.603); height: 10px; width: 10px; transition: box-shadow 0.15s, transform 0.15s; will-change: box-shadow, transform; @media screen and (prefers-color-scheme: dark) { background-color: var(--system-accent-light2); } &:hover { box-shadow: 0 0 0 2px var(--slider-thumb-border), 0 0.5px 3px 0 rgba(0, 0, 0, 0.603); transform: scale(1.3); } } &::-webkit-slider-runnable-track { height: 4px; border-radius: 8px; margin-top: 3px; margin-top: 4px; } &::-webkit-slider-container { } &:focus::-webkit-slider-runnable-track { } } .val { &::-webkit-inner-spin-button, &::-webkit-outer-spin-button { } } } } ================================================ FILE: src/css/vars.scss ================================================ // // Variables // :root { --system-accent-color: hsl(200, 80%, 83%); --system-accent-light: hsl(200, 80%, 83%); --system-accent-medium: hsl(200, 81%, 45%); --system-accent-dark: hsl(200, 80%, 20%); --slider-track-color: #727272; --slider-track-color-focus: #A5A5A5; --tray-background-base: #e4e4e4; --tray-background: var(--tray-background-base); --tray-background-transparent: rgba(219, 219, 219, 0.95); --tray-background-blur: rgba(219, 219, 219, 0); --tray-background-blur-start: rgba(219, 219, 219, 1); --tray-text: black; --tray-border: #aaaaaa; --page-background: #ffffff; --page-text: #000; --page-text-mid: #333; --sidebar-item-hover: #16161626; --window-border: #ddd; --titlebar-icon: #888; --titlebar-icon-hover: #000; --input-border: #555; --input-border-hover: #000; --input-active-background: #ddd; --button-background: #c0c0c0; --button-primary-background: var(--button-background); --slider-track-color: rgba(0, 0, 0, 0.42); --slider-track-color-focus: rgba(0, 0, 0, 0.65); body[data-theme="dark"] { --tray-background: var(--tray-background-base); --tray-background-base: #1f1f1f; --tray-background-transparent: rgba(41, 41, 41, 0.95); --tray-background-blur: rgba(41, 41, 41, 0); --tray-background-blur-start: rgba(41, 41, 41, 1); --tray-text: white; --tray-border: #434343; --page-background: #030303; --page-text: #fff; --page-text-mid: #bbb; --sidebar-item-hover: #ffffff26; --window-border: #222; --titlebar-icon: #888; --titlebar-icon-hover: #fff; --input-border: #6f6f6f; --input-border-hover: #fff; --input-active-background: #444; --button-background: #454545; --button-primary-background: var(--button-background); --slider-track-color: rgba(255, 255, 255, 0.42); --slider-track-color-focus: rgba(255, 255, 255, 0.65); } } body[data-transparent="true"][data-acrylic="false"] { .window-base { --tray-background: var(--tray-background-transparent) !important; } } body[data-transparent="true"][data-acrylic="true"][data-use-native-animation="false"] { .window-base { //--tray-background: var(--tray-background-blur-start) !important; background: transparent !important; background: var(--tray-background-blur-start) !important; } } body[data-transparent="true"][data-acrylic="true"][data-use-native-animation="false"][data-colored-taskbar="true"] { .window-base { //--tray-background: var(--tray-background-blur-start) !important; background: var(--system-accent-transparent) !important; } } body[data-transparent="true"][data-acrylic="true"][data-use-native-animation="false"][data-acrylic-show="true"], body[data-transparent="true"][data-acrylic="true"][data-use-native-animation="false"][data-acrylic-show="true"][data-colored-taskbar="true"] { .window-base { background: var(--tray-background-blur) !important; background: transparent !important; } } body[data-transparent="true"][data-acrylic="true"][data-use-native-animation="true"] { .window-base { background: transparent !important; } } html body[data-theme="dark"] { &[data-colored-taskbar="true"] { .window-base { --tray-background: var(--system-accent-dark) !important; } &[data-transparent="true"] { .window-base { --tray-background: var(--system-accent-transparent) !important; } } } } body[data-colored-taskbar="true"] { div#panel { --tray-background-base: #1f1f1f; --tray-background-transparent: var(--system-accent-transparent); --tray-background: var(--system-accent-dark1) !important; --tray-background-blur: rgba(41, 41, 41, 0); --tray-background-blur-start: rgba(41, 41, 41, 1); --tray-text: white; --tray-border: #434343; --page-background: #030303; --page-text: #fff; --page-text-mid: #bbb; --window-border: #222; --titlebar-icon: #888; --titlebar-icon-hover: #fff; --input-border: #6f6f6f; --input-border-hover: #fff; --input-active-background: #444; --slider-track-color: rgba(255, 255, 255, 0.42); --slider-track-color-focus: rgba(255, 255, 255, 0.65); #mica { background-color: transparent !important; .displays { .blur { opacity: 0.3 !important; } } } } } body[data-colored-taskbar="true"][data-transparent="false"][data-acrylic="false"], html body[data-is-win11="true"][data-colored-taskbar="true"] { div#panel { --tray-background: var(--system-accent-transparent) !important; --tray-background: var(--system-accent-dark2) !important; } } // Windows 11 style html body[data-is-win11="true"], html body[data-is-win11="true"] { --page-background: #f1f3f9 !important; --page-section-bg: #ffffff98; --tray-background: #f2f2f2 !important; --tray-background-transparent: #f2f2f2 !important; --tray-titlebar-bg: #eeeeee; --slider-track-color: #868686; --slider-thumb-border: #ffffff; --button-background: #ffffffc4; --button-highlight: #fffffffa; --button-border: #5c5c5c2b; --button-color-background: var(--system-accent-light2); --button-primary-background: var(--system-accent-dark1); --button-primary-background-hover: var(--system-accent-dark2); --button-color-border: var(--system-accent-light3); --input-border: rgba(0, 0, 0, 0.77); --mica-base-color: #f1f1f1; &[data-theme="dark"] { --page-background: #202020 !important; --page-section-bg: #ffffff0a; --tray-background: #242424 !important; --tray-background-transparent: #242424 !important; --tray-titlebar-bg: rgba(0,0,0,0.18); --slider-track-color: #9b9b9b; --slider-thumb-border: #414141; --button-background: #8a8a8a2b; --button-highlight: #b1b1b123; --button-border: #9797972b; --button-color-background: var(--system-accent-light2); --button-primary-background: var(--system-accent-light3); --button-primary-background-hover: var(--system-accent-light2); --button-color-border: var(--system-accent-light3); --input-border: rgba(255, 255, 255, 0.77); --mica-base-color: #2f2f2f; &[data-use-mica="false"] { --tray-titlebar-bg: rgba(0,0,0,0.24); } } } // Disable high contrast mode from Windows @media (forced-colors: active) { :root { forced-color-adjust: none; } } ================================================ FILE: src/electron.js ================================================ const { app } = require('electron') const fs = require('fs') const path = require('path'); let isDev = app.commandLine.hasSwitch("dev") let package = fs.readFileSync(isDev ? "package.json" : __dirname + '/../package.json') if(package) package = JSON.parse(package) const appVersionFull = (package?.versionBuild ?? app.getVersion()) const appVersion = appVersionFull.split('+')[0] const appVersionTag = appVersion?.split('-')[1] const appBuild = (isDev ? "dev" : appVersionFull.split('+')[1]) const appBuildShort = (appBuild && appBuild.length > 7 ? appBuild.slice(0, 7) : appBuild) const isAppX = (app.name == "twinkle-tray-appx" ? true : false) const isPortable = (app.name == "twinkle-tray-portable" ? true : false) const Utils = require("./Utils") const configFilesDir = (isPortable ? path.join(__dirname, "../../config/") : app.getPath("userData")) const settingsPath = path.join(configFilesDir, `\\settings${(isDev ? "-dev" : "")}.json`) const knownDisplaysPath = path.join(configFilesDir, `\\known-displays${(isDev ? "-dev" : "")}.json`) // Handle multiple instances before continuing const singleInstanceLock = app.requestSingleInstanceLock(process.argv) if (!singleInstanceLock) { try { Utils.handleProcessedArgs(Utils.processArgs(process.argv, app), knownDisplaysPath, settingsPath).then(() => app.exit()) } catch (e) { app.exit() } return false } else { console.log("Starting Twinkle Tray...") app.on('second-instance', handleCommandLine) } function reopenAppWithConsole() { const args = [__filename, "--console"] require('child_process').spawn('conhost.exe', ['cmd.exe', '/c', app.getPath("exe"), ...args], { detached: true, stdio: 'ignore' }).unref() app.exit() return false } // Handle --show-console switch if(app.commandLine.hasSwitch("show-console")) { reopenAppWithConsole() } const { Readable } = require("node:stream") //require("os").setPriority(0, require("os").constants.priority.PRIORITY_BELOW_NORMAL) const { BrowserWindow, nativeTheme, systemPreferences, Menu, ipcMain, screen, globalShortcut, powerMonitor } = require('electron') const uuid = require('crypto').randomUUID // Expose GC app.commandLine.appendSwitch('js-flags', '--expose_gc --max-old-space-size=128') app.commandLine.appendSwitch('disable-http-cache') require("v8").setFlagsFromString('--expose_gc'); global.gc = require("vm").runInNewContext('gc'); // Remove window animations app.commandLine.appendSwitch('wm-window-animations-disabled'); let updateKnownDisplaysTimeout const monitorRules = require('./monitor-rules.json') const knownDDCBrightnessVCPs = monitorRules?.ddcBrightnessCodes const { fork, exec } = require('child_process'); const { VerticalRefreshRateContext, addDisplayChangeListener } = require("win32-displayconfig"); const refreshCtx = new VerticalRefreshRateContext(); const {WindowUtils, MediaStatus, PowerEvents, AppStartup} = require("tt-windows-utils") const setWindowPos = () => { } const AccentColors = require("windows-accent-colors") const Acrylic = require("acrylic") const ActiveWindow = require('@paymoapp/active-window').default; ActiveWindow.initialize() const reg = require('native-reg'); const Color = require('color') const Translate = require('./Translate'); const { EventEmitter } = require("events"); const isReallyWin11 = (require("os").release()?.split(".")[2] * 1) >= 22000 const isAtLeast1803 = (require("os").release()?.split(".")[2] * 1) >= 17134 let ddcciModeTestResult = "auto" let lastKnownDisplays const SunCalc = require('suncalc') app.allowRendererProcessReuse = true // Logging const logPath = path.join(configFilesDir, `\\debug${(isDev ? "-dev" : "")}.log`) const updatePath = path.join(configFilesDir, `\\update.exe`) // Remove old log if (fs.existsSync(logPath)) { try { fs.unlinkSync(logPath) } catch (e) { console.log("Couldn't delete log file") } } const log = async (...args) => { for (let arg of args) { console.log(arg, "\r\n") fs.appendFile(logPath, arg.toString(), () => { }) } } const debug = { log, error: log } if (!isDev && !app.commandLine.hasSwitch("console")) console.log = () => { }; const windowMenu = Menu.buildFromTemplate([{ label: "Dev Tools", role: "toggleDevTools", accelerator: "Ctrl+I" }, { label: "Dev Tools 2", role: "toggleDevTools", accelerator: "Ctrl+Shift+I" }]) function vcpStr(code) { return `0x${parseInt(code).toString(16).toUpperCase()}` } // Monitors thread // Handles WMI + DDC/CI activity let monitorsThread = { send: async function (data) { try { if (!(monitorsThreadReal?.connected && monitorsThreadReal?.exitCode === null)) { startMonitorThread() while(!monitorsThreadReady) { await Utils.wait(50) } } if(!monitorsThreadReady) throw("Thread not ready!"); if(!(monitorsThreadReal?.connected && monitorsThreadReal?.exitCode === null)) throw("Thread not available!"); if((data.type == "vcp" || data.type == "brightness" || data.type == "getVCP") && isRefreshing) while(isRefreshing) { await Utils.wait(50) } monitorsThreadReal.send(data) } catch (e) { console.log("Couldn't communicate with Monitor thread.", e) } }, once: function (message, callback) { try { if (monitorsThreadReal && !monitorsThreadReal.connected) { startMonitorThread() } monitorsEventEmitter.once(message, callback) } catch (e) { console.log("Couldn't listen to Monitor thread.", e) } } } let monitorsThreadReal let monitorsEventEmitter = new EventEmitter() let monitorsThreadReady = false let monitorsThreadStarting = false let monitorsThreadFailed = false function startMonitorThread() { if((monitorsThreadReal?.connected && monitorsThreadReal?.exitCode === null) || monitorsThreadStarting || isWindowsUserIdle) return false; monitorsThreadReady = false monitorsThreadStarting = true console.log("Starting monitor thread") const skipTest = (settings.preferredDDCCIMethod == "auto" ? false : true) monitorsThreadReal = fork(path.join(__dirname, 'Monitors.js'), ["--isdev=" + isDev, "--apppath=" + app.getAppPath(), "--skiptest=" + skipTest], { silent: false }) monitorsThreadReal.on("message", (data) => { if (data?.type) { if (data.type === "ready") { monitorsThreadReady = true monitorsThreadStarting = false isRefreshing = false monitorsThreadReal.send({ type: "settings", settings }) monitorsThreadReal.send({ type: "ddcBrightnessVCPs", ddcBrightnessVCPs: getDDCBrightnessVCPs() }) monitorsThread.send({ type: "wmi-bridge-ok", value: wmiBridgeOK }) getLocalization() } if (data.type === "ddcciModeTestResult") { ddcciModeTestResult = data.value settings.lastDetectedDDCCIMethod = (data.value ? "fast" : "accurate") } monitorsEventEmitter.emit(data.type, data) } }) monitorsThreadReal.on("error", err => { console.error(err) if(monitorsThreadFailed) return false; monitorsThreadFailed = true const options = { title: 'Monitors thread failed', message: 'The monitors thread failed with the following message:', detail: err.message || err.toString(), }; require('electron').dialog.showMessageBox(null, options, (response, checkboxChecked) => { }); stopMonitorThread() setTimeout(() => { if(!monitorsThreadReal?.connected && !monitorsThreadStarting) { startMonitorThread() } }, 1000) }) } function stopMonitorThread() { console.log("Killing monitor thread") monitorsThreadReady = false monitorsThreadStarting = false setIsRefreshing(false) if(monitorsThreadReal?.connected) { monitorsThreadReal.kill() } } function getVCP(monitor, code) { return new Promise((resolve, reject) => { if (!monitor || !code) resolve(-1); const vcpParsed = parseInt(`0x${parseInt(code).toString(16).toUpperCase()}`) const hwid = (typeof monitor === "object" ? monitor.hwid.join("#") : monitor) const timeout = setTimeout(() => { resolve(-1) // Timed out }, 3000) monitorsThread.once(`getVCP::${hwid}::${vcpParsed}`, data => { clearTimeout(timeout) // Write VCP values to monitor object if(data?.value?.[0] != undefined) { try { monitors[hwid?.split("#")[2]].features[vcpStr(vcpParsed)] = data.value?.[0] } catch(e) { console.log(e) } } resolve(data?.value?.[0]) }) monitorsThread.send({ type: "getVCP", code: vcpParsed, monitor: hwid }) }) } // Test if wmi-bridge works properly on user's system let monitorsThreadTest let wmiBridgeOK = false async function doWMIBridgeTest() { return new Promise((resolve, reject) => { monitorsThreadTest = fork(path.join(__dirname, 'wmi-bridge-test.js'), ["--isdev=" + isDev, "--apppath=" + app.getAppPath()], { silent: false }) monitorsThreadTest.on("message", (data) => { if (data?.type === "ready") { console.log("WMI-BRIDGE TEST: READY") } if (data?.type === "ok") { console.log("WMI-BRIDGE TEST: OK") wmiBridgeOK = true monitorsThreadTest.kill() resolve(true) } if(data?.type === "failed") { console.log("WMI-BRIDGE TEST: FAILED") monitorsThreadTest.kill() resolve(false) } }) // Close after timeout setTimeout(() => { try { if (monitorsThreadTest.connected) { console.log("WMI-BRIDGE TEST: Killing thread") monitorsThreadTest.kill() } resolve(false) } catch (e) { console.log(e) } }, 2000) }) } // Mouse wheel scrolling let mouseEventsActive = false let mouseEvents let bounds function enableMouseEvents() { if (mouseEventsActive || settings.disableMouseEvents) return false; mouseEventsActive = true; try { mouseEvents = require("global-mouse-events"); mouseEvents.on('mousewheel', event => { if (!settings.scrollShortcut) return false; try { if (!bounds) return false; if (event.x >= bounds.x && event.x <= bounds.x + bounds.width && event.y >= bounds.y && event.y <= bounds.y + bounds.height) { const delta = settings.invertScroll ? -Math.round(event.delta) : Math.round(event.delta); const amount = delta * settings.scrollShortcutAmount; //refreshMonitors() setRecentlyInteracted(true) updateAllBrightness(amount) // If panel isn't open, use the overlay if (panelState !== "visible") { hotkeyOverlayStart(undefined, true) } pauseMonitorUpdates() // Pause monitor updates to prevent judder willPauseMouseEvents() // Delay pausing mouse events } } catch (e) { console.error(e) } }); // Handle edge cases where "blur" event doesn't properly fire mouseEvents.on("mousedown", (e) => { if (panelSize.visible || !canReposition) { // Check if clicking outside of panel/overlay const pBounds = screen.dipToScreenRect(mainWindow, mainWindow.getBounds()) if (e.x < pBounds.x || e.x > pBounds.x + pBounds.width || e.y < pBounds.y || e.y > pBounds.y + pBounds.height) { if (!canReposition) { // Overlay is displayed hotkeyOverlayHide(true) } else { // Panel is displayed if (!mainWindow.webContents.isDevToolsOpened()) { sendToAllWindows("panelBlur") showPanel(false) } } } } }) } catch (e) { console.error(e) } } function pauseMouseEvents(paused) { // Clear timeout if set if (willPauseMouseEventsTimeout) clearTimeout(willPauseMouseEventsTimeout); if (paused) { if (mouseEvents && !mouseEvents.getPaused()) { console.log("Pausing mouse events...") mouseEvents.pauseMouseEvents() } } else { if (mouseEvents && mouseEvents.getPaused()) { console.log("Resuming mouse events...") mouseEvents.resumeMouseEvents() } } } let willPauseMouseEventsTimeout function willPauseMouseEvents(time = 10000) { if (willPauseMouseEventsTimeout) clearTimeout(willPauseMouseEventsTimeout); willPauseMouseEventsTimeout = setTimeout(() => { pauseMouseEvents(true) willPauseMouseEventsTimeout = null }, time) } // Analytics let analyticsInterval = false let analyticsFrequency = 1000 * 60 * 29 // 29 minutes let lastAnalyticsPing = 0 function pingAnalytics() { // Skip if too recent if (Date.now() < lastAnalyticsPing + (1000 * 60 * 28)) return false; const analytics = require('ga4-mp').createClient("Y1YTliQdTL-moveI0z1TLA", "G-BQ22ZK4BPY", settings.uuid) console.log("\x1b[34mAnalytics:\x1b[0m sending with UUID " + settings.uuid) let events = [] events.push({ name: "page_view", params: { page_location: app.name + "/" + "v" + appVersion + "/" + (appBuild ? appBuild : ""), page_title: app.name + "/" + "v" + appVersion, page_referrer: app.name, os_version: require("os").release(), app_type: app.name, app_version: appVersion, engagement_time_msec: 1 } }) analytics.send(events) lastAnalyticsPing = Date.now() } let monitors = {} let mainWindow; let tray = null let lastTheme = false const panelSize = { width: 356, height: 500, base: 0, visible: false, taskbar: {} } // // // Settings init // // if (!fs.existsSync(configFilesDir)) { try { fs.mkdirSync(configFilesDir, { recursive: true }) } catch (e) { debug.error(e) } } const defaultSettings = { isDev, settingsVer: "v" + appVersion, settingsBuild: appBuild, userClosedIntro: false, theme: "default", icon: "icon", updateInterval: 500, openAtLogin: true, brightnessAtStartup: true, killWhenIdle: false, remaps: {}, hotkeys: [], hotkeyPercent: 10, adjustmentTimes: [], adjustmentTimeIndividualDisplays: false, adjustmentTimeSpeed: "normal", adjustmentTimeAnimate: false, adjustmentTimeLongitude: 0, adjustmentTimeLatitude: 0, checkTimeAtStartup: true, order: [], monitorFeatures: {}, monitorFeaturesSettings: {}, hideDisplays: {}, hdrDisplays: {}, sdrAsMainSliderDisplays: {}, sdrAsMainSlider: false, checkForUpdates: !isDev, dismissedUpdate: '', language: "system", names: {}, analytics: !isDev, scrollShortcut: true, scrollShortcutAmount: 2, scrollFlyoutAmount: 2, invertScroll: false, useAcrylic: false, useNativeAnimation: false, sleepAction: "ps", hotkeysBreakLinkedLevels: true, enableSunValley: true, isWin11: isReallyWin11, windowsStyle: "system", hideClosedLid: false, getDDCBrightnessUpdates: false, detectIdleTimeEnabled: false, detectIdleTimeSeconds: 0, detectIdleTimeMinutes: 5, detectIdleCheckFullscreen: false, detectIdleMedia: false, idleRestoreSeconds: 0, wakeRestoreSeconds: 0, hardwareRestoreSeconds: 0, restartOnWake: false, checkVCPWaitMS: 20, overrideTaskbarPosition: false, overrideTaskbarGap: false, disableAppleStudio: false, disableHighLevel: false, disableWMIC: false, disableWMI: false, disableWin32: false, disableHDR: false, autoDisabledWMI: false, useWin32Event: true, useElectronEvents: true, useWmDisplayChangeEvent: true, useScMonitorPowerEvent: true, useGuidPresenceEvent: true, useGuidBrightnessEvent: true, recreateTray: false, recreateFlyout: false, defaultOverlayType: "safe", disableMouseEvents: false, disableThrottling: false, userDDCBrightnessVCPs: {}, userSkipReapply: [], preferredDDCCIMethod: "accurate", lastDetectedDDCCIMethod: "none", forceLowPowerGPU: false, ddcPowerOffValue: 5, disableAutoRefresh: false, disableAutoApply: false, disableOnLockScreen: false, udpEnabled: false, udpRemote: false, udpPortStart: 14715, udpPortActive: 14715, udpKey: uuid(), showConsole: false, profiles: [], uuid: uuid(), branch: (appVersionTag?.indexOf?.("beta") === 0 ? "beta" : "master") } const tempSettings = { pauseTimeAdjustments: false, pauseIdleDetection: false } let settings = Object.assign({}, defaultSettings) function readSettings(doProcessSettings = true) { try { if (fs.existsSync(settingsPath)) { settings = Object.assign(settings, JSON.parse(fs.readFileSync(settingsPath))) } else { fs.writeFileSync(settingsPath, JSON.stringify({})) } //debug.log('Settings loaded:', settings) } catch (e) { debug.error("Couldn't load settings", e) } // Overrides settings.isDev = isDev settings.killWhenIdle = false if(!isDev && settings.showConsole && !app.commandLine.hasSwitch("console")) { reopenAppWithConsole() } if (settings.updateInterval === 999) settings.updateInterval = 100; // Upgrade settings const settingsVersion = Utils.getVersionValue(settings.settingsVer) const appVersionValue = Utils.getVersionValue(`v${app.getVersion()}`) if(settingsVersion < Utils.getVersionValue("v1.15.0")) { // v1.15.0 try { // Upgrade adjustment times const upgradedTimes = Utils.upgradeAdjustmentTimes(settings.adjustmentTimes) settings.adjustmentTimes = upgradedTimes console.log("Upgraded Adjustment Times to v1.15.0 format!") } catch (e) { console.log("Couldn't upgrade Adjustment Times", e) } try { // Upgrade idle settings if (settings.detectIdleTime) { if (settings.detectIdleTime * 1 > 0) { settings.detectIdleTimeEnabled = true settings.detectIdleTimeSeconds = (settings.detectIdleTime * 1) % 60 settings.detectIdleTimeMinutes = Math.floor((settings.detectIdleTime * 1) / 60) } delete settings.detectIdleTime } console.log("Upgraded Idle settings to v1.15.0 format!") } catch (e) { console.log("Couldn't upgrade Idle settings", e) } } else if(appVersionValue < Utils.getVersionValue("v1.16.0") && settingsVersion >= Utils.getVersionValue("v1.16.0")) { // Downgrade from v1.16.0+ if(settings.hotkeysPre1160) { settings.hotkeys = settings.hotkeysPre1160 } else { settings.hotkeys = {} } console.log("Downgraded settings from v1.16.0+ format!") } if (settingsVersion < Utils.getVersionValue("v1.16.0")) { // v1.16.0 lastKnownDisplays = {} // Reset lastKnownDisplays due to known bug in earlier versions try { // Upgrade hotkeys if (settings.hotkeys && Object.values(settings.hotkeys)?.length >= 0) { settings.hotkeysPre1160 = settings.hotkeys // Save old hotkeys in case of downgrade const newHotkeys = [] for (const hotkey of Object.values(settings.hotkeys)) { const newHotkey = { accelerator: hotkey.accelerator, id: uuid(), actions: [ { monitors: {}, target: "brightness", values: [0], value: 0, allMonitors: false } ] } if (hotkey.monitor === "turn_off_displays") { newHotkey.actions[0].type = "off" } else { newHotkey.monitors = {} if (hotkey.monitor === "all") { newHotkey.actions[0].allMonitors = true } else { newHotkey.actions[0].monitors[hotkey.monitor] = true } newHotkey.actions[0].type = "offset" newHotkey.actions[0].value = settings.hotkeyPercent * hotkey.direction } newHotkeys.push(newHotkey) } settings.hotkeys = newHotkeys } console.log(`Upgraded ${settings.hotkeys.length} hotkeys to v1.16.0 format!`) } catch (e) { console.log("Couldn't upgrade hotkeys", e) } try { // Upgrade Adjustment Times for SunCalc for(const time of settings.adjustmentTimes) { time.useSunCalc = false time.sunCalc = "sunrise" } console.log("Upgraded Adjustment Times to v1.16.0 format!") } catch(e) { console.log("Couldn't upgrade Adjustment Times", e) } try { // Upgrade Monitor Features for v1.16.0 const newMonitorFeatures = {} for(const monitorID in settings.monitorFeatures) { newMonitorFeatures[monitorID] = {} for(const featureName in settings.monitorFeatures[monitorID]) { if(featureName === "contrast") { newMonitorFeatures[monitorID]["0x12"] = settings.monitorFeatures[monitorID][featureName] } else if(featureName === "volume") { newMonitorFeatures[monitorID]["0x62"] = settings.monitorFeatures[monitorID][featureName] } else if(featureName === "powerState") { newMonitorFeatures[monitorID]["0xD6"] = settings.monitorFeatures[monitorID][featureName] } } } settings.monitorFeatures = newMonitorFeatures console.log("Upgraded Monitor Features to v1.16.0 format!") } catch(e) { console.log("Couldn't upgrade Monitor Features", e) } try { // Remove disableOverlay if(settings.disableOverlay === true) { settings.defaultOverlayType = "disabled" } if(settings.disableOverlay !== undefined) { delete settings.disableOverlay } } catch(e) { console.log("Couldn't remove disableOverlay") } } if (settingsVersion < Utils.getVersionValue("v1.16.1")) { // Disable win32display-config events by default as of v1.16.1 // settings.useWin32Event = false } // Fix missing UUIDs for app profiles if(settings.profiles?.length) { for(const profile of settings.profiles) { if(!profile.uuid) { profile.uuid = uuid() } } } // Fix rawSettings bug if(settings.rawSettings) delete settings.rawSettings; // Remove hdrDisplays from v1.17.0-beta1 if (settings.settingsVer == "v1.17.0-beta1" || settingsVersion < Utils.getVersionValue("v1.16.8")) { if(settings.hdrDisplays) delete settings.hdrDisplays; } if (doProcessSettings) processSettings({ isReadSettings: true }); } readSettings(false) if (settings.disableThrottling) { // Prevent background throttling app.commandLine.appendSwitch('disable-renderer-backgrounding'); app.commandLine.appendSwitch('disable-backgrounding-occluded-windows'); app.commandLine.appendSwitch('disable-background-timer-throttling'); } if (settings.forceLowPowerGPU) { app.commandLine.appendSwitch('force_low_power_gpu') } let writeSettingsTimeout = false function writeSettings(newSettings = {}, processAfter = true, sendUpdate = true) { settings = Object.assign(settings, newSettings) if (!writeSettingsTimeout) { writeSettingsTimeout = setTimeout(() => { // Save new settings try { fs.writeFile(settingsPath, JSON.stringify(settings, null, '\t'), (e) => { if (e) debug.error(e) }) } catch (e) { debug.error("Couldn't save settings.", settingsPath, e) } writeSettingsTimeout = false }, 333) } if (processAfter) processSettings(newSettings, sendUpdate); } function processSettings(newSettings = {}, sendUpdate = true) { let doRestartPanel = false let rebuildTray = false let shouldRefreshMonitors = false try { settings.settingsVer = "v" + appVersion settings.settingsBuild = appBuild if (settings.theme) { nativeTheme.themeSource = determineTheme(settings.theme) sendToAllWindows('theme-settings', lastTheme) } handleAccentChange() updateStartupOption((settings.openAtLogin || false)) applyOrder() applyRemaps() if (settings.killWhenIdle && mainWindow && mainWindow.isAlwaysOnTop() === false) { mainWindow.close() } if (newSettings.adjustmentTimes !== undefined) { lastTimeEvent = false restartBackgroundUpdate() rebuildTray = true } if (newSettings.hotkeys !== undefined) { applyHotkeys() } if (newSettings.language !== undefined) { getLocalization() rebuildTray = true } if (newSettings.monitorFeatures !== undefined) { shouldRefreshMonitors = true try { for(const monitorID in newSettings.monitorFeatures) { for(const vcp in newSettings.monitorFeatures[monitorID]) { // Add settings for VCP code if it doesn't exist if(!newSettings.monitorFeaturesSettings?.[monitorID]?.[vcp] && !settings.monitorFeaturesSettings?.[monitorID]?.[vcp]) { if(!settings.monitorFeaturesSettings[monitorID]) { settings.monitorFeaturesSettings[monitorID] = {} } settings.monitorFeaturesSettings[monitorID][vcp] = { icon: "e897", iconType: "windows", iconText: "", iconPath: "", min: 0, max: 100, maxVisual: 100, linked: false } } } } } catch(e) { console.log("Couldn't read monitorFeatures", e) } } if (app.isReady() && newSettings.preferredDDCCIMethod) { monitorsThread.send({ type: "flushvcp" }) setTimeout(() => { refreshMonitors(true) }, 500) } if (settings.udpEnabled === true) { if (!udp.server) udp.start(settings.udpPort); } else if (settings.udpEnabled === false) { if (udp.server) udp.stop(); } if (newSettings.order !== undefined) { doRestartPanel = true } if (newSettings.detectIdleTimeEnabled === true || newSettings.detectIdleTimeEnabled === false) { rebuildTray = true } if (newSettings.windowsStyle !== undefined) { if (newSettings.windowsStyle === "win11") { settings.isWin11 = true } else if (newSettings.windowsStyle === "win10") { settings.isWin11 = false } else { settings.isWin11 = isReallyWin11 } newSettings.useAcrylic = settings.useAcrylic sendToAllWindows('theme-settings', lastTheme) doRestartPanel = true } if (newSettings.useAcrylic !== undefined) { lastTheme["UseAcrylic"] = newSettings.useAcrylic sendToAllWindows('theme-settings', lastTheme) if(newSettings.useAcrylic) { currentWallpaperTime = false sendMicaWallpaper() } doRestartPanel = true } if (newSettings.icon !== undefined) { if (tray) { tray.setImage(getTrayIconPath()) } } if (newSettings.checkForUpdates !== undefined) { if (newSettings.checkForUpdates === false) { latestVersion = false sendToAllWindows('latest-version', latestVersion); } else { lastCheck = false } } if (newSettings.isDev === true || newSettings.isDev === false) { rebuildTray = true } if (settings.profiles) { rebuildTray = true if(settings.profiles?.length > 0) { if(!focusTrackingID) startFocusTracking(); } else if(focusTrackingID) { stopFocusTracking() } } if (newSettings.branch) { lastCheck = false settings.dismissedUpdate = false checkForUpdates() } if (settings.analytics) { pingAnalytics() if (analyticsInterval) { clearInterval(analyticsInterval) } analyticsInterval = setInterval(pingAnalytics, analyticsFrequency) } else { analytics = false if (analyticsInterval) { clearInterval(analyticsInterval) } } if (rebuildTray) { setTrayMenu() } if (mainWindow && doRestartPanel) { restartPanel() } } catch (e) { console.log("Couldn't process settings!", e) } if(monitorsThreadReady) { monitorsThread.send({ type: "settings", settings: settings }) monitorsThread.send({ type: "ddcBrightnessVCPs", ddcBrightnessVCPs: getDDCBrightnessVCPs() }) } if (sendUpdate) sendToAllWindows('settings-updated', settings); if (shouldRefreshMonitors) { refreshMonitors(true, true) } } // Check if given display should be skipped during brightness update const displaysMayBeIdleBlocks = [] function blockBadDisplays(tag = "") { const blockUUID = uuid() displaysMayBeIdleBlocks.push(blockUUID) const release = () => { const found = displaysMayBeIdleBlocks.indexOf(blockUUID) if(found >= 0) { displaysMayBeIdleBlocks.splice(found, 1) console.log(`\x1b[36mReleased block: ${blockUUID} ${tag} [${displaysMayBeIdleBlocks.length} left]\x1b[0m`) return true } console.log(`\x1b[36mFailed to release block: ${blockUUID} ${tag}\x1b[0m`) return false } console.log(`\x1b[36mStarted block: ${blockUUID} ${tag}\x1b[0m`) return { uuid: blockUUID, release: async () => { await Utils.wait(800) return release() } } } function shouldSkipDisplay(monitorOrHwid1, skipEventCheck = false) { if(!displaysMayBeIdleBlocks.length && !skipEventCheck) return false; const hwid1 = (typeof monitorOrHwid1 === "string" ? monitorOrHwid1 : monitorOrHwid1?.hwid?.[1]) let rules = [] rules = rules.concat(monitorRules.skipReapply) try { rules = rules.concat(settings.userSkipReapply) } catch(e) { console.log("Error merging userSkipReapply:", e) } const inRules = rules.includes(hwid1) return inRules } // Save all known displays to disk for future use async function updateKnownDisplays(force = false, immediate = false) { // Skip when idle if (!force && isUserIdle) return false; const doFunc = () => { try { // Get from file let known = getKnownDisplays(true) // Save to memory lastKnownDisplays = known // Write back to file fs.writeFileSync(knownDisplaysPath, JSON.stringify(known)) console.log(`\x1b[36mSaved known displays!\x1b[0m`) } catch (e) { console.error("Couldn't update known displays file.") } } // Reset timeout if (updateKnownDisplaysTimeout) clearTimeout(updateKnownDisplaysTimeout); if (immediate) { doFunc() } else { // Wait a moment updateKnownDisplaysTimeout = setTimeout(doFunc, 3000) } } // Get known displays from file, along with current displays function getKnownDisplays(useCurrentMonitors) { let known if (!lastKnownDisplays) { try { // Load known displays DB known = fs.readFileSync(knownDisplaysPath) known = JSON.parse(known) lastKnownDisplays = known } catch (e) { known = {} } } else { known = lastKnownDisplays } // Merge with existing displays if (useCurrentMonitors) { known = Object.assign(known, JSON.parse(JSON.stringify(monitors))) } return known } // Look up all known displays and re-apply last brightness function setKnownBrightness(useCurrentMonitors = false, useTransition = false, transitionSpeed = 1) { console.log(`\x1b[36mSetting brightness for known displays\x1b[0m`, useCurrentMonitors, useTransition, transitionSpeed) const known = getKnownDisplays(useCurrentMonitors) applyProfile(known, useTransition, transitionSpeed) } function applyProfile(profile = {}, useTransition = false, transitionSpeed = 1, skipBadDisplays = false) { applyOrder(profile) applyRemaps(profile) if (useTransition) { // If using smooth transition let transitionMonitors = [] for (const hwid in profile) { try { const monitor = profile[hwid] if(shouldSkipDisplay(monitor)) continue; transitionMonitors[monitor.id] = monitor.brightness } catch (e) { console.log("Couldn't set brightness for known display!") } } transitionBrightness(50, transitionMonitors, transitionSpeed) } else { // If not using a transition for (const hwid in profile) { try { const monitor = profile[hwid] if(shouldSkipDisplay(monitor)) continue; // Apply brightness to valid display types if (monitor.type == "wmi" || monitor.type == "studio-display" || (monitor.type == "ddcci" && monitor.brightnessType)) { // Replace DDC/CI brightness with SDR if(settings.sdrAsMainSliderDisplays?.[monitor.key] && monitor.hdr === "active") { monitor.brightness = monitor.sdrLevel } updateBrightness(monitor.id, monitor.brightness) } } catch (e) { console.log("Couldn't set brightness for known display!") } } } sendToAllWindows('monitors-updated', monitors); } function applyHotkeys(monitorList = monitors) { try { if (settings.hotkeys !== undefined && settings.hotkeys?.length) { globalShortcut.unregisterAll() for (const hotkey of settings.hotkeys) { try { // Only apply if found/valid if (hotkey.accelerator) { hotkey.active = globalShortcut.register(hotkey.accelerator, () => { doHotkey(hotkey) }) } } catch (e) { // Couldn't register hotkey } } } } catch(e) { console.log("Couldn't apply hotkeys:", e) } sendToAllWindows('settings-updated', settings) } let hotkeyOverlayTimeout let hotkeyThrottle = [] let doingHotkey = false const hotkeyCycleIndexes = [] async function doHotkey(hotkey) { const now = Date.now() if (!doingHotkey && (hotkeyThrottle[hotkey.id] === undefined || now > hotkeyThrottle[hotkey.id] + 100)) { if (!hotkey.actions?.length) return false; hotkeyThrottle[hotkey.id] = now let showOverlay = false doingHotkey = true setRecentlyInteracted(true) // First let's figure out where we're at in the cycle, if applicable let hasCheckedFirstCycleAction = false for (const action of hotkey.actions) { try { // Wait for refresh if user hasn't done so recently if (action.type !== "refresh" && lastRefreshMonitors < Date.now() - 10000) { await refreshMonitors() } if (action.type === "off") { showOverlay = false sleepDisplays(settings.sleepAction, 500) } else if (action.type === "refresh") { showOverlay = false await refreshMonitors(true, true) } else if (action.type === "set" || action.type === "offset" || action.type === "cycle") { // Build list of all applicable monitors const hotkeyMonitors = [] // Determine applicable monitors and new values for (const monitor of Object.values(monitors)) { let applicable = false if (action.allMonitors || (settings.linkedLevelsActive && !settings.hotkeysBreakLinkedLevels)) { // Target all monitors applicable = true } else if (Object.keys(action.monitors)?.length && action.monitors[monitor.id]) { // Target specified monitors applicable = true } if (applicable) { // Determine new value newValue = 0 if (action.type === "offset") { let currentValue = 0 if (action.target === "brightness") { currentValue = monitor.brightness } else if (action.target === "sdr") { currentValue = monitor.sdrLevel ?? 0 } else if (action.target === "contrast") { currentValue = await getVCP(monitor, parseInt("0x12")) } else if (action.target === "volume") { currentValue = await getVCP(monitor, parseInt("0x62")) } else if (action.target === "powerState") { currentValue = await getVCP(monitor, parseInt("0xD6")) } else { // Get VCP currentValue = await getVCP(monitor, parseInt(action.target)) } newValue = currentValue + parseInt(action.value); } else if (action.type === "cycle") { if (!action.values?.length) return -1; if (!hotkeyCycleIndexes[hotkey.id]) { hotkeyCycleIndexes[hotkey.id] = 0 } let currentCycleValue = 0 if (action.target === "brightness") { currentCycleValue = monitor.brightness } else if (action.target === "sdr") { currentCycleValue = monitor.sdrLevel ?? 0 } else if (action.target === "contrast") { currentCycleValue = await getVCP(monitor, parseInt("0x12")) } else if (action.target === "volume") { currentCycleValue = await getVCP(monitor, parseInt("0x62")) } else if (action.target === "powerState") { currentCycleValue = await getVCP(monitor, parseInt("0xD6")) } else { // Get VCP currentCycleValue = await getVCP(monitor, parseInt(action.target)) } // Update cycle if it's the first "cycle" action if (!hasCheckedFirstCycleAction) { hasCheckedFirstCycleAction = true // If current value is same as measured, move onto next value. Else reset. if (true || currentCycleValue == parseInt(action.values[hotkeyCycleIndexes[hotkey.id]])) { if (hotkeyCycleIndexes[hotkey.id] >= action.values.length - 1) { // End of list, reset hotkeyCycleIndexes[hotkey.id] = 0 } else { // Next value hotkeyCycleIndexes[hotkey.id]++ } } else { // Reset hotkeyCycleIndexes[hotkey.id] = 0 } } newValue = action.values[hotkeyCycleIndexes[hotkey.id]]; } else if (action.type === "set") { newValue = parseInt(action.value); } hotkeyMonitors.push({ monitor, value: newValue }) } } // Apply change if (hotkeyMonitors?.length) { for (const hotkeyMonitor of hotkeyMonitors) { const { monitor, value } = hotkeyMonitor if (action.target === "brightness") { const normalizedAdjust = minMax(value) monitors[monitor.key].brightness = normalizedAdjust sendToAllWindows('monitors-updated', monitors); updateBrightnessThrottle(monitor.id, monitors[monitor.key].brightness, true, false) pauseMonitorUpdates() // Stop incoming updates for a moment to prevent judder // Break linked levels if (settings.hotkeysBreakLinkedLevels && settings.linkedLevelsActive) { console.log("Breaking linked levels due to hotkey.") writeSettings({ linkedLevelsActive: false }) } showOverlay = true } else if(action.target === "sdr") { updateBrightnessThrottle(monitor.id, parseInt(value), false, true, "sdr") } else { let vcpCode = action.target if (action.target === "contrast") { vcpCode = "0x12" } else if (action.target === "volume") { vcpCode = "0x62" } else if (action.target === "powerState") { vcpCode = "0xD2" } updateBrightnessThrottle(monitor.id, parseInt(value), false, true, parseInt(vcpCode)) sendToAllWindows('monitors-updated', monitors); } } } } // Show brightness overlay, if applicable // If panel isn't open, use the overlay if (showOverlay && panelState !== "visible") { hotkeyOverlayStart(undefined, true) } } catch (e) { console.log("HOTKEY ERROR:", e) } } doingHotkey = false } } function hotkeyOverlayStart(timeout = 3000, force = true) { if (currentOverlayType() === "disabled") return false; if (canReposition) { hotkeyOverlayShow() } // Resume mouse events if disabled pauseMouseEvents(false) if (hotkeyOverlayTimeout) clearTimeout(hotkeyOverlayTimeout); hotkeyOverlayTimeout = setTimeout(() => hotkeyOverlayHide(force), timeout) } async function hotkeyOverlayShow() { if (currentOverlayType() === "disabled") return false; if (!mainWindow) return false; if (startHideTimeout) clearTimeout(startHideTimeout); startHideTimeout = null; mainWindow.showInactive() setAlwaysOnTop(true) sendToAllWindows("display-mode", "overlay") panelState = "overlay" let monitorCount = 0 Object.values(monitors).forEach((monitor) => { if ((monitor.type === "ddcci" || monitor.type === "studio-display" || monitor.type === "wmi") && (settings?.hideDisplays?.[monitor.key] !== true)) monitorCount++; }) if (monitorCount && settings.linkedLevelsActive) { monitorCount = 1 } canReposition = false if (settings.useAcrylic) { tryVibrancy(mainWindow, { theme: "#26262601", effect: "blur" }) } await toggleTray(true, true) if (settings?.isWin11) { const panelHeight = 14 + 36 + (28 * monitorCount) const panelWidth = 216 const primaryDisplay = screen.getPrimaryDisplay() // Only add gap if the taskbar is actually hidden (not taking up space). // This handles per-monitor auto-hide mods (e.g., Windhawk) where the global // auto-hide registry setting doesn't reflect the actual state on each monitor. const taskbarActuallyHidden = primaryDisplay.bounds.height === primaryDisplay.workArea.height let gap = 0 if(taskbarActuallyHidden && detectedTaskbarHide) { gap = detectedTaskbarHeight } if (typeof settings.overrideTaskbarGap === "number") { gap = settings.overrideTaskbarGap } const bounds = { width: panelWidth, height: panelHeight, x: parseInt((primaryDisplay.workArea.width - panelWidth) / 2), y: parseInt(primaryDisplay.workArea.height - panelHeight - gap) } mainWindow.setBounds(bounds) } else { // Win10 style const panelOffset = 40 mainWindow.setBounds({ width: 26 + (40 * monitorCount), height: 138, x: panelOffset + 10 + (panelSize.taskbar.position === "LEFT" ? panelSize.taskbar.gap : 0), y: panelOffset + 20 }) } // Dumb stuff to prevent UI flicker setTimeout(() => { sendToAllWindows("display-mode", "overlay") setTimeout(() => { mainWindow.setOpacity(1) }, 33) }, 66) } function hotkeyOverlayHide(force = true) { if (!mainWindow) { hotkeyOverlayStart(333) return false } if (!force && mainWindow && mainWindow.isFocused()) { hotkeyOverlayStart(333) return false; } clearTimeout(hotkeyOverlayTimeout) setAlwaysOnTop(false) canReposition = true if (!mainWindow.webContents.isDevToolsOpened()) { sendToAllWindows("panelBlur") showPanel(false) sendToAllWindows("display-mode", "normal") } hotkeyOverlayTimeout = false // Pause mouse events if scroll shortcut is not enabled pauseMouseEvents(true) mainWindow.setSize(0, 0) if (!settings.useAcrylic || !settings.useNativeAnimation) { tryVibrancy(mainWindow, false) } } function applyOrder(monitorList = monitors) { for (let key in monitorList) { const monitor = monitorList[key] for (let order of settings.order) { if (monitor.id == order.id) { monitor.order = order.order } } } } function applyRemaps(monitorList = monitors) { for (let key in monitorList) { const monitor = monitorList[key] applyRemap(monitor) } } function applyRemap(monitor) { if (settings.remaps) { for (let remapName in settings.remaps) { if (remapName == monitor.name || remapName == monitor.id) { let remap = settings.remaps[remapName] monitor.min = remap.min monitor.max = remap.max monitor.calibration = remap.calibration // Stop if using new scheme if (remapName == monitor.id) return monitor; } } } return monitor } function minMax(value, min = 0, max = 100) { let out = value if (value < min) out = min; if (value > max) out = max; return out; } function determineTheme(themeName) { theme = themeName.toLowerCase() if (theme === "dark" || theme === "light") return theme; if (lastTheme && lastTheme.SystemUsesLightTheme) { return "light" } else { return "dark" } } function enableStartup(appName, appPath) { const runKey = reg.openKey(reg.HKCU, 'Software\\Microsoft\\Windows\\CurrentVersion\\Run', reg.Access.ALL_ACCESS); reg.setValueSZ(runKey, appName, `"${appPath}"`); } function disableStartup(appName) { const runKey = reg.openKey(reg.HKCU, 'Software\\Microsoft\\Windows\\CurrentVersion\\Run', reg.Access.ALL_ACCESS); reg.deleteValue(runKey, appName); const approvedKey = reg.openKey(reg.HKCU, 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartupApproved\\Run', reg.Access.ALL_ACCESS); reg.deleteValue(approvedKey, appName); } async function updateStartupOption(openAtLogin) { if (!isDev && !isAppX) { /* app.setLoginItemSettings({ openAtLogin, path: `"${app.getPath('exe')}"`, }) */ if(openAtLogin) { enableStartup('electron.app.Twinkle Tray', app.getPath('exe')) } else { disableStartup('electron.app.Twinkle Tray') } } // Set autolaunch for AppX try { if (isAppX) { if (openAtLogin) { AppStartup.enable() } else { AppStartup.disable() } } } catch (e) { debug.error(e) } } // // // Localization // // const localization = { detected: "en", default: {}, desired: {}, all: [], languages: [] } let T = new Translate(localization.desired, localization.default) function getLocalization() { // Detect language let detected = app.getLocale() if (detected === "zh-CN") { detected = "zh_Hans" } else if (detected === "zh-TW" || detected === "zh-HK" || detected === "zh-MO") { detected = "zh-Hant" } else if (detected?.split("-")[0] === "pt") { detected = app.getLocale() } else { detected = detected?.split("-")[0] } // Use detected if user has not selected one localization.detected = (settings.language == "system" ? detected : settings.language) // Get default localization file try { const defaultFile = fs.readFileSync(path.join(__dirname, `/localization/en.json`)) localization.default = JSON.parse(defaultFile) } catch (e) { console.error("Couldn't read default langauge file!") } // Get user's local localization file, if available localization.desired = {} const langPath = path.join(__dirname, `/localization/${localization.detected}.json`) if (fs.existsSync(langPath)) { try { const desiredFile = fs.readFileSync(langPath) localization.desired = JSON.parse(desiredFile) } catch (e) { console.error(`Couldn't read language file: ${localization.detected}.json`) } } T = new Translate(localization.desired, localization.default) sendToAllWindows("localization-updated", localization) if(monitorsThreadReady) { monitorsThread.send({ type: "localization", localization: { GENERIC_DISPLAY_SINGLE: T.getString("GENERIC_DISPLAY_SINGLE") } }) } } async function getAllLanguages() { return new Promise((resolve, reject) => { fs.readdir(path.join(__dirname, `/localization/`), (err, files) => { if (!err) { let languages = [] for (let file of files) { try { const langText = fs.readFileSync(path.join(__dirname, `/localization/`, file)) const langName = JSON.parse(langText)["LANGUAGE"] if (!langName || langName.length === 0) { throw ("Invalid language.") } languages.push({ id: file.split(".")[0], name: langName }) } catch (e) { console.error(`Error reading language from ${file}`) } } localization.languages = languages sendToAllWindows("localization-updated", localization) resolve(languages) } else { reject() } }) }) } ipcMain.on('request-localization', () => { sendToAllWindows("localization-updated", localization) }) function getSettings() { processSettings({}) sendToAllWindows('settings-updated', settings) } function getDDCBrightnessVCPs() { try { // Create a new object to avoid mutating knownDDCBrightnessVCPs let ids = Object.assign({}, knownDDCBrightnessVCPs, settings.userDDCBrightnessVCPs) for (let mon in ids) { ids[mon] = parseInt(ids[mon]) } return ids } catch (e) { console.log("Couldn't generate DDC Brightness IDs!", e) return {} } } function sendToAllWindows(eventName, data) { if (mainWindow) { mainWindow.webContents.send(eventName, data) } if (settingsWindow) { settingsWindow.webContents.send(eventName, data) } if (introWindow) { introWindow.webContents.send(eventName, data) } } ipcMain.on('send-settings', (event, data) => { console.log("Recieved new settings", data.newSettings) writeSettings(data.newSettings, true, data.sendUpdate) }) ipcMain.on('request-settings', (event) => { getSettings() getThemeRegistry() // Technically, it doesn't belong here, but it's a good place to piggy-back off of }) ipcMain.on('reset-settings', () => { settings = Object.assign({}, defaultSettings) console.log("Resetting settings") lastKnownDisplays = {} fs.writeFileSync(knownDisplaysPath, JSON.stringify(lastKnownDisplays)) writeSettings({ userClosedIntro: true }) }) ipcMain.on('open-settings-file', () => { console.log("Opening settings file in default editor") exec(`notepad.exe "${settingsPath}"`) }) // Get the user's Windows Personalization settings async function getThemeRegistry() { console.log("Function: getThemeRegistry"); if (lastTheme) sendToAllWindows('theme-settings', lastTheme) const themeSettings = {}; try { const key = reg.openKey(reg.HKCU, 'Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize', reg.Access.ALL_ACCESS); themeSettings.AppsUseLightTheme = reg.getValue(key, null, 'AppsUseLightTheme'); themeSettings.EnableTransparency = reg.getValue(key, null, 'EnableTransparency'); themeSettings.SystemUsesLightTheme = reg.getValue(key, null, 'SystemUsesLightTheme'); themeSettings.ColorPrevalence = reg.getValue(key, null, 'ColorPrevalence'); } catch (e) { console.log("Couldn't access theme registry", e) } themeSettings.UseAcrylic = settings.useAcrylic if (themeSettings.ColorPrevalence) { if (settings.theme == "dark" || settings.theme == "light") { themeSettings.ColorPrevalence = false } } // Send it off! sendToAllWindows('theme-settings', themeSettings) lastTheme = themeSettings if (tray) { tray.setImage(getTrayIconPath()) } // Taskbar position // For use only if auto-hide is on try { const key = reg.openKey(reg.HKCU, 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StuckRects3', reg.Access.ALL_ACCESS); const Settings = reg.getValue(key, null, 'Settings'); taskbarPos = Settings[12] * 1 detectedTaskbarHeight = Settings[20] * 1 detectedTaskbarHide = (parseInt(Settings[8]) & 1 ? true : false) // 3 = auto-hide if (taskbarPos !== null || settings.useTaskbarRegistry) { switch (taskbarPos) { case 0: detectedTaskbarPos = "LEFT"; break; case 1: detectedTaskbarPos = "TOP"; break; case 2: detectedTaskbarPos = "RIGHT"; break; case 3: detectedTaskbarPos = "BOTTOM"; break; } } } catch (e) { console.log("Couldn't access taskbar registry", e) } return true } function getTrayIconPath() { const themeDir = (lastTheme && lastTheme.SystemUsesLightTheme ? 'light' : 'dark') let icon = "icon"; if (settings.icon === "mdl2" || settings.icon === "fluent") { icon = settings.icon } return path.join(__dirname, `assets/tray-icons/${themeDir}/${icon}.ico`) } function getAccentColors() { let detectedAccent = "0078d7" const colors = AccentColors.getAccentColors() try { if (systemPreferences.getAccentColor().length == 8) detectedAccent = systemPreferences.getAccentColor().substr(0, 6) } catch (e) { console.log("Couldn't get accent color from registry!") } const accent = Color("#" + detectedAccent, "hex") const matchLumi = (color, level) => { let adjusted = color.hsl() adjusted.color[2] = (level * 100) return adjusted } let adjustedAccent = accent if (accent.hsl().color[2] > 60) adjustedAccent = matchLumi(accent, 0.6); if (accent.hsl().color[2] < 40) adjustedAccent = matchLumi(accent, 0.4); // Start w/ old format let outColors = { accent: adjustedAccent.hex(), lighter: matchLumi(accent, 0.85).hex(), light: matchLumi(accent, 0.52).hex(), medium: matchLumi(accent, 0.48).hex(), mediumDark: matchLumi(accent, 0.33).desaturate(0.1).hex(), dark: matchLumi(accent, 0.275).desaturate(0.1).hex(), transparent: matchLumi(accent, 0.275).desaturate(0.1).rgb().string(), } // Merge in new format outColors = Object.assign(outColors, colors) return outColors } function tryVibrancy(window, value = null) { if (!window) return false; try { if (!settings.useAcrylic || settings.isWin11 || value === false) { window.setBackgroundColor("#00000000") Acrylic.disableAcrylic(window.getNativeWindowHandle().readInt32LE(0)) return false } const color = Color((typeof value === "string" ? value : value.theme)) Acrylic.setAcrylic(window.getNativeWindowHandle().readInt32LE(0), 1, color.red(), color.green(), color.blue(), parseInt(color.alpha() * 255)) } catch (e) { console.log("Couldn't set vibrancy", e) } } // // // Monitor updates // // let isRefreshing = true let shouldShowPanel = false const setIsRefreshing = newValue => { isRefreshing = (newValue ? true : false) sendToAllWindows("isRefreshing", isRefreshing) } refreshMonitorsJob = async (fullRefresh = false) => { return await new Promise((resolve, reject) => { try { monitorsThread.send({ type: "refreshMonitors", fullRefresh }) let timeout = setTimeout(() => { reject("Monitor thread timed out.") // Attempt to fix common issue with wmi-bridge by relying only on Win32 // However, if user re-enables WMI, don't disable it again if (!settings.autoDisabledWMI && !recentlyWokeUp) { settings.autoDisabledWMI = true settings.disableWMI = true } }, 60000) function listen(resolve) { monitorsThread.once("refreshMonitors", data => { clearTimeout(timeout) resolve(data.monitors) }) } listen(resolve) } catch (e) { reject("Monitor thread failed to send.") } }) } let lastRefreshMonitors = 0 async function refreshMonitors(fullRefresh = false, bypassRateLimit = false) { if (isWindowsUserIdle) { console.log("Displays are off, no updates.") return monitors } if (!monitorsThreadReady || pausedMonitorUpdates) { console.log("Sorry, no updates right now!") return monitors } // Don't do 2+ refreshes at once if (isRefreshing) { console.log(`Already refreshing. Aborting.`) return monitors; } lastRefreshMonitors = Date.now() console.log(" ") console.log("\x1b[34m-------------- Refresh Monitors -------------- \x1b[0m") // Don't check too often for no reason const now = Date.now() if (!fullRefresh && !bypassRateLimit && now < lastEagerUpdate + 5000) { console.log(`Requesting update too soon. ${5000 - (now - lastEagerUpdate)}ms left.`) console.log("\x1b[34m---------------------------------------------- \x1b[0m") return monitors; } setIsRefreshing(true) // Reset all known displays if (fullRefresh) { console.log("Doing full refresh.") } // Save old monitors for comparison let oldMonitors = Object.assign({}, monitors) let newMonitors let failed = false try { newMonitors = await refreshMonitorsJob(fullRefresh) if (!newMonitors) { failed = true; throw "No monitors recieved!"; } lastEagerUpdate = Date.now() } catch (e) { console.log('Couldn\'t refresh monitors', e) } if (!failed) { applyOrder(newMonitors) applyRemaps(newMonitors) applyHotkeys(newMonitors) // Normalize values for (let id in newMonitors) { const monitor = newMonitors[id] // Brightness monitor.brightness = normalizeBrightness(monitor.brightness, true, monitor.min, monitor.max, monitor.calibration) // Replace DDC/CI brightness with SDR if(settings.sdrAsMainSliderDisplays?.[monitor.key] && monitor.hdr === "active") { monitor.brightness = monitor.sdrLevel } // Other DDC/CI normalizations const featuresSettings = settings.monitorFeaturesSettings?.[monitor.hwid[1]] if(featuresSettings) { // For each feature, check for matching normalization data for(const vcp in monitor.features) { if(featuresSettings[vcp] && featuresSettings[vcp].min >= 0 && featuresSettings[vcp].max <= 100) { monitor.features[vcp][0] = normalizeBrightness(monitor.features[vcp][0], true, featuresSettings[vcp].min, featuresSettings[vcp].max) } } } } monitors = newMonitors; // Only send update if something changed if (JSON.stringify(newMonitors) !== JSON.stringify(oldMonitors)) { setTrayPercent() sendToAllWindows('monitors-updated', monitors) } else { console.log("===--- NO CHANGE ---===") } } if (shouldShowPanel) { shouldShowPanel = false setTimeout(() => toggleTray(true), 333) } console.log("\x1b[34m---------------------------------------------- \x1b[0m") setIsRefreshing(false) return monitors; } let pausedMonitorUpdates = false function pauseMonitorUpdates() { if (pausedMonitorUpdates) clearTimeout(pausedMonitorUpdates); pausedMonitorUpdates = setTimeout(() => pausedMonitorUpdates = false, settings.updateInterval * 2) } // // // Brightness (and VCP) updates // // let updateBrightnessTimeout = false let updateBrightnessQueue = [] let lastBrightnessTimes = [] function updateBrightnessThrottle(id, level, useCap = true, sendUpdate = true, vcp = "brightness") { let idx = updateBrightnessQueue.length const found = updateBrightnessQueue.findIndex(item => item.id === id) updateBrightnessQueue[(found > -1 ? found : idx)] = { id, level, useCap, vcp } const now = Date.now() if (lastBrightnessTimes[id] === undefined || now >= lastBrightnessTimes[id] + settings.updateInterval) { lastBrightnessTimes[id] = now updateBrightness(id, level, useCap, vcp) if (sendUpdate) sendToAllWindows('monitors-updated', monitors); return true } else if (!updateBrightnessTimeout) { lastBrightnessTimes[id] = now updateBrightnessTimeout = setTimeout(() => { const updateBrightnessQueueCopy = updateBrightnessQueue.splice(0) for (let bUpdate of updateBrightnessQueueCopy) { if (bUpdate) { try { updateBrightness(bUpdate.id, bUpdate.level, bUpdate.useCap, bUpdate.vcp) } catch (e) { console.error(e) } } } updateBrightnessTimeout = false if (sendUpdate) sendToAllWindows('monitors-updated', monitors); }, settings.updateInterval) } return false } let ignoreBrightnessEvent = false let ignoreBrightnessEventTimeout = false function updateBrightness(index, newLevel, useCap = true, vcpValue = "brightness", clearTransition = true) { if(isWindowsUserIdle) return false; // Skip if displays are off try { let level = newLevel let vcp = "brightness" switch(vcpValue) { case "brightness": vcp = "brightness"; break; case "sdr": vcp = "sdr"; break; default: vcp = `0x${parseInt(vcpValue).toString(16)}`; } let monitor = false if (typeof index == "string" && index * 1 != index) { monitor = Object.values(monitors).find((display) => { return display?.id?.indexOf(index) === 0 }) } else { if (index >= Object.keys(monitors).length) { console.log("updateBrightness: Invalid monitor") return false; } monitor = monitors[index] } if (!monitor) { console.log(`Monitor does not exist: ${index}`) return false } if (settings.hideDisplays?.[monitor.key] === true) { return false } if(vcp == "brightness" && monitor.hdr === "active" && settings.sdrAsMainSliderDisplays?.[monitor.key]) { vcp = "sdr" useCap = false } if (clearTransition && currentTransition) { clearInterval(currentTransition) currentTransition = null } if(shouldSkipDisplay(monitor)) { console.log(`\x1b[31mSkipping monitor ${monitor.id} due to rules list\x1b[0m`) return false } const normalized = normalizeBrightness(level, false, (useCap ? monitor.min : 0), (useCap ? monitor.max : 100), (useCap ? monitor.calibration : [])) if (vcp === "sdr") { monitorsThread.send({ type: "sdr", brightness: level, id: monitor.id }) monitor.sdrLevel = level if(settings.sdrAsMainSliderDisplays?.[monitor.key]) { monitor.brightness = level monitor.brightnessRaw = normalized } } else if (monitor.type == "ddcci") { if (vcp === "brightness") { monitor.brightness = level monitor.brightnessRaw = normalized monitorsThread.send({ type: "brightness", brightness: normalized * ((monitor.brightnessMax || 100) / 100), id: monitor.id }) // Replace DDC/CI brightness with SDR if(settings.sdrAsMainSliderDisplays?.[monitor.key] && monitor.hdr === "active") { monitor.brightness = monitor.sdrLevel } // Apply linked DDC/CI features const featuresSettings = settings.monitorFeaturesSettings?.[monitor.hwid[1]] if(featuresSettings) { // For each feature, check for linked value for(const vcp in monitor.features) { if(featuresSettings[vcp]?.linked && settings.monitorFeatures?.[monitor.hwid[1]]?.[vcp]) { const maxBrightness = (featuresSettings[vcp].maxVisual ?? 100) let processedLevel = newLevel if(processedLevel > maxBrightness) { processedLevel = maxBrightness } const capped = parseInt(normalizeBrightness(processedLevel, true, 0, maxBrightness)) updateBrightnessThrottle(index, capped, useCap, false, vcp) } } } } else { const vcpString = `0x${parseInt(vcp).toString(16).toUpperCase()}` try { // Normalize VCP value, if applicable const featuresSettings = settings.monitorFeaturesSettings?.[monitor.hwid[1]] if(featuresSettings?.[vcp] && featuresSettings[vcp].min >= 0 && featuresSettings[vcp].max <= 100) { level = normalizeBrightness(level, false, featuresSettings[vcp].min, featuresSettings[vcp].max) } if(monitor.features?.[vcpString]) { monitor.features[vcpString][0] = parseInt(level) } monitorsThread.send({ type: "vcp", monitor: monitor.hwid.join("#"), code: parseInt(vcp), value: parseInt(level) }) console.log('monitors-updated', monitor.features?.[vcpString]) } catch(e) { console.log(`Couldn't set VCP code ${vcpString} for monitor ${monitor.id}`, e) } } } else if (monitor.type === "studio-display") { monitor.brightness = level monitor.brightnessRaw = normalized monitorsThread.send({ type: "brightness", brightness: normalized * ((monitor.brightnessMax || 100) / 100), id: monitor.id }) } else if (monitor.type == "wmi") { ignoreBrightnessEvent = true // Don't listen for Windows brightness events monitor.brightness = level monitor.brightnessRaw = normalized monitorsThread.send({ type: "brightness", brightness: normalized }) if(ignoreBrightnessEventTimeout) clearTimeout(ignoreBrightnessEventTimeout); ignoreBrightnessEventTimeout = setTimeout(() => { ignoreBrightnessEvent = false ignoreBrightnessEventTimeout = false }, 500) } setTrayPercent() updateKnownDisplays() } catch (e) { debug.error("Could not update brightness", e) } } function updateAllBrightness(brightness, mode = "offset") { let linkedLevelVal // Update internal brightness values for (let key in monitors) { const monitor = monitors[key] if (monitor.type !== "none") { // Replace DDC/CI brightness with SDR if(settings.sdrAsMainSliderDisplays?.[monitor.key] && monitor.hdr === "active") { monitor.brightness = monitor.sdrLevel } let normalizedAdjust = minMax(mode == "set" ? brightness : brightness + monitor.brightness) // Use linked levels, if applicable if (settings.linkedLevelsActive) { // Set shared brightness value if not set if (linkedLevelVal) { normalizedAdjust = linkedLevelVal } else { linkedLevelVal = normalizedAdjust } } monitors[key].brightness = normalizedAdjust if(settings.sdrAsMainSliderDisplays?.[monitor.key]) monitors[key].sdrLevel = normalizedAdjust; } } // Update UI sendToAllWindows('monitors-updated', monitors); // Send brightness updates for (let key in monitors) { updateBrightnessThrottle(monitors[key].id, monitors[key].brightness, true, false) } } function normalizeBrightness(brightness, normalize = false, min = 0, max = 100, calibrationPoints = []) { // normalize = true when recieving from Monitors.js // normalize = false when sending to Monitors.js const points = calibrationPoints.slice() if(min > 0) points.push({ input: 0, output: min }) if(max < 100) points.push({ input: 100, output: max }) return Utils.getCalibratedValue(brightness, points, normalize) let level = brightness if (level > 100) level = 100; if (level < 0) level = 0; if (min > 0 || max < 100) { let out = level if (!normalize) { // Normalize out = (min + ((level / 100) * (max - min))) } else { // Unnormalize out = ((level - min) * (100 / (max - min))) } if (out > 100) out = 100; if (out < 0) out = 0; return Math.round(out) } else { return level } } let currentTransition = null function transitionBrightness(level, eventMonitors = [], stepSpeed = 1) { if (currentTransition !== null) clearInterval(currentTransition); // Slow down transition let transitionIntervalMult = 1 switch (settings.adjustmentTimeSpeed) { case "slow": transitionIntervalMult = 4; break; case "slowest": transitionIntervalMult = 10; break; default: transitionIntervalMult = 1; break; } // Speed up transition let stepSpeedMult = 1 switch (settings.adjustmentTimeSpeed) { case "fast": stepSpeedMult = 3; break; case "fastest": stepSpeedMult = 6; break; default: stepSpeedMult = 1; break; } const step = (stepSpeed * stepSpeedMult) currentTransition = setInterval(() => { if (recentlyWokeUp || isWindowsUserIdle) clearInterval(currentTransition); let numDone = 0 for (let key in monitors) { const monitor = monitors[key] let normalized = level * 1 if (settings.adjustmentTimeIndividualDisplays) { // If using individual monitor settings normalized = (eventMonitors[monitor.id] >= 0 ? eventMonitors[monitor.id] : level) } if (settings.remaps) { for (let remapName in settings.remaps) { if (remapName == monitor.name) { normalized = normalized } } } if (monitor.brightness < normalized + (step + 1) && monitor.brightness > normalized - (step + 1)) { updateBrightness(monitor.id, normalized, undefined, undefined, false) numDone++ } else { updateBrightness(monitor.id, (monitor.brightness < normalized ? monitor.brightness + step : monitor.brightness - step), undefined, undefined, false) } sendToAllWindows('monitors-updated', monitors) if (numDone === Object.keys(monitors).length) { clearInterval(currentTransition); currentTransition = null } } }, settings.updateInterval * transitionIntervalMult) } function transitionlessBrightness(level, eventMonitors = []) { for (let key in monitors) { const monitor = monitors[key] let normalized = level if (settings.adjustmentTimeIndividualDisplays) { // If using individual monitor settings normalized = (eventMonitors[monitor.id] >= 0 ? eventMonitors[monitor.id] : level) } updateBrightness(monitor.id, normalized) sendToAllWindows('monitors-updated', monitors) } } // Flag recent user activity to skip certain events let hasRecentlyInteracted = false function setRecentlyInteracted(hasInteracted) { if(hasRecentlyInteracted) clearTimeout(hasRecentlyInteracted); if(!hasInteracted) { hasRecentlyInteracted = false } else { hasRecentlyInteracted = setTimeout(() => { hasRecentlyInteracted = false }, 5000) } } let sleepTimeout function sleepDisplays(mode = "ps", delayMS = 333) { try { if(sleepTimeout) clearTimeout(sleepTimeout); sleepTimeout = setTimeout(async () => { //startIdleCheckShort() if (mode === "ddcci" || mode === "ps_ddcci") { for (let monitorID in monitors) { const monitor = monitors[monitorID] await turnOffDisplayDDC(monitor.hwid.join("#")) } } if (mode === "ps" || mode === "ps_ddcci") { exec(`powershell.exe -NoProfile (Add-Type '[DllImport(\\"user32.dll\\")]^public static extern int PostMessage(int hWnd, int hMsg, int wParam, int lParam);' -Name a -Pas)::PostMessage(0xFFFF,0x0112,0xF170,0x0002)`) } sleepTimeout = false }, delayMS) } catch (e) { console.log(e) } } async function turnOffDisplayDDC(hwid, toggle = false) { try { const offVal = parseInt(settings.ddcPowerOffValue) if (toggle) { const currentValue = await getVCP(hwid, 0xD6) if (currentValue > 1) { monitorsThread.send({ type: "vcp", monitor: hwid, code: 0xD6, value: 1 }) return true } } if (offVal === 4 || offVal === 6) { monitorsThread.send({ type: "vcp", monitor: hwid, code: 0xD6, value: 4 }) } if (offVal === 5 || offVal === 6) { monitorsThread.send({ type: "vcp", monitor: hwid, code: 0xD6, value: 5 }) } } catch (e) { console.log("turnOffDisplayDDC failed", e) } } function readInstanceName(insName) { return insName.replace(/&/g, '&').split("\\") } // // // IPC Events // // ipcMain.on('request-colors', () => { sendToAllWindows('update-colors', getAccentColors()) getThemeRegistry() }) ipcMain.on('update-brightness', function (event, data) { setRecentlyInteracted(true) updateBrightness(data.index, data.level) // If overlay is visible, keep it open if (hotkeyOverlayTimeout) { hotkeyOverlayStart() } }) ipcMain.on('request-monitors', function (event, arg) { sendToAllWindows("monitors-updated", monitors) //refreshMonitors(false, true) }) ipcMain.on('full-refresh', function (event, forceUpdate = false) { refreshMonitors(true).then(() => { if (forceUpdate) { sendToAllWindows('monitors-updated', monitors) } }) }) ipcMain.on('flush-vcp-cache', function (event) { monitorsThread.send({ type: "flushvcp" }) }) ipcMain.on('get-refreshing', () => { sendToAllWindows('isRefreshing', isRefreshing) }) ipcMain.on('open-settings', createSettings) ipcMain.on('log', (e, msg) => console.log(msg)) ipcMain.on('pause-updates', pauseMonitorUpdates) ipcMain.on('open-url', (event, url) => { if (url === "ms-store") { require("electron").shell.openExternal("ms-windows-store://pdp/?productid=9PLJWWSV01LK") } else if (url === "privacy-policy") { require("electron").shell.openExternal("https://twinkletray.com/privacy-policy.html") } else if (url === "troubleshooting-features") { require("electron").shell.openExternal("https://github.com/xanderfrangos/twinkle-tray/wiki/Display-Detection-&-Support-Issues#disabling-monitor-detection-methods-available-in-v1140") } }) ipcMain.on('get-update', (event, version) => { latestVersion.error = false getLatestUpdate(version) }) ipcMain.on('panel-height', (event, height) => { if (panelState === "overlay") return; panelSize.height = height + (settings?.isWin11 ? 24 : 0) panelSize.width = 356 + (settings?.isWin11 ? 24 : 0) if (panelSize.visible && !isAnimatingPanel) { repositionPanel() } }) ipcMain.on('panel-hidden', () => { sendToAllWindows("display-mode", "normal") panelState = "hidden" if (settings.killWhenIdle) mainWindow.close() }) ipcMain.on('blur-panel', () => { if (mainWindow) mainWindow.blur(); }) ipcMain.on('show-acrylic', () => { if (settings.useAcrylic && !settings.useNativeAnimation) { if (lastTheme && lastTheme.ColorPrevalence) { tryVibrancy(mainWindow, { theme: getAccentColors().dark + (settings.useAcrylic ? "D0" : "70"), effect: (settings.useAcrylic ? "acrylic" : "blur") }) } else { tryVibrancy(mainWindow, { theme: (lastTheme && nativeTheme.themeSource === "light" ? (settings.useAcrylic ? "#DBDBDBDD" : "#DBDBDB70") : (settings.useAcrylic ? "#292929DD" : "#29292970")), effect: (settings.useAcrylic ? "acrylic" : "blur") }) } } else { tryVibrancy(mainWindow, false) mainWindow.setBackgroundColor("#00000000") } sendToAllWindows("set-acrylic-show") }) ipcMain.on('apply-last-known-monitors', () => { setKnownBrightness() }) ipcMain.on('sleep-displays', () => sleepDisplays(settings.sleepAction, 1000)) ipcMain.on('sleep-display', (e, hwid) => turnOffDisplayDDC(hwid, true)) ipcMain.on('set-vcp', (e, values) => { setRecentlyInteracted(true) updateBrightnessThrottle(values.monitor, values.value, false, true, values.code) }) ipcMain.on('set-sdr-brightness', (e, values) => { setRecentlyInteracted(true) updateBrightnessThrottle(values.monitor, values.value, false, true, "sdr") }) ipcMain.on('get-window-history', () => sendToAllWindows('window-history', windowHistory)) ipcMain.on('save-report', async () => { try { monitorsThread.send({ type: "getReport" }) monitorsThread.once("getReport", data => { require('electron').dialog.showSaveDialog({ title: "Save report", buttonLabel: 'Save file', defaultPath: app.getPath("desktop") + `\\tt-report-${Date.now()}.txt`, filters: [{ name: ".txt", extensions: ["txt"] }] }).then(result => { if(result?.filePath) { fs.writeFileSync(result.filePath, JSON.stringify(data, null, '\t')) } }) }) } catch (e) { reject("getReport failed to send.") } }) // // // Initialize Panel // // let panelState = "hidden" let panelReady = false function createPanel(toggleOnLoad = false, isRefreshing = false, showOnLoad = true) { console.log("Creating panel...") mainWindow = new BrowserWindow({ width: panelSize.width, height: panelSize.height, x: 0, y: 0, minHeight: 0, minWidth: 0, backgroundColor: "#00000000", frame: false, transparent: true, show: false, alwaysOnTop: false, skipTaskbar: true, resizable: false, type: "toolbar", title: "Twinkle Tray Flyout", maximizable: false, minimizable: false, webPreferences: { preload: path.join(__dirname, 'panel-preload.js'), devTools: settings.isDev, nodeIntegration: true, contextIsolation: false, plugins: false, backgroundThrottling: (settings.disableThrottling ? false : true), spellcheck: false, webgl: false, enableWebSQL: false, v8CacheOptions: "none", zoomFactor: 1.0, additionalArguments: ["jsVars" + Buffer.from(JSON.stringify({ appName: app.name, appVersion: appVersion, appVersionTag: appVersionTag, appBuild: appBuildShort, isRefreshing: isRefreshing })).toString('base64')], allowRunningInsecureContent: true, webSecurity: false } }); mainWindow.loadURL( isDev ? "http://localhost:3000/index.html" : `file://${path.join(__dirname, "../build/index.html")}` ); mainWindow.on("closed", () => { console.log("~~~~~ MAIN WINDOW CLOSED ~~~~~~"); mainWindow = null }); mainWindow.on("minimize", () => { console.log("~~~~~ MAIN WINDOW MINIMIZED ~~~~~~") }); mainWindow.on("restore", () => { console.log("~~~~~ MAIN WINDOW RESTORED ~~~~~~") }); mainWindow.once('ready-to-show', () => { if (mainWindow) { mainWindow.setMenu(windowMenu) panelReady = true console.log("Panel ready!") createTray() if(showOnLoad) showPanel(false); setTimeout(() => { if(!mainWindow) return false; if (!settings.useAcrylic || settings.isWin11) { tryVibrancy(mainWindow, false) mainWindow.setBackgroundColor("#00000000") } }, 100) if (toggleOnLoad) setTimeout(() => { toggleTray(false) }, 33); } }) mainWindow.on("blur", () => { // Only run when not in an overlay if (canReposition) { if (!mainWindow.webContents.isDevToolsOpened()) { sendToAllWindows("panelBlur") showPanel(false) } } }) mainWindow.on('move', (e) => { try { e.preventDefault() sendToAllWindows('panel-position', mainWindow.getPosition()) } catch (e) { } }) mainWindow.on('resize', (e) => { try { e.preventDefault() sendToAllWindows('panel-position', mainWindow.getPosition()) } catch (e) { } }) mainWindow.webContents.once('dom-ready', () => { try { sendToAllWindows('monitors-updated', monitors) // Do full refreshes shortly after startup in case Windows isn't ready. setTimeout(sendMicaWallpaper, 1000) sendToAllWindows('panel-position', mainWindow.getPosition()) } catch (e) { } }) mainWindow.hookWindowMessage(126, (wParam, lParam) => { if(settings.useWmDisplayChangeEvent && !settings.disablePowerNotifications) handleMetricsChange("wm_displaychange") }) // WM_POWERBROADCAST mainWindow.hookWindowMessage(0x218, (wParam, lParam) => { if(settings.disablePowerNotifications) return false; if(wParam.readUInt32LE() !== 32787) return false; // PBT_POWERSETTINGCHANGE const setting = PowerEvents.getPowerSetting(lParam.readBigInt64LE(0)) if(setting.name !== "" || setting.guid) { console.log(`Event: ${setting.name || setting.guid} (${setting.data})`) } if(setting.name === "GUID_SESSION_USER_PRESENCE") { if(!settings.useGuidPresenceEvent) return false; if(setting.data === 2) { // Idle if(!isWindowsUserIdle) { console.log("Displays have gone to sleep.") // If we were about to do a hardware event, stop. if (handleChangeTimeout1) clearTimeout(handleChangeTimeout1); if (handleChangeTimeout2) clearTimeout(handleChangeTimeout2); //if(!isUserIdle) startIdleCheckShort(); } isWindowsUserIdle = true } else if(setting.data === 0) { // Active if(isWindowsUserIdle) { isWindowsUserIdle = false console.log("Displays have woken up.") recentlyWokeUp = true handleMetricsChange("GUID_SESSION_USER_PRESENCE") setTimeout(() => { recentlyWokeUp = false }, 15000 ) } } } else if(setting.name === "GUID_VIDEO_POWERDOWN_TIMEOUT") { // "Turn off my screen after" } else if(setting.name === "GUID_STANDBY_TIMEOUT") { // "Make my device sleep after" } else if(setting.name === "GUID_VIDEO_CURRENT_MONITOR_BRIGHTNESS") { // Internal display brightness change if(!settings.useGuidBrightnessEvent) return false; if(!ignoreBrightnessEvent) { for(const hwid2 in monitors) { const monitor = monitors[hwid2] if(monitor.type === "wmi") { const normalized = normalizeBrightness(setting.data, true, monitor.min, monitor.max, monitor.calibration) monitor.brightness = normalized monitor.brightnessRaw = setting.data } sendToAllWindows('monitors-updated', monitors) } } } }) // WM_SYSCOMMAND mainWindow.hookWindowMessage(0x0112, (wParam, lParam) => { if(!settings.useScMonitorPowerEvent || settings.disablePowerNotifications) return false; if(wParam.readUInt32LE() === 61808) { // SC_MONITORPOWER if(lParam.readUInt32LE() === 2) { // 2 = Display is being shut off console.log("Event: SC_MONITORPOWER") //if(!isUserIdle) startIdleCheckShort(); } } }) if(!settings.disablePowerNotifications) PowerEvents.registerPowerSettingNotifications(getMainWindowHandle()) } function currentOverlayType() { let overlayType = currentProfile?.overlayType if(!overlayType || overlayType == "normal") { overlayType = settings.defaultOverlayType } console.log(`overlayType: ${overlayType}`) return overlayType } function setAlwaysOnTop(onTop = true) { if (!mainWindow) return false; if (onTop) { if(currentOverlayType() === "aggressive") { mainWindow.setAlwaysOnTop(true, 'screen-saver') if(settingsWindow?.isMinimized() === false) { settingsWindow?.minimize() // Workaround for weird bug when settings window is open } } else { mainWindow.setAlwaysOnTop(true, 'modal-panel') } } else { mainWindow.setAlwaysOnTop(false) } return true } function destroyPanel() { if (mainWindow) { mainWindow.destroy() mainWindow = null } } let restartingPanel = false function restartPanel(show = false) { console.log("Function: restartPanel"); if(restartingPanel) { console.log("Function: restartPanel: already restarting") return false } restartingPanel = true if (mainWindow) { mainWindow.setBounds({ x: 0, y: 0, width: 0, height: 0 }) mainWindow.setOpacity(1) //mainWindow.restore() mainWindow.showInactive() } destroyPanel() createPanel(show, false, false) restartingPanel = false } function getPrimaryDisplay() { let displays = screen.getAllDisplays() // Use coordinate (0,0) to choose the primary display. let primaryDisplay = displays.find((display) => { return display.bounds.x == 0 && display.bounds.y == 0 }) // Fall back on previous logic if none is found. if (!primaryDisplay) primaryDisplay = displays.find((display) => { return display.bounds.x == 0 || display.bounds.y == 0 }) if (tray) { try { let trayBounds = tray.getBounds() let foundDisplay = displays.find(d => { return (trayBounds.x >= d.bounds.x && trayBounds.x <= d.bounds.x + d.bounds.width && trayBounds.y >= d.bounds.y && trayBounds.y <= d.bounds.y + d.bounds.height) }) if (foundDisplay) primaryDisplay = foundDisplay; } catch (e) { } } return primaryDisplay } let detectedTaskbarPos = false let detectedTaskbarHeight = false let detectedTaskbarHide = false let canReposition = true function repositionPanel() { try { if (!canReposition) { mainWindow.setBounds({ width: panelSize.width, height: panelSize.height }) return false } let primaryDisplay = getPrimaryDisplay() const taskbarPosition = () => { let primaryDisplay = getPrimaryDisplay() const bounds = primaryDisplay.bounds const workArea = primaryDisplay.workArea let gap = 0 let position = "BOTTOM" if (bounds.x < workArea.x) { position = "LEFT" gap = bounds.width - workArea.width } else if (bounds.y < workArea.y) { position = "TOP" gap = bounds.height - workArea.height } else if (bounds.width > workArea.width) { position = "RIGHT" gap = bounds.width - workArea.width } else { position = "BOTTOM" gap = bounds.height - workArea.height } // Use taskbar position from registry if auto-hide is on if (detectedTaskbarHide) { position = detectedTaskbarPos if (position === "TOP" || position === "BOTTOM") { gap = detectedTaskbarHeight } } if (typeof settings.overrideTaskbarPosition === "string") { const pos = settings.overrideTaskbarPosition.toUpperCase() if (pos === "BOTTOM" || pos === "TOP" || pos === "LEFT" || pos === "RIGHT") { position = pos } } if (typeof settings.overrideTaskbarGap === "number") { gap = settings.overrideTaskbarGap console.log(gap) } return { position, gap } } const taskbar = taskbarPosition() panelSize.taskbar = taskbar sendToAllWindows('taskbar', taskbar) if (mainWindow && !isAnimatingPanel) { // Check if taskbar is actually taking up space on the primary display. // This handles per-monitor auto-hide mods (e.g., Windhawk) where the global // auto-hide registry setting doesn't reflect the actual state on each monitor. const taskbarActuallyHidden = (taskbar.position === "BOTTOM" || taskbar.position === "TOP") ? primaryDisplay.bounds.height === primaryDisplay.workArea.height : primaryDisplay.bounds.width === primaryDisplay.workArea.width if (taskbar.position == "LEFT") { mainWindow.setBounds({ width: panelSize.width, height: panelSize.height, x: primaryDisplay.bounds.x + taskbar.gap, y: primaryDisplay.bounds.y + primaryDisplay.workArea.height - panelSize.height }) } else if (taskbar.position == "TOP") { mainWindow.setBounds({ width: panelSize.width, height: panelSize.height, x: primaryDisplay.bounds.x + primaryDisplay.workArea.width - panelSize.width, y: primaryDisplay.bounds.y + taskbar.gap }) } else if (taskbarActuallyHidden && taskbar.position == "BOTTOM") { // Edge case for auto-hide taskbar (taskbar is truly hidden, not taking up space) mainWindow.setBounds({ width: panelSize.width, height: panelSize.height, x: primaryDisplay.bounds.x + primaryDisplay.workArea.width - panelSize.width, y: primaryDisplay.bounds.y + primaryDisplay.workArea.height - panelSize.height - taskbar.gap }) } else { mainWindow.setBounds({ width: panelSize.width, height: panelSize.height, x: primaryDisplay.bounds.x + primaryDisplay.workArea.width - panelSize.width, y: primaryDisplay.bounds.y + primaryDisplay.bounds.height - panelSize.height - taskbar.gap }) } panelSize.base = mainWindow.getBounds().y } sendToAllWindows('panel-position', mainWindow.getPosition()) } catch (e) { console.log("Couldn't reposition panel", e) } } let forcedFocusID = 0 let currentProfile const ignoreAppList = [ "twinkletray.exe", "explorer.exe", "electron.exe" ] const windowHistory = [] let preProfileBrightness = {} let focusTrackingID = 0 function startFocusTracking() { if(focusTrackingID) return false; // Already tracking focusTrackingID = ActiveWindow.subscribe(async window => { if (!window) return false; if (settings.profiles?.length == 0) return false; const hwnd = WindowUtils.getForegroundWindow() const profile = windowMatchesProfile(window) if (ignoreAppList.includes(path.basename(window.path)) === false) { // Remove from history if exists const isInHistory = windowHistory.find((w, idx) => { if (w.path === window.path) { windowHistory.splice(idx, 1) return true } return false }) // Add current window windowHistory.unshift({ app: window.application, path: window.path }) // Limit history while (windowHistory.length > 8) windowHistory.pop(); sendToAllWindows('window-history', windowHistory) } if (forcedFocusID > 0 && forcedFocusID !== hwnd && hwnd != getMainWindowHandle()) { // This is the overlay // We're going to force focus back to the previous window trySetForegroundWindow(hwnd) } else if (profile?.setBrightness) { // Set brightness, if available // First, save current brightness for later await updateKnownDisplays(true, true) preProfileBrightness = Object.assign({}, lastKnownDisplays) // Then apply user profile brightness applyProfileBrightness(profile) } else if (currentProfile?.setBrightness) { // Last profile had brightness settings // So we should restore the last known brightness applyProfile(preProfileBrightness, false) } currentProfile = profile }) console.log(`Starting focus tracking... (#${focusTrackingID})`) } function stopFocusTracking() { if (focusTrackingID) { console.log("Stopping focus tracking...") ActiveWindow.unsubscribe(focusTrackingID) focusTrackingID = 0 } } function windowMatchesProfile(window) { if (!window) return false; let foundProfile if (settings.profiles?.length && window.path?.length) { for (const profile of settings.profiles) { if(profile.path?.length) { for (const path of profile.path.split(',')) { if (window.path.toLowerCase().indexOf(path.trim().toLowerCase()) > -1) { foundProfile = profile } } } } } if(foundProfile) console.log(`Matched window to profile ${foundProfile.name}`); return foundProfile } function applyProfileBrightness(profile) { try { Object.values(monitors)?.forEach(monitor => { updateBrightness(monitor.id, profile.monitors[monitor.id], true, "brightness") }) sendToAllWindows('monitors-updated', monitors) } catch (e) { console.log("Error applying profile brightness", e) } } function getMainWindowHandle() { try { return mainWindow.getNativeWindowHandle().readInt32LE() } catch (e) { return 0 } } /* Brightness panel animations */ let panelAnimationInterval = false let shouldAnimatePanel = false let isAnimatingPanel = false let panelHeight = 0 let panelMaxHeight = 80 let panelTransitionTime = 0.35 let currentPanelTime = 0 let startPanelTime = process.hrtime.bigint() let lastPanelTime = process.hrtime.bigint() let primaryRefreshRate = 59.97 let primaryDPI = 1 let mainWindowHandle let easeOutQuad = t => 1 + (--t) * t * t * t * t // Set brightness panel state (visible or not) function showPanel(show = true, height = 300) { if (show) { // Show panel if (startHideTimeout) clearTimeout(startHideTimeout); // Reset "hide" timeout startHideTimeout = null mainWindow.restore() mainWindowHandle = mainWindow.getNativeWindowHandle().readInt32LE(0) repositionPanel() panelHeight = height panelSize.visible = true panelSize.bounds = screen.dipToScreenRect(mainWindow, mainWindow.getBounds()) panelSize.bounds = mainWindow.getBounds() primaryDPI = screen.getPrimaryDisplay().scaleFactor panelHeight = panelHeight * primaryDPI if (settings.useNativeAnimation && settings.useAcrylic && lastTheme.EnableTransparency) { // Acrylic + Native Animation if (lastTheme && lastTheme.ColorPrevalence) { tryVibrancy(mainWindow, { theme: getAccentColors().dark + (settings.useAcrylic ? "D0" : "70"), effect: (settings.useAcrylic ? "acrylic" : "blur") }) } else { tryVibrancy(mainWindow, { theme: (lastTheme && lastTheme.SystemUsesLightTheme ? (settings.useAcrylic ? "#DBDBDBDD" : "#DBDBDB70") : (settings.useAcrylic ? "#292929DD" : "#29292970")), effect: (settings.useAcrylic ? "acrylic" : "blur") }) } startPanelAnimation() } else { // No blur, or CSS Animation tryVibrancy(mainWindow, false) mainWindow.setBackgroundColor("#00000000") if (panelSize.taskbar.position === "TOP") { // Top setWindowPos(mainWindowHandle, -2, panelSize.bounds.x * primaryDPI, ((panelSize.base) * primaryDPI), panelSize.bounds.width * primaryDPI, panelHeight, 0x0400) } else { // Bottom, left, right mainWindow.show() mainWindow.setBounds(panelSize.bounds) } } setAlwaysOnTop(true) mainWindow.focus() // Resume mouse events if disabled pauseMouseEvents(false) mainWindow.setOpacity(1) mainWindow.show() sendToAllWindows('panel-position', mainWindow.getPosition()) sendToAllWindows("playPanelAnimation") } else { // Hide panel setAlwaysOnTop(false) panelSize.visible = false clearInterval(panelAnimationInterval) panelAnimationInterval = false shouldAnimatePanel = false isAnimatingPanel = false sendToAllWindows("display-mode", "normal") panelState = "hidden" sendToAllWindows("closePanelAnimation") if (!settings.useAcrylic || !settings.useNativeAnimation) { tryVibrancy(mainWindow, false) } // Pause mouse events pauseMouseEvents(true) if(mainWindow.isVisible) startHidePanel(); } } function trySetForegroundWindow(hwnd) { if (!hwnd) return false; try { console.log("trySetForegroundWindow: " + hwnd) WindowUtils.setForegroundWindow(hwnd) } catch (e) { console.log("Couldn't focus window", e) } } let startHideTimeout function startHidePanel() { if (!startHideTimeout) { startHideTimeout = setTimeout(() => { if (mainWindow) { mainWindow.minimize(); } startHideTimeout = null }, 100) if (mainWindow) mainWindow.setOpacity(0); } } // Begins panel opening animation async function startPanelAnimation() { if (!shouldAnimatePanel) { // Set to animating shouldAnimatePanel = true isAnimatingPanel = true // Reset timing variables startPanelTime = process.hrtime.bigint() currentPanelTime = -1 // Get refresh rate of primary display // This allows the animation to play no more than the refresh rate primaryRefreshRate = await refreshCtx.findVerticalRefreshRateForDisplayPoint(0, 0) // Start animation interval after a short delay // This avoids jank from React updating the DOM if (!panelAnimationInterval) setTimeout(() => { if (!panelAnimationInterval) panelAnimationInterval = setTimeout(doAnimationStep, 1000 / 600) }, 100) } } // Borrowed some of this animation logic from @djsweet function hrtimeDeltaForFrequency(freq) { return BigInt(Math.ceil(1000000000 / freq)); } let busy = false function doAnimationStep() { // If animation has been requested to stop, kill it if (!isAnimatingPanel) { clearInterval(panelAnimationInterval) panelAnimationInterval = false shouldAnimatePanel = false return false } if (currentPanelTime === -1) { startPanelTime = process.hrtime.bigint() currentPanelTime = 0 } // Limit updates to specific interval const now = process.hrtime.bigint() if (!busy && now > lastPanelTime + hrtimeDeltaForFrequency(primaryRefreshRate * (settings.useAcrylic ? 1 : 2) || 59.97)) { lastPanelTime = now currentPanelTime = Number(Number(now - startPanelTime) / 1000000000) // Check if at end of animation if (currentPanelTime >= panelTransitionTime) { // Stop animation isAnimatingPanel = false shouldAnimatePanel = false // Stop at 100% currentPanelTime = panelTransitionTime clearInterval(panelAnimationInterval) panelAnimationInterval = false } // LERP height and opacity let calculatedHeight = panelHeight - (panelMaxHeight * primaryDPI) + Math.round(easeOutQuad(currentPanelTime / panelTransitionTime) * (panelMaxHeight * primaryDPI)) let calculatedOpacity = (Math.round(Math.min(1, currentPanelTime / (panelTransitionTime / 6)) * 100) / 100) // Apply panel size busy = true if (panelSize.taskbar.position === "TOP") { // Top setWindowPos(mainWindowHandle, -2, panelSize.bounds.x * primaryDPI, ((panelSize.base) * primaryDPI), panelSize.bounds.width * primaryDPI, calculatedHeight, 0x0400) } else { // Bottom, left, right setWindowPos(mainWindowHandle, -2, panelSize.bounds.x * primaryDPI, ((panelSize.base) * primaryDPI) + (panelHeight - calculatedHeight), panelSize.bounds.width * primaryDPI, calculatedHeight + (6 * primaryDPI * (settings.useAcrylic ? 0 : 1)), 0x0400) } // Stop opacity updates if at 1 already if (mainWindow.getOpacity() < 1) mainWindow.setOpacity(calculatedOpacity) busy = false } if (isAnimatingPanel) { panelAnimationInterval = setTimeout(doAnimationStep, 1000 / (primaryRefreshRate * (settings.useAcrylic ? 1 : 2) || 59.97)) } else { repositionPanel() } } // Local Parcel server if(isDev) { console.log("Starting Parcel bundler server...") require("./parcelAPI")("dev", 1) } app.on("ready", async () => { await getAllLanguages() await getThemeRegistry() //readSettings() getLocalization() showIntro() createPanel(false, true) await doWMIBridgeTest() startMonitorThread() monitorsThread.once("ready", async () => { monitorsThread.send({ type: "localization", localization: { GENERIC_DISPLAY_SINGLE: T.getString("GENERIC_DISPLAY_SINGLE") } }) isRefreshing = false await refreshMonitors(true, true) if (settings.brightnessAtStartup) setKnownBrightness(); if (settings.checkTimeAtStartup) { lastTimeEvent = false; setTimeout(() => handleBackgroundUpdate(true), 3500) } restartBackgroundUpdate() // Set startup grace period to prevent delayed handlers from overwriting current brightness isStartupGracePeriod = true setTimeout(() => { isStartupGracePeriod = false console.log("Startup grace period ended") }, 30000) // 30 seconds grace period setTimeout(addEventListeners, 5000) }) }) app.on("window-all-closed", () => { //app.quit(); }); app.on("activate", () => { if (mainWindow === null) { //createPanel(true); } }); app.on('quit', () => { try { tray.destroy() } catch (e) { } }) // // // Tray // // function createTray() { if (tray != null) return false; const { Tray } = require('electron') tray = new Tray(getTrayIconPath()) tray.setToolTip('Twinkle Tray' + (isDev ? " (Dev)" : "")) setTrayMenu() tray.on("click", async () => toggleTray(true)) let lastMouseMove = Date.now() tray.on('mouse-move', async () => { const now = Date.now() if (lastMouseMove + 500 > now) return false; lastMouseMove = now bounds = tray.getBounds() bounds = screen.dipToScreenRect(null, bounds) tryEagerUpdate(false) sendToAllWindows('panel-unsleep') if (settings.scrollShortcut) { // Start tracking cursor to determine when it leaves the tray if (mouseEvents && mouseEvents.getPaused()) { pauseMouseEvents(false) } willPauseMouseEvents() } }) } let recreatingTray = false async function recreateTray() { if(recreatingTray) return; recreatingTray = true tray?.destroy?.() tray = null createTray() recreatingTray = false } function setTrayMenu() { if (tray === null) return false; const contextMenu = Menu.buildFromTemplate([ getTimeAdjustmentsMenuItem(), getDetectIdleMenuItem(), getProfilesMenuItem(), getPausableSeparatorMenuItem(), { label: T.t("GENERIC_REFRESH_DISPLAYS"), type: 'normal', click: () => refreshMonitors(true, true) }, { label: T.t("GENERIC_SETTINGS"), type: 'normal', click: createSettings }, { type: 'separator' }, getDebugTrayMenuItems(), { label: T.t("GENERIC_QUIT"), type: 'normal', click: quitApp } ]) tray.setContextMenu(contextMenu) } function getPausableSeparatorMenuItem() { if (settings.detectIdleTimeEnabled || settings.adjustmentTimes.length > 0) { return { type: 'separator' } } return { label: "", visible: false } } function getTimeAdjustmentsMenuItem() { if (settings.adjustmentTimes?.length) { return { label: T.t("GENERIC_PAUSE_TOD"), type: 'checkbox', click: (e) => tempSettings.pauseTimeAdjustments = e.checked } } return { label: "", visible: false } } function getDetectIdleMenuItem() { if (settings.detectIdleTimeEnabled) { return { label: T.t("GENERIC_PAUSE_IDLE"), type: 'checkbox', click: (e) => tempSettings.pauseIdleDetection = e.checked } } return { label: "", visible: false } } function getProfilesMenuItem() { try { if(settings.profiles?.length) { const profiles = [] for(const profile of settings.profiles) { if(profile.showInMenu && profile.setBrightness) { profiles.push({ label: profile.name, type: 'normal', click: (e) => applyProfileBrightness(profile) }) } } if(profiles.length) { const submenu = Menu.buildFromTemplate(profiles) return { label: T.t("SETTINGS_PROFILES_TITLE"), submenu: submenu } } } } catch(e) { } return { label: "", visible: false } } function getDebugTrayMenuItems() { return { label: "DEBUG", visible: (settings.isDev ? true : false), submenu: [ { label: "RESTART PANEL", type: 'normal', click: () => restartPanel() }, { label: "RECREATE TRAY", type: 'normal', click: () => recreateTray() }, { label: "MINIMIZE PANEL", type: 'normal', click: () => mainWindow?.minimize() }, { label: "HIDE PANEL", type: 'normal', click: () => showPanel(false) }, { label: "OPACITY 0", type: 'normal', click: () => mainWindow?.setOpacity(0) }, { label: "OPACITY 1", type: 'normal', click: () => mainWindow?.setOpacity(1) }, { label: "DO CURRENT TOD", type: 'normal', click: () => applyCurrentAdjustmentEvent(true) }, { label: "REMOVE ACRYLIC", type: 'normal', click: () => tryVibrancy(mainWindow, false) }, { label: "PAUSE MOUSE", type: 'normal', click: () => pauseMouseEvents(true) }, { label: "LAST ACTIVE WIN", type: 'normal', click: () => trySetForegroundWindow(forcedFocusID) } ] } } function setTrayPercent() { try { if (tray) { let averagePerc = 0 let i = 0 for (let key in monitors) { if (monitors[key].type === "ddcci" || monitors[key].type === "wmi") { i++ averagePerc += monitors[key].brightness } } if (i > 0) { averagePerc = Math.floor(averagePerc / i) tray.setToolTip('Twinkle Tray' + (isDev ? " (Dev)" : "") + ' (' + averagePerc + '%)') } } } catch (e) { console.log(e) } } let lastEagerUpdate = 0 function tryEagerUpdate(forceRefresh = true) { const now = Date.now() if (now > lastEagerUpdate + 5000) { lastEagerUpdate = now refreshMonitors(forceRefresh, true) } } function quitApp() { app.quit() } const toggleTray = async (doRefresh = true, isOverlay = false) => { if (mainWindow == null) { createPanel(true) return false } if (isRefreshing) { //shouldShowPanel = true //return false } if (doRefresh && !isOverlay) { tryEagerUpdate(false) getThemeRegistry() getSettings() // Send accent sendToAllWindows('update-colors', getAccentColors()) if (latestVersion) sendToAllWindows('latest-version', latestVersion); } if (mainWindow) { mainWindow.setBackgroundColor("#00000000") if (!isOverlay) { // Check if overlay is currently open and deal with that if (!canReposition) { showPanel(false) hotkeyOverlayHide() setTimeout(() => { sendToAllWindows("display-mode", "normal") //toggleTray(doRefresh, isOverlay) }, 300) return false } sendMicaWallpaper() sendToAllWindows("display-mode", "normal") showPanel(true, panelSize.height) panelState = "visible" mainWindow.focus() } else { sendToAllWindows("display-mode", "overlay") panelState = "overlay" } sendToAllWindows('request-height') mainWindow.webContents.send("tray-clicked") mainWindow.setSkipTaskbar(false) mainWindow.setSkipTaskbar(true) } } // // // Intro Window // // let introWindow function showIntro() { // Check if user has already seen the intro if (settings.userClosedIntro) { return false; } if (introWindow != null) { // Don't make window if already open introWindow.focus() return false; } introWindow = new BrowserWindow({ width: 500, height: 650, show: false, maximizable: false, resizable: false, minimizable: false, frame: false, transparent: true, icon: './src/assets/logo.ico', title: "Twinkle Tray", webPreferences: { preload: path.join(__dirname, 'intro-preload.js'), devTools: settings.isDev, nodeIntegration: true, zoomFactor: 1.0, contextIsolation: false } }); introWindow.loadURL( isDev ? "http://localhost:3000/intro.html" : `file://${path.join(__dirname, "../build/intro.html")}` ); introWindow.on("closed", () => (introWindow = null)); introWindow.once('ready-to-show', () => { introWindow.setMenu(windowMenu) introWindow.show() if (lastTheme) sendToAllWindows('theme-settings', lastTheme) }) } ipcMain.on('close-intro', (event, newSettings) => { if (introWindow) { introWindow.close() writeSettings({ userClosedIntro: true }) } }) // // // Settings Window // // let settingsWindow function createSettings() { if (settingsWindow != null) { // Don't make window if already open settingsWindow.focus() return false; } const { width, height } = screen.getPrimaryDisplay().workAreaSize settingsWindow = new BrowserWindow({ width: (width >= 1200 ? 1024 : 600), height: (height >= 768 ? 720 : 500), minHeight: 450, minWidth: 600, show: false, maximizable: true, resizable: true, minimizable: true, backgroundColor: "#00000000", frame: false, icon: './src/assets/logo.ico', title: "Twinkle Tray Settings", webPreferences: { preload: path.join(__dirname, 'settings-preload.js'), devTools: settings.isDev, nodeIntegration: true, contextIsolation: false, allowRunningInsecureContent: true, webSecurity: false, zoomFactor: 1.0, additionalArguments: ["jsVars" + Buffer.from(JSON.stringify({ appName: app.name, appVersion: appVersion, appVersionTag: appVersionTag, appBuild: appBuildShort, settings, lastTheme, settingsPath })).toString('base64')] } }); settingsWindow.loadURL( isDev ? "http://localhost:3000/settings.html" : `file://${path.join(__dirname, "../build/settings.html")}` ); settingsWindow.on("closed", () => (settingsWindow = null)); settingsWindow.on("move", sendSettingsBounds) settingsWindow.on("resize", sendSettingsBounds) settingsWindow.on("maximize", sendSettingsBounds) settingsWindow.on("unmaximize", sendSettingsBounds) settingsWindow.on("restore", sendSettingsBounds) settingsWindow.once('ready-to-show', () => { settingsWindow.setMenu(windowMenu) // Show after a very short delay to avoid visual bugs setTimeout(() => { sendMicaWallpaper() settingsWindow.show() }, 100) // Prevent links from opening in Electron settingsWindow.webContents.on('will-navigate', (e, url) => { if (url.indexOf("http://localhost:3000") !== 0 || url.indexOf("file://") !== 0) return false; e.preventDefault() require('electron').shell.openExternal(url) }) }) // Sort Time of Day Adjustments // We're doing it here as it's least obtrusive to the UI. Refreshing when re-opening the window. if (settings.adjustmentTimes?.length) { settings.adjustmentTimes.sort((a, b) => { const aVal = Utils.parseTime(a.time) const bVal = Utils.parseTime(b.time) return aVal - bVal }) } } function sendSettingsBounds() { const newBounds = settingsWindow.getBounds() settingsWindow.webContents.send("settingsWindowMove", [newBounds.x, newBounds.y]) } ipcMain.on("sendSettingsWindowPos", sendSettingsBounds) ipcMain.on("windowMinimize", e => { BrowserWindow.fromWebContents(e.sender).minimize() }) ipcMain.on("windowToggleMaximize", e => { const window = BrowserWindow.fromWebContents(e.sender); if(window.isMaximized()) { window.unmaximize() } else { window.maximize() } }) ipcMain.on("windowClose", e => { BrowserWindow.fromWebContents(e.sender).close() }) // // // App Updates // // let latestVersion = false let lastCheck = false checkForUpdates = async (force = false) => { if (!force) { if (!settings.checkForUpdates) return false; if (lastCheck && lastCheck == new Date().getDate()) return false; } if (isPortable || isAppX) return false; lastCheck = new Date().getDate() try { if (isAppX === false) { console.log("Checking for updates...") fetch("https://api.github.com/repos/xanderfrangos/twinkle-tray/releases").then((response) => { response.json().then((releases) => { let foundVersion = false for (let release of releases) { if (!(settings.branch === "master" && release.prerelease === true)) { // Skip versions older than current const versionParsed = Utils.getVersionValue(release.tag_name) const appVersionValue = Utils.getVersionValue(`v${app.getVersion()}`) if(versionParsed < appVersionValue) continue; foundVersion = true latestVersion = { releaseURL: (release.html_url), version: release.tag_name, downloadURL: release.assets[0]["browser_download_url"], filesize: release.assets[0]["size"], changelog: release.body, show: false, error: false } console.log("Found version: " + latestVersion.version) break } } if (foundVersion && "v" + appVersion != latestVersion.version && (settings.dismissedUpdate != latestVersion.version || force)) { if (!force) latestVersion.show = true console.log("Sending new version to windows.") sendToAllWindows('latest-version', latestVersion) } }) }); } } catch (e) { console.log(e) } } getLatestUpdate = async (version) => { try { console.log("Downloading update from: " + version.downloadURL) const fs = require('fs'); latestVersion.downloading = true sendToAllWindows('latest-version', latestVersion) // Remove old update if (fs.existsSync(updatePath)) { try { fs.unlinkSync(updatePath) } catch (e) { console.log("Couldn't delete old update file") } } const update = await fetch(version.downloadURL) await new Promise((resolve, reject) => { console.log("Downloading...!") const readableNodeStream = Readable.fromWeb(update.body) const dest = fs.createWriteStream(updatePath) //update.body.pipe(dest); readableNodeStream.on('error', (err) => { reject(err) }) dest.on('close', () => { setTimeout(() => { runUpdate(version.filesize) }, 1250) resolve(true) }) readableNodeStream.on('finish', function () { console.log("Saved! Running...") }); let size = 0 let lastSizeUpdate = 0 readableNodeStream.on('data', (chunk) => { size += chunk.length dest.write(chunk, (err) => { if (size >= version.filesize) { dest.close() } }) if (size >= lastSizeUpdate + (version.filesize * 0.01) || lastSizeUpdate === 0 || size === version.filesize) { lastSizeUpdate = size sendToAllWindows('updateProgress', Math.floor((size / version.filesize) * 100)) console.log(`Downloaded ${size / 1000}KB. [${Math.floor((size / version.filesize) * 100)}%]`) } }) }) } catch (e) { console.log("Couldn't download update!", e) latestVersion.show = true latestVersion.downloading = false sendToAllWindows('latest-version', latestVersion) } } function runUpdate(expectedSize = false) { try { if (!fs.existsSync(updatePath)) { throw ("Update file doesn't exist!") } console.log("Expected size: " + expectedSize) const fileSize = fs.statSync(updatePath).size if (expectedSize && fileSize != expectedSize) { try { // Wrong file size, will try to delete fs.unlinkSync(updatePath) } catch (e) { throw ("Couldn't delete update file. " + e) } console.log("Atempted to delete update file") throw (`Update is wrong file size! Expected: ${expectedSize}. Got: ${fileSize}`) } /* // For testing latestVersion.show = true latestVersion.error = true sendToAllWindows('latest-version', latestVersion) return false; */ const { spawn } = require('child_process'); let process = spawn(updatePath, { detached: true, stdio: 'ignore' }); // IDK, try again? process.once("error", () => { setTimeout(() => { process = spawn(updatePath, { detached: true, stdio: 'ignore' }); }, 1000) }) process.unref() app.quit() } catch (e) { console.log(e) latestVersion.show = true latestVersion.error = true sendToAllWindows('latest-version', latestVersion) } } ipcMain.on('check-for-updates', () => { latestVersion.error = false sendToAllWindows('latest-version', latestVersion) checkForUpdates(true) }) ipcMain.on('ignore-update', (event, dismissedUpdate) => { writeSettings({ dismissedUpdate }) latestVersion.show = false sendToAllWindows('latest-version', latestVersion) }) ipcMain.on('clear-update', (event, dismissedUpdate) => { latestVersion.show = false sendToAllWindows('latest-version', latestVersion) }) // // // System event listeners // // let backgroundInterval = null function addEventListeners() { systemPreferences.on('accent-color-changed', () => { if(!settings.disableThemeChanges) handleAccentChange(); }) systemPreferences.on('color-changed', () => { if(!settings.disableThemeChanges) handleAccentChange(); }) nativeTheme.on('updated', () => { if(!settings.disableThemeChanges) handleAccentChange(); }) addDisplayChangeListener(() => { if(settings.useWin32Event) handleMonitorChange("win32") }) screen.addListener("display-added", () => { if(settings.useElectronEvents) handleMonitorChange("display-added") }) screen.addListener("display-removed", () => { if(settings.useElectronEvents) handleMonitorChange("display-removed") }) screen.addListener("display-metrics-changed", () => { if(settings.useElectronEvents) handleMetricsChange("display-metrics-changed") }) enableMouseEvents() // Disable mouse events at startup pauseMouseEvents(true) } let handleAccentChangeTimeout = false function handleAccentChange() { if (handleAccentChangeTimeout) clearTimeout(handleAccentChangeTimeout); handleAccentChangeTimeout = setTimeout(async () => { console.log("Event: handleAccentChange"); sendToAllWindows('update-colors', getAccentColors()) await getThemeRegistry() setTimeout(sendMicaWallpaper, 100) try { tray.setImage(getTrayIconPath()) } catch (e) { debug.log("Couldn't update tray icon!", e) } handleAccentChangeTimeout = false }, 2000) } let skipFirstMonChange = false let isStartupGracePeriod = false let handleChangeTimeout0 let handleChangeTimeout1 let handleChangeTimeout2 function handleMonitorChange(t, e, d) { console.log(`Event: handleMonitorChange (${t})`); // Skip event that happens at startup if (!skipFirstMonChange) { skipFirstMonChange = true return false } console.log("Hardware change detected.") const block = blockBadDisplays("handleMonitorChange") // Defer actions for a moment just in case of repeat events if (handleChangeTimeout2) { clearTimeout(handleChangeTimeout2) } handleChangeTimeout2 = setTimeout(async () => { if(settings.recreateTray) recreateTray(); // Reset all known displays await refreshMonitors(true) // During startup grace period, use current monitor brightness instead of saved profile // This prevents overwriting brightness that was manually set before shutdown if (!settings.disableAutoApply) { if (isStartupGracePeriod) { setKnownBrightness(true); // useCurrentMonitors = true to preserve current brightness } else { setKnownBrightness(); } } handleBackgroundUpdate(true) // Apply Time Of Day Adjustments // If displays not shown, refresh mainWindow if(settings.reloadFlyout && !panelSize.visible) { restartPanel(false) } handleChangeTimeout2 = false }, parseInt(settings.hardwareRestoreSeconds || 5) * 1000) setTimeout(() => { block.release() }, parseInt(settings.hardwareRestoreSeconds || 5) * 1000) } // Handle resume from sleep/hibernation powerMonitor.on("resume", () => { console.log("Resuming......") stopMonitorThread() const block = blockBadDisplays("powerMonitor:resume") setRecentlyInteracted(false) if(settings.restartOnWake) { // Screw it, just restart the whole app. tray.destroy() app.relaunch() app.exit() } setTimeout( () => { startMonitorThread() setTimeout( () => { block.release() if (!settings.disableAutoRefresh) refreshMonitors(true).then(() => { if (!settings.disableAutoApply && !hasRecentlyInteracted) setKnownBrightness(); if(settings.recreateTray) recreateTray(); if(settings.recreateFlyout && !panelSize.visible) restartPanel(); // Check if time adjustments should apply applyCurrentAdjustmentEvent(true, false) }) }, parseInt(settings.wakeRestoreSeconds || 8) * 1000 // Give Windows a few seconds to... you know... wake up. ) }, 100) }) function handleMetricsChange(type) { console.log(`Event: handleMetricsChange (${type})`); const block = blockBadDisplays("handleMetricsChange") // Defer actions for a moment just in case of repeat events if (handleChangeTimeout1) { clearTimeout(handleChangeTimeout1) } handleChangeTimeout1 = setTimeout(async () => { // if handleMonitorChange is going to run, we don't need to do anything if(handleChangeTimeout2) return false; // Do a quick check to ensure handles are all good await refreshMonitors(true) // During startup grace period, use current monitor brightness instead of saved profile // This prevents overwriting brightness that was manually set before shutdown if (!settings.disableAutoApply && !hasRecentlyInteracted) { if (isStartupGracePeriod) { setKnownBrightness(true); // useCurrentMonitors = true to preserve current brightness } else { setKnownBrightness(); } } handleBackgroundUpdate(true) // Apply Time Of Day Adjustments handleChangeTimeout1 = false }, parseInt(settings.idleRestoreSeconds || 7) * 1000) setTimeout(() => { block.release() }, parseInt(settings.idleRestoreSeconds || 3) * 1000) } // Monitor system power/lock state to avoid accidentally tripping the WMI auto-disabler let recentlyWokeUp = false powerMonitor.on("suspend", () => { console.log("Event: suspend"); recentlyWokeUp = true }) powerMonitor.on("lock-screen", () => { console.log("Event: lock-screen"); if (settings.disableOnLockScreen) recentlyWokeUp = true }) powerMonitor.on("unlock-screen", () => { console.log("Event: unlock-screen"); if (recentlyWokeUp) { if (!settings.disableAutoRefresh) handleMetricsChange("unlock-screen"); setTimeout(() => { recentlyWokeUp = false }, 15000 ) } }) powerMonitor.on("resume", () => { console.log("Event: resume"); recentlyWokeUp = true if (!settings.disableAutoRefresh) handleMetricsChange("resume"); setTimeout(() => { recentlyWokeUp = false }, 15000 ) }) let restartBackgroundUpdateThrottle = false function restartBackgroundUpdate() { if (!restartBackgroundUpdateThrottle) { restartBackgroundUpdateThrottle = setTimeout(() => { restartBackgroundUpdateThrottle = false clearInterval(backgroundInterval) backgroundInterval = setInterval(() => handleBackgroundUpdate(), (isDev ? 8000 : 60000 * 1)) handleBackgroundUpdate() }, 3000) } else { clearTimeout(restartBackgroundUpdateThrottle) restartBackgroundUpdateThrottle = false restartBackgroundUpdate() } } // Idle detection let isUserIdle = false // Idle detection as defined by Twinkle Tray let userIdleInterval = false // Check if idle let userCheckingForActiveInterval = false // Check if came back let userIdleDimmed = false let idleMonitorBlock let isWindowsUserIdle = false // Idle detection as defined by Windows let idleMonitor = setInterval(idleCheckLong, 5000) let notIdleMonitor let lastIdleTime = 0 let preIdleMonitors = {} function getIdleSettingValue() { const detectIdleTime = (parseInt(settings.detectIdleTimeSeconds) + (settings.detectIdleTimeMinutes * 60)) return detectIdleTime } function idleCheckLong() { if (tempSettings.pauseIdleDetection) return false; //if(powerMonitor.onBatteryPower) return false; const idleTime = powerMonitor.getSystemIdleTime() lastIdleTime = idleTime if (idleTime >= (settings.detectIdleTimeEnabled ? getIdleSettingValue() : 180) && !notIdleMonitor) { startIdleCheckShort() } } async function startIdleCheckShort() { isUserIdle = true await updateKnownDisplays(true, true) preIdleMonitors = Object.assign({}, lastKnownDisplays) console.log(`\x1b[36mStarted short idle monitor.\x1b[0m`) if (notIdleMonitor) clearInterval(notIdleMonitor); notIdleMonitor = setInterval(idleCheckShort, 1000) } function isFocusedWindowFullscreen() { try { if(!settings.detectIdleCheckFullscreen) return false; const focusedHwnd = WindowUtils.getForegroundWindow() const isFullscreen = WindowUtils.getWindowFullscreen(focusedHwnd) return isFullscreen } catch(e) { console.log(e) return false } } function isMediaPlaying() { try { if(!settings.detectIdleMedia) return false; const mediaPlaying = MediaStatus.getPlaybackStatus() return (mediaPlaying === "playing" ? true : false) } catch(e) { console.log(e) return false } } function idleCheckShort() { try { const idleTime = powerMonitor.getSystemIdleTime() if (!userIdleDimmed && settings.detectIdleTimeEnabled && !settings.disableAutoApply && idleTime >= getIdleSettingValue() && !isFocusedWindowFullscreen() && !isMediaPlaying()) { console.log(`\x1b[36mUser idle. Dimming displays.\x1b[0m`) userIdleDimmed = true idleMonitorBlock?.release?.() idleMonitorBlock = blockBadDisplays("idle:start") try { const transitionMonitors = {} Object.values(monitors)?.forEach((monitor) => { if(!shouldSkipDisplay(monitor, true)) { if(settings.idleTransitionSpeed) { transitionMonitors[monitor.id] = 0 } else { updateBrightness(monitor.id, 0, true, "brightness") } } }) if(Object.keys(transitionMonitors).length) { transitionBrightness(0, transitionMonitors, settings.idleTransitionSpeed) } } catch (e) { console.log(`Error dimming displays`, e) } } if (isUserIdle && (idleTime < lastIdleTime || idleTime < getIdleSettingValue())) { // Wake up console.log(`\x1b[36mUser no longer idle after ${lastIdleTime} seconds.\x1b[0m`) clearInterval(notIdleMonitor) notIdleMonitor = false // Different behavior depending on if idle dimming is on if (settings.detectIdleTimeEnabled) { // Always restore when dimmed const block = blockBadDisplays("idle:restore") setKnownBrightness(false) block.release() } else { // Not dimmed, try checking ToD first. sKB as backup. const foundEvent = applyCurrentAdjustmentEvent(true, true) if (!foundEvent && !settings.disableAutoApply) setKnownBrightness(false); } idleMonitorBlock?.release?.() // Wait a little longer, re-apply known brightness in case monitors take a moment, and finish up setTimeout(() => { isUserIdle = false userIdleDimmed = false lastIdleTime = 1 const block = blockBadDisplays("idle:end") // Similar logic to above if (settings.detectIdleTimeEnabled) { // Always restore when dimmed, then check ToD setKnownBrightness(false) applyCurrentAdjustmentEvent(true, false) } else { // Not dimmed, try checking ToD first. sKB as backup. const foundEvent = applyCurrentAdjustmentEvent(true, true) if (!foundEvent && !settings.disableAutoApply) setKnownBrightness(false) } block.release() }, parseInt(settings.idleRestoreSeconds || 4) * 1000) } lastIdleTime = idleTime } catch (e) { console.log('Error in idleCheckShort', e) } } // Get the currently applicable Time of Day Adjustment function getCurrentAdjustmentEvent() { const date = new Date() const nowValue = (date.getHours() * 60) + (date.getMinutes() * 1) // Find most recent event let foundEvent = false try { for (let event of settings.adjustmentTimes) { const eventTime = (event.useSunCalc ? getSunCalcTime(event.sunCalc) : event.time) const eventValue = Utils.parseTime(eventTime) // Check if event is not later than current time, last event time, or last found time if (eventValue <= nowValue) { // Check if found event is greater than last found event if (foundEvent === false || foundEvent.value <= eventValue) { foundEvent = Object.assign({}, event) foundEvent.monitors = Object.assign({}, event.monitors) foundEvent.value = eventValue } } } } catch (e) { console.log("Error getting adjustment times!", e) } return foundEvent } function getNextAdjustmentEvent() { const currentEvent = getCurrentAdjustmentEvent() if (!currentEvent) return false let earliestEvent = false let closestEvent = false try { for (let event of settings.adjustmentTimes) { const eventTime = (event.useSunCalc ? getSunCalcTime(event.sunCalc) : event.time) const eventValue = Utils.parseTime(eventTime) // Check if event is later than current time, and less than the last found event if (eventValue > currentEvent.value && (!closestEvent || eventValue < closestEvent.value)) { closestEvent = Object.assign({}, event) closestEvent.monitors = Object.assign({}, event.monitors) closestEvent.value = eventValue } // Check if event is the earliest if (!earliestEvent || eventValue < earliestEvent.value) { earliestEvent = Object.assign({}, event) earliestEvent.monitors = Object.assign({}, event.monitors) earliestEvent.value = eventValue } } } catch (e) { console.log("Error getting adjustment times!", e) } // Return closest event or earliest event return (closestEvent ? closestEvent : earliestEvent) } function getCurrentAdjustmentEventLERP() { try { const current = getCurrentAdjustmentEvent() const next = getNextAdjustmentEvent() if (!current || !next) return false; const date = new Date() const nowValue = (date.getHours() * 60) + (date.getMinutes() * 1) if (current.value > next.value) { next.value += 1440 // Add 24hr if next event is tomorrow } // Calculate 0-1 percentage of progress const lerpValues = { next: next.value - current.value, current: current.value - current.value, now: nowValue - current.value } lerpValues.progress = lerpValues.next - lerpValues.now lerpValues.end = lerpValues.next lerpValues.percent = 1 - (lerpValues.progress / lerpValues.end) // Generate result depending on if displays are linked if (settings.adjustmentTimeIndividualDisplays) { const keys = Object.keys(next.monitors) const monitors = Object.assign(current.monitors) keys.forEach(key => { if (monitors[key] > -1) { monitors[key] = Math.round(Utils.lerp(current.monitors[key], next.monitors[key], lerpValues.percent)) } }) return monitors } else { return Math.round(Utils.lerp(current.brightness, next.brightness, lerpValues.percent)) } } catch (e) { console.log("Error generating Adjustment Time LERP", e) return false } } function getSunCalcTime(timeName = "solarNoon") { const localTimes = SunCalc.getTimes(new Date(), settings.adjustmentTimeLatitude, settings.adjustmentTimeLongitude) const time = new Date(localTimes[timeName]) return `${time.getHours()}:${time.getMinutes()}` } function getSunCalcTimes() { const localTimes = SunCalc.getTimes(new Date(), settings.adjustmentTimeLatitude, settings.adjustmentTimeLongitude) for(const timeName in localTimes) { const time = new Date(localTimes[timeName]) localTimes[timeName] = `${time.getHours()}:${time.getMinutes()}` } return localTimes } // If applicable, apply the current Time of Day Adjustment function applyCurrentAdjustmentEvent(force = false, instant = true) { try { if (tempSettings.pauseTimeAdjustments || currentProfile?.setBrightness) return false; if (settings.adjustmentTimes.length === 0 || userIdleDimmed) return false; const date = new Date() // Reset on new day if (force || settings.adjustmentTimeAnimate || (lastTimeEvent && lastTimeEvent.day != date.getDate())) { console.log("New day (or forced)... resetting lastTimeEvent") lastTimeEvent = false } // Find most recent event const foundEvent = getCurrentAdjustmentEvent() if (foundEvent) { if (lastTimeEvent == false || lastTimeEvent.value < foundEvent.value) { if (settings.adjustmentTimeAnimate) { // If LERPing, override foundEvent with interpolated value lerp = getCurrentAdjustmentEventLERP() if (typeof lerp === "number") { foundEvent.brightness = lerp } else if (typeof lerp === "object") { foundEvent.monitors = lerp } } console.log("Adjusting brightness automatically", foundEvent) lastTimeEvent = Object.assign({}, foundEvent) lastTimeEvent.day = new Date().getDate() refreshMonitors().then(() => { if (instant || settings.adjustmentTimeSpeed === "instant") { transitionlessBrightness(foundEvent.brightness, (foundEvent.monitors ? foundEvent.monitors : {})) } else { transitionBrightness(foundEvent.brightness, (foundEvent.monitors ? foundEvent.monitors : {})) } }) return foundEvent } } } catch (e) { console.log("Error applying current Time of Day Adjustment", e) } } let lastTimeEvent = { hour: new Date().getHours(), minute: new Date().getMinutes(), day: new Date().getDate() } function handleBackgroundUpdate(force = false) { console.log("Event: handleBackgroundUpdate"); try { // Wallpaper updates sendMicaWallpaper() // Time of Day Adjustments if (settings.adjustmentTimes.length > 0 && !userIdleDimmed) { applyCurrentAdjustmentEvent(force, false) } } catch (e) { console.error(e) } if (!force) checkForUpdates(); // Ignore when forced update, since it should just be about fixing brightness. // GC setTimeout(() => { try { global.gc() } catch (e) { } }, 1000) } let lastCoordCheck = { value: { lat: 0, long: 0}, ts: 0 } async function getUserCoordinates() { if(Date.now() - 10000 < lastCoordCheck.ts) return lastCoordCheck.value; try { if (isAppX === false) { console.log("Getting geolocation...") const response = await fetch("https://geo.twinkletray.com/") if(response.status === 200) { const coordinates = { lat: response.headers.get("X-Geo-Lat"), long: response.headers.get("X-Geo-Long") } if(typeof coordinates.lat === "string" && typeof coordinates.long === "string") { console.log("Coordinates: ", coordinates) lastCoordCheck.value = coordinates lastCoordCheck.ts = Date.now() return coordinates } throw("Couldn't get coordinates. Returned: " . JSON.stringify(coordinates)) } } } catch (e) { console.log(e) } } async function getAndApplyUserCoordinates() { try { const coordinates = await getUserCoordinates() writeSettings({adjustmentTimeLongitude: coordinates.long, adjustmentTimeLatitude: coordinates.lat}, true, true) } catch(e) { console.log(e) } } ipcMain.on('get-coordinates', getAndApplyUserCoordinates) /* Handle input from second process command line. One monitor argument and one brightness argument is required. Multiple arguments will override each other. Full example: TwinkleTray.exe --MonitorNum=1 --Offset=-30 Supported args: --MonitorNum Select monitor by number. Starts at 1. Example: --MonitorNum=2 --MonitorID Select monitor by internal ID. Partial or whole matches accepted. Example: --MonitorID="UID2353" --All Flag to update all monitors. Example: --All --Set Set brightness percentage. Example: --Set=95 --Offset Adjust brightness percentage. Example: --Offset=-20 --VCP Send a specific DDC/CI VCP code and value instead of brightness. The first part is the VCP code (decimal or hexadecimal), and the second is the value. Example: --VCP="0xD6:5" --Overlay Flag to show brightness levels in the overlay Example: --Overlay --Panel Flag to show brightness levels in the panel Example: --Panel */ function handleCommandLine(event, argv, directory, additionalData) { let display let type let brightness let usetime let ddcciVCP let commandLine = [] try { // Extract flags additionalData.forEach((flag) => { if (flag.indexOf('--') == 0) { commandLine.push(flag.toLowerCase()) } }) if (commandLine.length > 0) { commandLine.forEach(arg => { // List all displays if (arg.indexOf("--list=") === 0) { } // Get display by index if (arg.indexOf("--monitornum=") === 0) { display = Object.values(monitors)[(arg.substring(13) * 1) - 1] } // Get display by ID (partial or whole) if (arg.indexOf("--monitorid=") === 0) { const monID = Object.keys(monitors).find(id => { return id.toLowerCase().indexOf(arg.substring(12)) >= 0 }) display = monitors[monID] } // Run on all displays if (arg.indexOf("--all") === 0 && arg.length === 5) { display = "all" } // Use absolute brightness if (arg.indexOf("--set=") === 0) { brightness = (arg.substring(6) * 1) type = "set" } // Use relative brightness if (arg.indexOf("--offset=") === 0) { brightness = (arg.substring(9) * 1) type = "offset" } // Use time adjustments if (arg.indexOf("--usetime") === 0) { usetime = true } // DDC/CI command if (arg.indexOf("--vcp=") === 0 && arg.indexOf(":")) { try { const values = arg.substring(6).replace('"').replace('"').split(":") ddcciVCP = { code: parseInt(values[0]), value: parseInt(values[1]) } } catch (e) { console.log("Couldn't parse VCP code!") } } // Show overlay if (arg.indexOf("--overlay") === 0 && panelState !== "visible") { hotkeyOverlayStart() } // Show panel if (arg.indexOf("--panel") === 0 && panelState !== "visible") { toggleTray(true) } }) // If value input, update brightness if (display && type && brightness !== undefined) { if (display === "all") { console.log(`Setting brightness via command line: All @ ${brightness}%`); updateAllBrightness(brightness, type) } else { const newBrightness = minMax(type === "set" ? brightness : display.brightness + brightness) console.log(`Setting brightness via command line: Display #${display.num} (${display.name}) @ ${newBrightness}%`); updateBrightnessThrottle(display.id, newBrightness, true) } } if (display && ddcciVCP) { if (display === "all") { Object.values(monitors).forEach(monitor => { monitorsThread.send({ type: "vcp", code: ddcciVCP.code, value: ddcciVCP.value, monitor: monitor.hwid.join("#") }) }) } else { monitorsThread.send({ type: "vcp", code: ddcciVCP.code, value: ddcciVCP.value, monitor: display.hwid.join("#") }) } } if (usetime) { applyCurrentAdjustmentEvent(true, false) } } } catch (e) { console.log(e) } } // Mica features let currentWallpaper = "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D"; let currentWallpaperTime = false; let currentWallpaperFileSize = 0; let currentScreenSize = { width: 1280, height: 720, scale: 1 } let micaBusy = false let lastMicaTime = Date.now() const homeDir = require("os").homedir() const micaWallpaperPath = path.join(configFilesDir, `\\mica${(isDev ? "-dev" : "")}.jpg`) const windowWallpaperPath = path.join(homeDir, "AppData", "Roaming", "Microsoft", "Windows", "Themes", "TranscodedWallpaper"); function checkMicaWallpaper() { if (micaBusy) { sendToAllWindows("mica-wallpaper", { path: currentWallpaper, size: currentScreenSize }) return false } try { const file = fs.statSync(windowWallpaperPath) const newTime = file.mtime.getTime() const newSize = file.size currentScreenSize = screen.getPrimaryDisplay().workAreaSize currentScreenSize.scale = screen.getPrimaryDisplay().scaleFactor if (file?.mtime && (newTime !== currentWallpaperTime || newSize !== currentWallpaperFileSize)) { micaBusy = true currentWallpaperTime = newTime currentWallpaperFileSize = newSize; // Send off wallpaper to be Mica'd in "panel" renderer sendToAllWindows("mica-wallpaper-create", { path: "file://" + windowWallpaperPath + "?" + newTime, size: currentScreenSize }) } sendToAllWindows("mica-wallpaper", { path: currentWallpaper, size: currentScreenSize }) } catch(e) { micaBusy = false sendToAllWindows("mica-wallpaper", { path: currentWallpaper, size: currentScreenSize }) } } ipcMain.on('mica-wallpaper-data', (event, data) => { try { console.log("Created Mica wallpaper:", micaWallpaperPath) fs.writeFileSync(micaWallpaperPath, Buffer.from(data.split(',')[1], 'base64')) lastMicaTime = Date.now() currentWallpaper = "file://" + micaWallpaperPath + "?" + lastMicaTime sendToAllWindows("mica-wallpaper", { path: currentWallpaper, size: currentScreenSize }) } catch(e) { console.log(e) } micaBusy = false }) ipcMain.on('mica-wallpaper-same', (event, data) => { sendToAllWindows("mica-wallpaper", { path: currentWallpaper, size: currentScreenSize }) }) async function sendMicaWallpaper() { if (!mainWindow) return false; checkMicaWallpaper() } ipcMain.on('get-mica-wallpaper', sendMicaWallpaper) // // // Server common // // const handleClientMessage = async (message, remote) => { const type = (remote ? `UDP` : `PIPE`) try { if(remote) { console.log(`[${type}] Got: ${message} from ${remote.address}:${remote.port}`) } else { console.log(`[${type}] Got: ${message}`) } const data = JSON.parse(message) if (typeof data !== "object" || !data?.type) { throw(`[${type}] Invalid command`) } console.log(data.key, settings.udpKey) if (remote && data.key !== settings.udpKey) { throw("[UDP] Missing or invalid key") } const findMonitor = monitor => { try { const searchID = monitor.toLowerCase() const monID = Object.keys(monitors).find(id => { return id.toLowerCase().indexOf(searchID) >= 0 }) return monitors[monID] } catch (e) { return false } } const determineVCP = vcp => { switch (vcp) { case "brightness": return 0x10; case "contrast": return 0x12; case "power": return 0xD6; case "volume": return 0x62; default: return parseInt(vcp); } } // Run recieved command if (data.type === "list") { // data.type === "list" // List all current monitors return JSON.stringify(monitors) } else if (data.type === "get") { // data.type === "get" // Get property of specific monitor if (!(data.monitor && data.property)) throw("Missing parameter!"); const monitor = findMonitor(data.monitor) if (!monitor) throw("Couldn't find monitor!") const getMonitorProperty = (monitor, property) => { try { const { features } = monitor switch (property) { case "brightness": return monitor.brightness; case "maxbrightness": return monitor.brightnessMax; case "rawbrightness": return monitor.brightnessRaw; case "brightnesstype": return monitor.brightnessType; case "id": return monitor.id; case "key": return monitor.key; case "name": return monitor.name; case "hwid": return monitor.hwid.join("#"); case "name": return monitor.name; case "type": return monitor.type; case "connector": return monitor.connector; case "serial": return monitor.serial; case "order": return monitor.order; case "contrast": return (features.contrast ? features.contrast[0] : -1); case "maxcontrast": return (features.contrast ? features.contrast[1] : -1); case "powerstate": return (features.powerState ? features.powerState[0] : -1); case "maxpowerstate": return (features.powerState ? features.powerState[1] : -1); case "volume": return (features.volume ? features.volume[0] : -1); case "maxvolume": return (features.volume ? features.volume[1] : -1); default: throw("Invalid property!"); } } catch (e) { throw(`[${type}] Error getting monitor property`, e) } } if (data.property === "vcp") { return await getVCP(monitor, data.code) } else { return getMonitorProperty(monitor, data.property) } } else if (data.type === "set" || data.type === "setvcp") { // data.type === "set" // Set property of specific monitor if (!(data.monitor && data.vcp)) throw("Missing parameters!"); const value = parseInt(data.value) if (data.monitor === "all") { updateAllBrightness(value, (data.mode ?? "set")) return true } const monitor = findMonitor(data.monitor) if (!monitor) throw("Couldn't find monitor!"); if (data.vcp === "brightness") { const newBrightness = minMax(data.mode !== "offset" ? value : monitor.brightness + value) updateBrightnessThrottle(monitor.id, newBrightness, true) } else { monitorsThread.send({ type: "vcp", code: determineVCP(data.vcp), value: value, monitor: monitor.hwid.join("#") }) } } else if (data.type === "checktime") { // data.type === "checktime" // Use time adjustments applyCurrentAdjustmentEvent(true, false) } else if (data.type === "refresh") { // data.type === "refresh" // Force refresh monitors refreshMonitors(true, true) } } catch (e) { console.log(`[${type}] Error:`, e) } } // // // UDP Server // // const udp = { server: false, start: function (port = 14715) { if (udp.server) return false; console.log("[UDP] Starting local UDP Server...") const dgram = require('dgram') const server = dgram.createSocket('udp4') udp.server = server server.on('error', error => { console.log(`[UDP] UDP server error:\n${error.stack}`) server.close() }); server.on('message', async (message, remote) => { const sendResponse = response => server.send(`${response}`, remote.port, remote.address) try { const response = await handleClientMessage(message, remote) sendResponse(response) } catch(e) { console.log(e) } }); server.on('listening', () => { const connection = server.address(); writeSettings({ udpPortActive: connection.port }) console.log(`[UDP] UDP server listening at ${connection.address}:${connection.port}`); }); // Bind to default port, or another if it fails const address = (!settings.udpRemote ? 'localhost' : undefined) try { server.bind({ address, port }) } catch (e) { try { // Let's try another server.bind({ address, port: (port + 13137) }) } catch (e2) { try { // Okay, one more? server.bind({ address, port: (port + 1603) }) } catch (e3) { console.log(e3) } } } }, stop: function () { try { if (udp.server) { console.log("[UDP] Stopping local UDP Server.") udp.server.close() udp.server = false } } catch (e) { console.log("[UDP] Couldn't close UDP server.") } } } // // // Named Pipe Server // // const pipe = { server: false, start: function () { if (pipe.server) return false; console.log("[PIPE] Starting named pipe...") const server = require('net').createServer(function(stream) { stream.on('data', async function(message) { console.log('server data:', message.toString()); const sendResponse = response => stream.write(`${response}`) try { const response = await handleClientMessage(message) sendResponse(response) } catch(e) { console.log(e) } }); }); pipe.server = server server.on('error', error => { console.log(`[PIPE] Server error:\n${error.stack}`) server.close() }); server.on('listening', () => { const connection = server.address(); console.log(`[PIPE] Server listening at ${connection.toString()}`); }); // Bind to default port, or another if it fails try { server.listen('\\\\.\\pipe\\twinkle-tray\\cmds'); } catch (e) { console.log(e) } }, stop: function () { try { if (pipe.server) pipe.server.close(); } catch (e) { console.log("[PIPE] Couldn't close server.") } } } pipe.start() ================================================ FILE: src/hooks/useObject.js ================================================ import { useState } from "react" export function useObject(initialState = {}) { const [state, setState] = useState(Object.assign({}, initialState)) const applyState = (newState) => { setState(prevState => ({ ...prevState, ...newState })) } return [state, applyState] } ================================================ FILE: src/html/index.html ================================================ Twinkle Tray Panel
================================================ FILE: src/html/intro.html ================================================ Twinkle Tray
================================================ FILE: src/html/settings.html ================================================ Twinkle Tray Settings
================================================ FILE: src/intro-preload.js ================================================ const { ipcRenderer: ipc } = require('electron'); window.closeIntro = () => { ipc.send('close-intro') } function detectSunValley() { try { // Detect new Fluent Icons (Windows build 21327+) if(document.fonts.check("12px Segoe Fluent Icons")) { window.document.body.dataset.fluentIcons = true window.document.body.dataset.isWin11 = true } else { window.document.body.dataset.fluentIcons = false } // Detect new system font (Windows build 21376+) if(document.fonts.check("12px Segoe UI Variable Text")) { window.document.body.dataset.segoeUIVariable = true } else { window.document.body.dataset.segoeUIVariable = false } } catch(e) { console.log("Couldn't test for Sun Valley", e) } } window.addEventListener('load', () => { ipc.send('request-localization') detectSunValley() setTimeout(() => { document.getElementById("video").play() }, 2400) }) // Localization recieved ipc.on('localization-updated', (event, localization) => { window.dispatchEvent(new CustomEvent('localizationUpdated', { detail: localization })) }) window.ipc = ipc ================================================ FILE: src/intro.js ================================================ import React from "react"; import { createRoot } from 'react-dom/client'; import IntroWindow from "./components/IntroWindow"; createRoot(document.getElementById("root")).render() ================================================ FILE: src/localization/ar.json ================================================ { "LANGUAGE": "Arabic", "GENERIC_OK": "اوكي", "GENERIC_CANCEL": "إلغاء", "GENERIC_SAVE": "حفظ", "GENERIC_CLEAR": "مسح", "GENERIC_OFF": "إيقاف", "GENERIC_ON": "تشغيل", "GENERIC_QUIT": "خروج", "GENERIC_CLOSE": "اغلاق", "GENERIC_SETTINGS": "الإعدادات", "GENERIC_INSTALL": "تثبيت", "GENERIC_DISMISS": "رفض", "GENERIC_DISPLAY_SINGLE": "الشاشة", "GENERIC_ALL_DISPLAYS": "كل الشاشات", "GENERIC_REFRESH_DISPLAYS": "تحديث الشاشة", "GENERIC_MINIMUM": "اقل", "GENERIC_MAXIMUM": "اكثر", "GENERIC_NO_DISPLAYS": "لم يتم الكشف عن أي شاشات. يرجى توصيل شاشة بجهاز الكمبيوتر الخاص بك.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "لم يتم العثور على شاشات متوافقة. يرجى التحقق من تمكين \"DDC / CI\" لشاشات العرض الخاصة بك.", "GENERIC_NO_DISPLAYS_SHORT": "لم يت العثور على شاشات متطابقة.", "GENERIC_SECONDS": "ثواني", "GENERIC_MINUTES": "دقائق", "GENERIC_DDC_WARNING": "DDC/CI يمكن أن تتسبب ميزات مثل التحكم في حالة الطاقة في عدم استجابة شاشتك. استخدام على مسؤوليتك الخاصة.", "GENERIC_SPEED_INSTANT": "فوري", "GENERIC_SPEED_SLOW": "بطيء", "GENERIC_SPEED_VERY_SLOW": "بطيء جدا", "GENERIC_SPEED_NORMAL": "طبيعي", "GENERIC_SPEED_FAST": "سريع", "GENERIC_SPEED_VERY_FAST": "سريع جدا", "GENERIC_PAUSE_TOD": "ايقاف تعديلات الوقت", "GENERIC_PAUSE_IDLE": "ايقاف كشف الخمول", "PANEL_TITLE": "تعديل السطوع", "PANEL_UPDATE_AVAILABLE": "يوجد اصدار جديد", "PANEL_BUTTON_LINK_LEVELS": "ربط المستويات", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "ايقاف شاشة العرض", "PANEL_LABEL_BRIGHTNESS": "السطوع", "PANEL_LABEL_CONTRAST": "التباين", "PANEL_LABEL_OFF_ON": "حالة الطاقة", "PANEL_LABEL_COLOR_TEMPERATURE": "حرارة الالوان", "PANEL_LABEL_VOLUME": "الصوت", "PANEL_LABEL_TURN_OFF": "ايقاف الطاقة", "INTRO_TITLE": "مرحباً, توينكل تراي", "INTRO_INSTRUCTIONS": "ربما تكون أيقونة الدرج الخاصة بـ توينكل تراي مخفية ، لذا يجب عليك نقلها إلى مكان ما يمكنك الوصول إليه بسهولة. انظر أدناه للحصول على التعليمات.", "SETTINGS_TITLE": "إعدادات توينكل تراي", "SETTINGS_SIDEBAR_GENERAL": "عام", "SETTINGS_SIDEBAR_MONITORS": "ضبط توينكل تراي", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI خصائص", "SETTINGS_SIDEBAR_TIME": "تعديلات الوقت", "SETTINGS_SIDEBAR_HOTKEYS": "المفاتيح السريعة و الاختصارات", "SETTINGS_SIDEBAR_UPDATES": "التحديثات", "SETTINGS_GENERAL_TITLE": "عام", "SETTINGS_GENERAL_STARTUP": "تشغيل البرنامج عند بدء الجهاز", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "تطبيق السطوع عند بدء التشغيل", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "قم باستعادة آخر سطوع معروف لكل شاشة عند بدء توينكل تراي.", "SETTINGS_GENERAL_THEME_TITLE": "الانماط", "SETTINGS_GENERAL_THEME_SYSTEM": "تفضيلات النظام (افتراضي)", "SETTINGS_GENERAL_THEME_DARK": "مظلم", "SETTINGS_GENERAL_THEME_LIGHT": "مضيء", "SETTINGS_GENERAL_LANGUAGE_TITLE": "اللغة", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "لغة النظام (افتراضي)", "SETTINGS_GENERAL_RESET_TITLE": "اعادة الضبط", "SETTINGS_GENERAL_RESET_DESC": "اضغط على هذا الزر لمسح الضبط الخاص بك.", "SETTINGS_GENERAL_RESET_BUTTON": "اعادة الضبط", "SETTINGS_GENERAL_ACRYLIC_TITLE": "تمويه اكلريكي", "SETTINGS_GENERAL_ACRYLIC_DESC": "قم بتمكين أو تعطيل التمويه خلف الخلفيات الشفافة في توينكل تراي.", "SETTINGS_GENERAL_MICA_TITLE": "تمويه مايكا", "SETTINGS_GENERAL_MICA_DESC": "قم بتمكين أو تعطيل التمويه خلف الخلفيات الشفافة في توينكل تراي.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "احصائيات", "SETTINGS_GENERAL_ANALYTICS_DESC": "أرسل بيانات الاستخدام للمساعدة في تحسين توينكل تراي. لا يتم إرسال معلومات شخصية. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "تعلم المزيد", "SETTINGS_GENERAL_SCROLL_TITLE": "اختصار تمرير رمز الدرج", "SETTINGS_GENERAL_SCROLL_DESC": "اضبط سطوع جميع شاشات العرض مرة واحدة عن طريق التمرير فوق رمز علبة النظام. هذا لا يعمل مع بعض لوحات التتبع.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "رمز الدرج", "SETTINGS_GENERAL_TROUBLESHOOTING": "استكشاف الأخطاء وإصلاحها", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "تعطيل طرق الكشف عن الشاشة", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "إذا كان توينكل تراي لا يستجيب عند النقر فوق رمز العلبة أو عدم اكتشاف شاشات العرض الخاصة بك ، يمكنك محاولة تعطيل بعض طرق الكشف عن الشاشة. أعد تشغيل توينكل تراي حتى تدخل التغييرات حيز التنفيذ. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "تعطيل التداخل", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "إذا كان تداخل مفتاح الاختصار لـ توينكل تراي يتداخل مع تطبيقات ملء الشاشة ، فيمكنك تعطيله هنا.", "SETTINGS_MONITORS_RATE_TITLE": "معدل تحديث السطوع", "SETTINGS_MONITORS_RATE_DESC": "كم مرة سيتم تحديث السطوع على شاشاتك أثناء ضبط قيمها. قم بزيادة الوقت إذا كانت شاشات العرض الخاصة بك تومض.", "SETTINGS_MONITORS_RATE_0": "غريب", "SETTINGS_MONITORS_RATE_1": "سريع (250 ms)", "SETTINGS_MONITORS_RATE_2": "طبيعي (500 ms)", "SETTINGS_MONITORS_RATE_3": "بطيء (1 second)", "SETTINGS_MONITORS_RATE_4": "بطيء جدا (2 seconds)", "SETTINGS_MONITORS_RENAME_TITLE": "إعادة تسمية الشاشات", "SETTINGS_MONITORS_RENAME_DESC": "إذا كنت تفضل اسمًا مختلفًا لكل شاشة (مثل \"الشاشة اليسرى \" ، \"الشاشة الوسطى \") ، يمكنك إدخاله أدناه. سيؤدي ترك الحقل فارغًا إلى استعادة الاسم الأصلي.", "SETTINGS_MONITORS_ENTER_NAME": "ادخل الاسم", "SETTINGS_MONITORS_REORDER_TITLE": "اعادة ترتيب الشاشات", "SETTINGS_MONITORS_REORDER_DESC": "قم بتغيير ترتيب عرض الشاشات في الدرج. انقر واسحب لإجراء التغييرات.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "تطبيع السطوع", "SETTINGS_MONITORS_NORMALIZE_DESC": "غالبًا ما يكون للشاشات نطاقات سطوع مختلفة. من خلال تحديد الحد الأدنى / الحد الأقصى للسطوع لكل شاشة ، تكون مستويات السطوع بين شاشات العرض أكثر اتساقًا. ستستخدم الشاشات المماثلة نفس الإعدادات.", "SETTINGS_MONITORS_DETAILS_NAME": "الاسم", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "الاسم الداخلي", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "طريقة التواصل", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "السطوع الحالي", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "اقصى سطوع", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "تطبيع السطوع", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "إخفاء الشاشة الداخلية غير النشطة", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "عند إغلاق الغطاء أو تعطيل الشاشة الداخلية في Windows ، قم بإخفاء شريط تمرير السطوع في اللوحة.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "اخفاء الشاشات", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "إذا كنت ترغب في إخفاء عروض معينة من القائمة المنبثقة ، فيمكنك تبديلها هنا.", "SETTINGS_FEATURES_DESCRIPTION": "قم بتمكين أو تعطيل ميزات DDC / CI المحددة في لوحة السطوع. يجب تمكين ميزة واحدة على الأقل حتى تظهر شاشتك في لوحة السطوع. لا تدعم جميع شاشات العرض هذه الميزات ، مثل شاشات الكمبيوتر المحمول / الكمبيوتر اللوحي.", "SETTINGS_FEATURES_UNSUPPORTED": "لا تدعم هذه الشاشة ميزات DDC / CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "الحصول على السطوع الحالي", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "احصل دائمًا على أحدث مستوى سطوع من الشاشة عند فتح صفحة السطوع. قم بتمكين هذا إذا كان السطوع يتغير بشكل متكرر من خارج توينكل تراي (مثل تطبيق آخر).", "SETTINGS_TIME_TITLE": "تعديلات الاوقات في اليوم", "SETTINGS_TIME_DESC": "اضبط شاشاتك تلقائيًا على مستوى سطوع معين في الوقت المطلوب. سيتم تعيين جميع الشاشات على نفس المستويات الطبيعية.", "SETTINGS_TIME_ADD": "اضفة وقت", "SETTINGS_TIME_REMOVE": "ازالة وقت", "SETTINGS_TIME_INDIVIDUAL_TITLE": "ضبط السطوع لشاشة منفردة", "SETTINGS_TIME_INDIVIDUAL_DESC": "قم بتكوين السطوع لكل شاشة بدلاً من جميع شاشات العرض مرة واحدة.", "SETTINGS_TIME_TRANSITON_TITLE": "سرعة انتقال السطوع", "SETTINGS_TIME_TRANSITON_DESC": "مدى سرعة انتقال السطوع عند تنشيط تعديلات الوقت في اليوم.", "SETTINGS_TIME_STARTUP_TITLE": "التفقد عن بداية البرنامج", "SETTINGS_TIME_STARTUP_DESC": "اضبط السطوع ليتناسب مع الوقت الأكثر صلة عندما يبدأ توينكل تراي.", "SETTINGS_TIME_IDLE_TITLE": "كشف الخمول", "SETTINGS_TIME_IDLE_DESC": "في حالة عدم اكتشاف أي إدخال لفترة من الوقت ، سيتم تقليل سطوع جميع شاشات العرض.", "SETTINGS_TIME_ANIMATE_TITLE": "التحريك بين التوقيتات", "SETTINGS_TIME_ANIMATE_DESC": "سيتم تحريك قيم السطوع بين الحدث المجدول الحالي والتالي. قد يزيد من استخدام وحدة المعالجة المركزية. ستتم الكتابة بسرعة فوق تعديلات السطوع اليدوية عندما يكون هذا نشطًا.", "SETTINGS_HOTKEYS_TITLE": "المفاتيح السريعة", "SETTINGS_HOTKEYS_DESC": "قم بتكوين مفاتيح الاختصار لضبط سطوع شاشة واحدة أو كلها.", "SETTINGS_HOTKEYS_ADD": "اضافة مفتاح اختصار", "SETTINGS_HOTKEYS_REMOVE": "ازالة مفتاح اختصار", "SETTINGS_HOTKEYS_INCREASE": "زيادة السطوع", "SETTINGS_HOTKEYS_DECREASE": "تقليل السطوع", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "اضغط الازرار هنا", "SETTINGS_HOTKEYS_LEVEL_TITLE": "ضبط مستوى السطوع", "SETTINGS_HOTKEYS_LEVEL_DESC": "كم يجب ضبط السطوع عند استخدام مفاتيح الاختصار.", "SETTINGS_HOTKEYS_TOD_TITLE": "ايقاف عمل الشاشات", "SETTINGS_HOTKEYS_TOD_DESC": "قم بتخصيص الإشارة المرسلة عند استخدام رمز أو مفتاح التشغيل السريع ايقاف الشاشات. ستعرض إشارة البرنامج شاشة سوداء حتى يكتشف Windows الإدخال (مثل الماوس أو لوحة المفاتيح). ستقوم إشارة الجهاز بإيقاف تشغيل الطاقة عن الشاشات.", "SETTINGS_HOTKEYS_TOD_NONE": "بلا (إخفاء الرمز)", "SETTINGS_HOTKEYS_TOD_SOFT": "إشارة البرنامج (افتراضي)", "SETTINGS_HOTKEYS_TOD_HARD": "*إشارة الأجهزة (DDC/CI فقط)", "SETTINGS_HOTKEYS_TOD_BOTH": "اشارة الاجهزة* و البرامج", "SETTINGS_HOTKEYS_TOD_NOTE": "*ملاحظة: ليست كل شاشات DDC / CI تدعم هذه الميزة.", "SETTINGS_HOTKEYS_BREAK_TITLE": "تعمل مفاتيح الاختصار على كسر المستويات المرتبطة", "SETTINGS_HOTKEYS_BREAK_DESC": "عند استخدام مفتاح التشغيل السريع لعرض واحد و \"المستويات المرتبطة \" نشطة ، سيتم إلغاء تنشيطه.", "SETTINGS_UPDATES_TITLE": "التحديثات", "SETTINGS_UPDATES_VERSION": "لديك توينكل تراي {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "الكشف التلقائي عن التحديثات", "SETTINGS_UPDATES_AUTOMATIC_DESC": "عندما يكون هناك إصدار جديد ، سيظهر في لوحة السطوع.", "SETTINGS_UPDATES_MS_STORE": "للتحقق من وجود إصدارات جديدة ، قم بزيارة تطبيق Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "يتوفر اصدار جديد من توينكل تراي", "SETTINGS_UPDATES_NONE_AVAILABLE": "حتى الآن. يتضمن الإصدار الحالي التغييرات التالية:", "SETTINGS_UPDATES_DOWNLOADING": "تحميل التحديثات…", "SETTINGS_UPDATES_DOWNLOAD": "تحميل و تثبيت {{1}}", "SETTINGS_UPDATES_CHANNEL": "تحديث القناة", "SETTINGS_UPDATES_BRANCH_STABLE": "ثابت (افتراضي)", "SETTINGS_UPDATES_BRANCH_BETA": "بيتا", "SETTINGS_FEATURES_POWER_OFF": "ايقاف الطاقة", "GENERIC_DELETE": "حذف", "GENERIC_DEFAULT": "الإفتراضي", "GENERIC_OPTIONAL": "اختياري", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "السطوع" } ================================================ FILE: src/localization/az.json ================================================ { "LANGUAGE": "Azərbaycan dili", "GENERIC_OK": "Tamam", "GENERIC_CANCEL": "Ləğv et", "GENERIC_SAVE": "Yadda saxla", "GENERIC_CLEAR": "Təmizlə", "GENERIC_OFF": "Bağla", "GENERIC_ON": "Açıq", "GENERIC_QUIT": "Çıxış", "GENERIC_CLOSE": "Bağla", "GENERIC_SETTINGS": "Sazlamalar", "GENERIC_INSTALL": "Yüklə", "GENERIC_DISMISS": "Rədd et", "GENERIC_DISPLAY_SINGLE": "Ekran", "GENERIC_ALL_DISPLAYS": "Bütün Ekranlar", "GENERIC_REFRESH_DISPLAYS": "Ekranları yenilə", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Maks", "GENERIC_NO_DISPLAYS": "Ekran tapılmadı. Zəhmət olmasa kompüterinizə bir ekran bağlayın.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Uyğun ekran tapılmadı. Zəhmət olmasa monitorunuzun sazlamalarında \"DDC/CI\" seçiminin aktiv olduğundan əmin olun.", "GENERIC_NO_DISPLAYS_SHORT": "Uyğun ekran tapılmadı.", "PANEL_TITLE": "Parlaqlıq Sazlaması", "PANEL_UPDATE_AVAILABLE": "Yeni versiya mövcuddur", "PANEL_BUTTON_LINK_LEVELS": "Səviyyələri eyniləşdir", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Ekranları bağla", "PANEL_LABEL_BRIGHTNESS": "Parlaqlıq", "PANEL_LABEL_CONTRAST": "Kontrast", "PANEL_LABEL_OFF_ON": "Enerji vəziyyəti", "PANEL_LABEL_COLOR_TEMPERATURE": "Rəng Temperaturu", "PANEL_LABEL_VOLUME": "Səs", "INTRO_TITLE": "Salam, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Twinkle Tray simvolunu daha əlçatan yerə köçürün. Təlimatlar üçün aşağıya baxın.", "SETTINGS_TITLE": "Twinkle Tray sazlamaları", "SETTINGS_SIDEBAR_GENERAL": "Ümumi", "SETTINGS_SIDEBAR_MONITORS": "Monitor Sazlamaları", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI Sazlamaları", "SETTINGS_SIDEBAR_TIME": "Zaman Sazlamaları", "SETTINGS_SIDEBAR_HOTKEYS": "Düymə & Qısayollar", "SETTINGS_SIDEBAR_UPDATES": "Yeniləmələr", "SETTINGS_GENERAL_TITLE": "Ümumi", "SETTINGS_GENERAL_STARTUP": "Başlanğıcda işə sal", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Başlanğıcda parlaqlığı tətbiq et", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Twinkle Tray başladılanda hər ekran üçün bilinən son parlaqlığı geri yükləsin.", "SETTINGS_GENERAL_THEME_TITLE": "Tema", "SETTINGS_GENERAL_THEME_SYSTEM": "Sistem seçimləri (Susmaya görə)", "SETTINGS_GENERAL_THEME_DARK": "Qara", "SETTINGS_GENERAL_THEME_LIGHT": "Ağ", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Dil", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Sistem dili (Susmaya görə)", "SETTINGS_GENERAL_RESET_TITLE": "Sazlamaları sıfırla", "SETTINGS_GENERAL_RESET_DESC": "Sazlamalarınızı təmizləmək üçün bu düyməyə basın.", "SETTINGS_GENERAL_RESET_BUTTON": "Sazlamaları sıfırla", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akril Bulanıqlığı", "SETTINGS_GENERAL_ACRYLIC_DESC": "Twinkle Tray-də şəffaf arxa planların arxasındakı bulanıqlılığı aktivləşdirin və ya deaktiv edin.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analitika", "SETTINGS_GENERAL_ANALYTICS_DESC": "Twinkle Tray-ı təkmilləşdirmək üçün istifadə məlumatlarını göndərin. Şəxsi məlumatlar göndərilmir. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Daha çox məlumat", "SETTINGS_GENERAL_SCROLL_TITLE": "Tray simvolu skrol qısayolu", "SETTINGS_GENERAL_SCROLL_DESC": "Tray simvolunda bütün ekranların parlaqlığını skrol edərək tənzimləyin. Bu, bəzi toxunmalı ekranlar(Trackpad və s.) ilə işləməyə bilər.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Tray simvolu", "SETTINGS_MONITORS_RATE_TITLE": "Parlaqlıq yeniləmə sürəti", "SETTINGS_MONITORS_RATE_DESC": "Parlaqlığı tənzimləyərkən yeniləmə tezliyi. Ekranda titrəmələr olursa bu vaxtı artırın.", "SETTINGS_MONITORS_RATE_0": "Gülməli", "SETTINGS_MONITORS_RATE_1": "Sürətli (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Yavaş (1 saniyə)", "SETTINGS_MONITORS_RATE_4": "Çox yavaş (2 saniyə)", "SETTINGS_MONITORS_RENAME_TITLE": "Monitorları Yenidən Adlandır", "SETTINGS_MONITORS_RENAME_DESC": "Hər bir monitor üçün fərqli ad daxil etmək istəsəniz, aşağıya daxil edə bilərsiniz. Boş buraxmaq əsl adı geri yükləyəcəkdir.", "SETTINGS_MONITORS_ENTER_NAME": "Ad daxil edin", "SETTINGS_MONITORS_REORDER_TITLE": "Monitorları yenidən sırala", "SETTINGS_MONITORS_REORDER_DESC": "Monitorların tray-də görünmə sırasını dəyişdirin. Dəyişiklik etmək üçün klikləyin və sürüşdürün.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Parlaqlığı Normallaşdır", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitorlar adətən fərqli parlaqlıq aralığına sahibdir. Hər ekran üçün minimum/maksimum parlaqlığı məhdudlaşdıraraq bu ekranlar arasındakı parlaqlıq səviyyələrini daha uyğun hala gətirə bilərsiniz. Oxşar monitorlar eyni parametrləri istifadə edir.", "SETTINGS_MONITORS_DETAILS_NAME": "Ad", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Daxili Ad", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Əlaqə metodu", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Cari Parlaqlıq", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maksimum Parlaqlıq", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Parlaqlıq Normallaşdırma", "SETTINGS_FEATURES_DESCRIPTION": "Parlaqlıq panelində müəyyən DDC/CI xüsusiyyətlərini aktivləşdirin və ya deaktiv edin. Monitorunuzun parlaqlıq panelində görünməsi üçün ən az bir xüsusiyyətin aktiv olması lazımdır. Bütün ekranlar bu xüsusiyyətləri dəstəkləməyə bilər (məsələn, noutbuk/tablet).", "SETTINGS_TIME_TITLE": "Günün Saat Sazlamaları", "SETTINGS_TIME_DESC": "Monitorlarınızı müəyyən bir vaxtda avtomatik olaraq müəyyən bir parlaqlıq səviyyəsinə təyin edin. Bütün monitorlar eyni, normallaşdırılmış səviyyələrə qurulacaq.", "SETTINGS_TIME_ADD": "Bir vaxt əlavə edin", "SETTINGS_TIME_REMOVE": "Vaxtı sil", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Fərqli ekranlar üçün parlaqlığı tənzimləyin", "SETTINGS_TIME_INDIVIDUAL_DESC": "Bütün ekranlar üçün eyni anda deyil, ekran başına parlaqlığı konfiqurasiya edin.", "SETTINGS_TIME_STARTUP_TITLE": "Tətbiq açılışında yoxlayın", "SETTINGS_TIME_STARTUP_DESC": "Twinkle Tray başladılanda parlaqlığı ən uyğun vaxtla tənzimləyin.", "SETTINGS_HOTKEYS_TITLE": "Qısa Yol Düymələri", "SETTINGS_HOTKEYS_DESC": "Ekran parlaqlığını tənzimləmək üçün qısa yol düymələrini konfiqurasiya edin.", "SETTINGS_HOTKEYS_ADD": "Qısayol düyməsi əlavə edin", "SETTINGS_HOTKEYS_REMOVE": "Qısayol düyməsini silin", "SETTINGS_HOTKEYS_INCREASE": "Parlaqlığı artır", "SETTINGS_HOTKEYS_DECREASE": "Parlaqlığı azaldın", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Burada düymələrə basın", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Parlaqlıq səviyyəsi tənzimləməsi", "SETTINGS_HOTKEYS_LEVEL_DESC": "Qısayol düymələrindən istifadə edərkən parlaqlığın tənzimləmə səviyyəsi.", "SETTINGS_HOTKEYS_TOD_TITLE": "Ekranları Söndür əməliyyatı", "SETTINGS_HOTKEYS_TOD_DESC": "Ekranları Söndür qısa yol düyməsindən və ya simvolundan istifadə edərkən göndərilən siqnalı fərdiləşdirin. Proqram siqnalı, giriş (məsələn, siçan və ya klaviatura) Windows tərəfindən aşkar edilənə qədər qara ekran göstərəcək. Aparat siqnalı monitorları söndürür.", "SETTINGS_HOTKEYS_TOD_NONE": "Yox (simvolu gizlə)", "SETTINGS_HOTKEYS_TOD_SOFT": "Proqram siqnalı (susmaya görə)", "SETTINGS_HOTKEYS_TOD_HARD": "Aparat* siqnalı (yalnız DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Aparat* və proqram siqnalı", "SETTINGS_HOTKEYS_TOD_NOTE": "*Qeyd: Bütün DDC/CI monitorlar bu xüsusiyyəti dəstəkləmir.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Qısayol düymələri bağlantılı səviyyələri qırır", "SETTINGS_HOTKEYS_BREAK_DESC": "Tək bir ekran üçün bir qısa yol düyməsi istifadə edildikdə və \"bağlı səviyyələr\" aktiv olduqda, bu deaktiv ediləcək.", "SETTINGS_UPDATES_TITLE": "Yeniləmələr", "SETTINGS_UPDATES_VERSION": "Mövcud Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Yeni versiyaları avtomatik yoxla", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Yeni bir versiya mövcud olduqda parlaqlıq panelində görünsün.", "SETTINGS_UPDATES_MS_STORE": "Yeni versiyaları yoxlamaq üçün Microsoft Store tətbiqini ziyarət edin.", "SETTINGS_UPDATES_AVAILABLE": "Twinkle Tray-in yeni versiyası mövcuddur!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Aktualdır. Cari versiya aşağıdakı dəyişiklikləri əhatə edir:", "SETTINGS_UPDATES_DOWNLOADING": "Yeniləmə yüklənilir...", "SETTINGS_UPDATES_DOWNLOAD": "{{1}} Yüklə və Quraşdır", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Twinkle Tray tray simvoluna klikləyərkən cavab vermirsə və ya ekranlarınızı aşkar edə bilmirsə, müəyyən monitor aşkar etmə üsullarını deaktiv etməyə cəhd edə bilərsiniz. Dəyişikliklərin effektiv olması üçün Twinkle Tray-i yenidən başladın. {{1}}", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Aktiv olmayan daxili ekranı gizlədin", "SETTINGS_GENERAL_MICA_TITLE": "Mika Bulanıklığı", "SETTINGS_GENERAL_MICA_DESC": "Twinkle Tray-də arxa planların arxasındakı bulanıqlığı aktiv edin və ya deaktiv edin.", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Qapaq bağlı ikən və ya daxili ekran Windows-da deaktiv edildikdə, paneldəki parlaqlıq tənzimləyicisini gizlədin.", "SETTINGS_FEATURES_UNSUPPORTED": "Bu monitor DDC/CI xüsusiyyətlərini dəstəkləmir.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Cari Parlaqlığı Al", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Parlaqlıq səhifəsini açarkən həmişə monitordan ən son parlaqlıq səviyyəsini alın. Parlaqlıq tez-tez Twinkle Tray xaricində dəyişdirilirsə (məsələn, başqa bir tətbiq), bunu aktiv edin.", "GENERIC_MINUTES": "dəqiqə", "GENERIC_SECONDS": "saniyə", "SETTINGS_TIME_IDLE_TITLE": "Boş vaxtı aşkarlama", "PANEL_LABEL_TURN_OFF": "Enerji bağlıdır", "SETTINGS_TIME_IDLE_DESC": "Müəyyən bir müddət ərzində heç bir giriş aşkarlanmadıqda, bütün ekranların parlaqlığı azalacaq.", "GENERIC_PAUSE_TOD": "Vaxt tənzimləmələrini dayandır", "GENERIC_PAUSE_IDLE": "Boş vaxtın aşkarlanmasını dayandır", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Monitor aşkar etmə üsullarını deaktiv et", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Yer paylaşımını deaktiv et", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Əgər Twinkle Tray-in qısa yol sazlaması tam ekran tətbiqlərə mane olursa, onu buradan deaktiv edə bilərsiniz.", "SETTINGS_TIME_TRANSITON_TITLE": "Parlaqlığın keçid sürəti", "SETTINGS_TIME_TRANSITON_DESC": "Günün saat parametrləri aktivləşdirildikdə parlaqlığın keçid sürəti.", "SETTINGS_TIME_ANIMATE_TITLE": "Zamanlar arasında animasiya", "SETTINGS_TIME_ANIMATE_DESC": "Parlaqlıq dəyərləri mövcud və növbəti planlaşdırılmış hadisə arasında animasiya ediləcək. CPU istifadəsini artıra bilər. Bu aktiv olduqda manual parlaqlıq parametrləri tez bir şəkildə üzərinə yazılacaq.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Ekranları Gizlət", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Müəyyən ekranları açılan menyudan gizlətmək istəyirsinizsə, onları buradan gizlədə bilərsiniz.", "GENERIC_SPEED_INSTANT": "Ani", "GENERIC_SPEED_SLOW": "Yavaş", "GENERIC_SPEED_VERY_SLOW": "Çox yavaş", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_DDC_WARNING": "Enerji vəziyyətini yoxlama kimi DDC/CI xüsusiyyətləri monitorunuzun cavab verməməsinə səbəb ola bilər. İstifadə riski sizə aiddir.", "GENERIC_SPEED_FAST": "Sürətli", "GENERIC_SPEED_VERY_FAST": "Çox sürətli", "SETTINGS_GENERAL_TROUBLESHOOTING": "Problem Həll Edilməsi", "SETTINGS_UPDATES_CHANNEL": "Yeniləmə kanalı", "SETTINGS_UPDATES_BRANCH_STABLE": "Sabit (susmaya görə)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Enerji bağlıdır", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Parlaqlıq" } ================================================ FILE: src/localization/bn.json ================================================ { "LANGUAGE": "ইংরেজি", "GENERIC_OK": "ঠিক আছে", "GENERIC_CANCEL": "বাতিল করুন", "GENERIC_SAVE": "সংরক্ষণ করুন", "GENERIC_CLEAR": "পরিষ্কার", "GENERIC_OFF": "বন্ধ", "GENERIC_ON": "চালু", "GENERIC_QUIT": "প্রস্থান করুন", "GENERIC_CLOSE": "বন্ধ করুণ", "GENERIC_SETTINGS": "সেটিংস", "GENERIC_INSTALL": "ইনস্টল করুন", "GENERIC_DISMISS": "খারিজ", "GENERIC_DISPLAY_SINGLE": "ডিসপ্লে", "GENERIC_ALL_DISPLAYS": "সমস্ত ডিসপ্লে", "GENERIC_REFRESH_DISPLAYS": "ডিসপ্লে রিফ্রেশ করুন", "GENERIC_MINIMUM": "সর্বনিম্ন", "GENERIC_MAXIMUM": "সর্বোচ্চ", "GENERIC_NO_DISPLAYS": "কোনো ডিসপ্লে সনাক্ত করা যায়নি। আপনার পিসিতে একটি ডিসপ্লে সংযোগ করুন.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "কোন সামঞ্জস্যপূর্ণ ডিসপ্লে পাওয়া যায়নি. আপনার ডিসপ্লেগুলির জন্য \"DDC/CI\" সক্ষম করা আছে কিনা তা পরীক্ষা করুন৷", "GENERIC_NO_DISPLAYS_SHORT": "কোনো সামঞ্জস্যপূর্ণ ডিসপ্লে সনাক্ত করা যায়নি.", "GENERIC_SECONDS": "সেকেন্ড", "GENERIC_MINUTES": "মিনিট", "PANEL_TITLE": "উজ্জ্বলতা নিয়ন্ত্রণ", "PANEL_UPDATE_AVAILABLE": "নতুন সংস্করণ উপলব্ধ রয়েছে", "PANEL_BUTTON_LINK_LEVELS": "লিঙ্ক স্তর", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "ডিসপ্লেগুলো বন্ধ করুন", "PANEL_LABEL_BRIGHTNESS": "উজ্জ্বলতা", "PANEL_LABEL_CONTRAST": "বৈপরীত্য", "PANEL_LABEL_OFF_ON": "পাওয়ারের অবস্থা", "PANEL_LABEL_COLOR_TEMPERATURE": "কালার টেম্পারেচার", "PANEL_LABEL_VOLUME": "ভলিউম", "PANEL_LABEL_TURN_OFF": "বন্ধ করুন", "INTRO_TITLE": "হ্যালো, Twinkle Tray!", "INTRO_INSTRUCTIONS": "টুইঙ্কল ট্রে-র ট্রে আইকনটি সম্ভবত লুকানো আছে, তাই আপনার এটিকে এমন জায়গায় নিয়ে যাওয়া উচিত যেখানে আপনি সহজেই এটি অ্যাক্সেস করতে পারেন। নির্দেশাবলীর জন্য নীচে দেখুন.", "SETTINGS_TITLE": "টুইঙ্কল ট্রে সেটিংস", "SETTINGS_SIDEBAR_GENERAL": "সাধারণ", "SETTINGS_SIDEBAR_MONITORS": "মনিটর সেটিংস", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI বৈশিষ্ট্য", "SETTINGS_SIDEBAR_TIME": "সময় সমন্বয়", "SETTINGS_SIDEBAR_HOTKEYS": "হটকি এবং শর্টকাট", "SETTINGS_SIDEBAR_UPDATES": "আপডেট", "SETTINGS_GENERAL_TITLE": "সাধারণ", "SETTINGS_GENERAL_STARTUP": "স্টার্টআপে লঞ্চ করুন", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "স্টার্টআপে উজ্জ্বলতা প্রয়োগ করুন", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "টুইঙ্কল ট্রে শুরু হলে প্রতিটি ডিসপ্লের জন্য সর্বশেষ পরিচিত উজ্জ্বলতা পুনরুদ্ধার করুন।", "SETTINGS_GENERAL_THEME_TITLE": "থিম", "SETTINGS_GENERAL_THEME_SYSTEM": "সিস্টেম পছন্দ (ডিফল্ট)", "SETTINGS_GENERAL_THEME_DARK": "অন্ধকার", "SETTINGS_GENERAL_THEME_LIGHT": "আলো", "SETTINGS_GENERAL_LANGUAGE_TITLE": "ভাষা", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "সিস্টেম ভাষা (ডিফল্ট)", "SETTINGS_GENERAL_RESET_TITLE": "রিসেট সেটিংস", "SETTINGS_GENERAL_RESET_DESC": "আপনার কনফিগারেশন সাফ করতে এই বোতাম টিপুন।", "SETTINGS_GENERAL_RESET_BUTTON": "রিসেট সেটিংস", "SETTINGS_GENERAL_ACRYLIC_TITLE": "এক্রাইলিক ব্লার", "SETTINGS_GENERAL_ACRYLIC_DESC": "টুইঙ্কল ট্রেতে স্বচ্ছ ব্যাকগ্রাউন্ডের পিছনের অস্পষ্টতা সক্ষম বা অক্ষম করুন।", "SETTINGS_GENERAL_MICA_TITLE": "মাইকা ব্লার", "SETTINGS_GENERAL_MICA_DESC": "টুইঙ্কল ট্রেতে ব্যাকগ্রাউন্ডের পিছনের অস্পষ্টতা সক্ষম বা অক্ষম করুন।", "SETTINGS_GENERAL_ANALYTICS_TITLE": "বিশ্লেষণ", "SETTINGS_GENERAL_ANALYTICS_DESC": "টুইঙ্কল ট্রে উন্নত করতে সাহায্য করার জন্য ব্যবহার ডেটা পাঠান। কোন ব্যক্তিগত তথ্য পাঠানো হয় না. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "আরও জানুন", "SETTINGS_GENERAL_SCROLL_TITLE": "ট্রে আইকন স্ক্রোল শর্টকাট", "SETTINGS_GENERAL_SCROLL_DESC": "সিস্টেম ট্রে আইকনে স্ক্রোল করে একবারে সমস্ত ডিসপ্লের উজ্জ্বলতা সামঞ্জস্য করুন। এটি কিছু ট্র্যাকপ্যাডের সাথে কাজ করে না।", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "ট্রে আইকন", "SETTINGS_MONITORS_RATE_TITLE": "উজ্জ্বলতা আপডেট হার", "SETTINGS_MONITORS_RATE_DESC": "আপনি যখন তাদের মানগুলি সামঞ্জস্য করছেন তখন আপনার ডিসপ্লেতে কত ঘন ঘন উজ্জ্বলতা আপডেট হবে। আপনার ডিসপ্লে চকচকে হলে সময় বাড়ান।", "SETTINGS_MONITORS_RATE_0": "হাস্যকর", "SETTINGS_MONITORS_RATE_1": "দ্রুত (250 ms)", "SETTINGS_MONITORS_RATE_2": "সাধারণ (500 ms)", "SETTINGS_MONITORS_RATE_3": "ধীর (1 সেকেন্ড)", "SETTINGS_MONITORS_RATE_4": "খুব ধীর (2 সেকেন্ড)", "SETTINGS_MONITORS_RENAME_TITLE": "মনিটরের নাম পরিবর্তন করুন", "SETTINGS_MONITORS_RENAME_DESC": "আপনি যদি প্রতিটি মনিটরের জন্য আলাদা নাম পছন্দ করেন (যেমন \"বাম মনিটর\", \"মিডল মনিটর\"), আপনি এটি নীচে লিখতে পারেন। ক্ষেত্রটি খালি রেখে আসল নামটি পুনরুদ্ধার করবে।", "SETTINGS_MONITORS_ENTER_NAME": "রত", "SETTINGS_MONITORS_REORDER_TITLE": "মনিটর পুনরায় সাজান", "SETTINGS_MONITORS_REORDER_DESC": "মনিটরগুলি ট্রেতে প্রদর্শিত হয় এমন ক্রম পরিবর্তন করুন। পরিবর্তন করতে ক্লিক করুন এবং টেনে আনুন।", "SETTINGS_MONITORS_NORMALIZE_TITLE": "উজ্জ্বলতা স্বাভাবিক করুন", "SETTINGS_MONITORS_NORMALIZE_DESC": "মনিটর প্রায়ই বিভিন্ন উজ্জ্বলতা পরিসীমা আছে. প্রতি ডিসপ্লেতে সর্বনিম্ন/সর্বোচ্চ উজ্জ্বলতা সীমিত করে, ডিসপ্লেগুলির মধ্যে উজ্জ্বলতার মাত্রা অনেক বেশি সামঞ্জস্যপূর্ণ। অনুরূপ মনিটর একই সেটিংস ব্যবহার করবে।", "SETTINGS_MONITORS_DETAILS_NAME": "নাম", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "অভ্যন্তরীণ নাম", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "যোগাযোগ পদ্ধতি", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "বর্তমান উজ্জ্বলতা", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "সর্বোচ্চ উজ্জ্বলতা", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "উজ্জ্বলতা স্বাভাবিককরণ", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "নিষ্ক্রিয় অভ্যন্তরীণ ডিসপ্লে লুকান", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "যখন ঢাকনা বন্ধ থাকে বা উইন্ডোজে অভ্যন্তরীণ প্রদর্শন অক্ষম করা হয়, তখন প্যানেলে উজ্জ্বলতা স্লাইডারটি লুকান।", "SETTINGS_FEATURES_DESCRIPTION": "উজ্জ্বলতা প্যানেলে নির্দিষ্ট DDC/CI বৈশিষ্ট্যগুলি সক্ষম বা অক্ষম করুন৷ আপনার মনিটরের উজ্জ্বলতা প্যানেলে দেখানোর জন্য অন্তত একটি বৈশিষ্ট্য সক্রিয় করা আবশ্যক। সমস্ত ডিসপ্লে এই বৈশিষ্ট্যগুলিকে সমর্থন করে না, যেমন ল্যাপটপ/ট্যাবলেট প্রদর্শন।", "SETTINGS_FEATURES_UNSUPPORTED": "এই মনিটর DDC/CI বৈশিষ্ট্য সমর্থন করে না।", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "বর্তমান উজ্জ্বলতা পান", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "উজ্জ্বলতা পৃষ্ঠা খোলার সময় সর্বদা মনিটর থেকে সর্বশেষ উজ্জ্বলতা স্তর পান। Twinkle Tray (যেমন অন্য অ্যাপ্লিকেশন) এর বাইরে থেকে উজ্জ্বলতা ঘন ঘন পরিবর্তন হলে এটি সক্ষম করুন।", "SETTINGS_TIME_TITLE": "দিনের সামঞ্জস্যের সময়", "SETTINGS_TIME_DESC": "স্বয়ংক্রিয়ভাবে একটি পছন্দসই সময়ে একটি নির্দিষ্ট উজ্জ্বলতা স্তরে আপনার মনিটর সেট করুন। সমস্ত মনিটর একই, স্বাভাবিক স্তরে সেট করা হবে।", "SETTINGS_TIME_ADD": "একটি সময় যোগ করুন", "SETTINGS_TIME_REMOVE": "সময় সরান", "SETTINGS_TIME_INDIVIDUAL_TITLE": "পৃথক প্রদর্শনের জন্য উজ্জ্বলতা সেট করুন", "SETTINGS_TIME_INDIVIDUAL_DESC": "একযোগে সমস্ত প্রদর্শনের পরিবর্তে প্রতি প্রদর্শনের উজ্জ্বলতা কনফিগার করুন।", "SETTINGS_TIME_STARTUP_TITLE": "অ্যাপ স্টার্টআপে পরীক্ষা করুন", "SETTINGS_TIME_STARTUP_DESC": "টুইঙ্কল ট্রে শুরু হওয়ার সময় সবচেয়ে প্রাসঙ্গিক সময়ের সাথে মেলে উজ্জ্বলতা সামঞ্জস্য করুন।", "SETTINGS_TIME_IDLE_TITLE": "নিষ্ক্রিয় সনাক্তকরণ", "SETTINGS_TIME_IDLE_DESC": "যখন নির্দিষ্ট সময়ের জন্য কোনো ইনপুট সনাক্ত করা যায় না, তখন সমস্ত প্রদর্শনের উজ্জ্বলতা হ্রাস পাবে।", "SETTINGS_HOTKEYS_TITLE": "হটকি", "SETTINGS_HOTKEYS_DESC": "এক বা সমস্ত প্রদর্শনের উজ্জ্বলতা সামঞ্জস্য করতে হটকিগুলি কনফিগার করুন৷", "SETTINGS_HOTKEYS_ADD": "হটকি যোগ করুন", "SETTINGS_HOTKEYS_REMOVE": "হটকি সরান", "SETTINGS_HOTKEYS_INCREASE": "উজ্জ্বলতা বাড়ান", "SETTINGS_HOTKEYS_DECREASE": "উজ্জ্বলতা হ্রাস", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "এখানে কী টিপুন", "SETTINGS_HOTKEYS_LEVEL_TITLE": "উজ্জ্বলতা স্তর সমন্বয়", "SETTINGS_HOTKEYS_LEVEL_DESC": "হটকি ব্যবহার করার সময় উজ্জ্বলতা কতটা সামঞ্জস্য করা উচিত।", "SETTINGS_HOTKEYS_TOD_TITLE": "ডিসপ্লে অ্যাকশন বন্ধ করুন", "SETTINGS_HOTKEYS_TOD_DESC": "টার্ন অফ ডিসপ্লে হটকি বা আইকন ব্যবহার করার সময় প্রেরিত সংকেত কাস্টমাইজ করুন। সফ্টওয়্যার সংকেত একটি কালো পর্দা প্রদর্শন করবে যতক্ষণ না ইনপুট (উদাঃ মাউস বা কীবোর্ড) উইন্ডোজ দ্বারা সনাক্ত করা হয়। হার্ডওয়্যার সংকেত মনিটরগুলিতে পাওয়ার বন্ধ করে দেবে।", "SETTINGS_HOTKEYS_TOD_NONE": "কোনটিই নয় (আইকন লুকান)", "SETTINGS_HOTKEYS_TOD_SOFT": "সফ্টওয়্যার সংকেত (ডিফল্ট)", "SETTINGS_HOTKEYS_TOD_HARD": "হার্ডওয়্যার* সংকেত (শুধুমাত্র DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "হার্ডওয়্যার* এবং সফ্টওয়্যার সংকেত", "SETTINGS_HOTKEYS_TOD_NOTE": "*দ্রষ্টব্য: সমস্ত DDC/CI মনিটর এই বৈশিষ্ট্যটিকে সমর্থন করে না।", "SETTINGS_HOTKEYS_BREAK_TITLE": "হটকিগুলি সংযুক্ত স্তরগুলি ভেঙে দেয়", "SETTINGS_HOTKEYS_BREAK_DESC": "যখন একটি একক প্রদর্শনের জন্য একটি হটকি ব্যবহার করা হয় এবং \"লিঙ্কড লেভেল\" সক্রিয় থাকে, তখন এটি নিষ্ক্রিয় করা হবে।", "SETTINGS_UPDATES_TITLE": "আপডেট", "SETTINGS_UPDATES_VERSION": "আপনার কাছে টুইঙ্কল ট্রে {{1}} আছে।", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "স্বয়ংক্রিয়ভাবে নতুন সংস্করণের জন্য পরীক্ষা করুন", "SETTINGS_UPDATES_AUTOMATIC_DESC": "যখন একটি নতুন সংস্করণ আছে, এটি উজ্জ্বলতা প্যানেলে প্রদর্শিত হবে।", "SETTINGS_UPDATES_MS_STORE": "নতুন সংস্করণ পরীক্ষা করতে, Microsoft স্টোর অ্যাপে যান।", "SETTINGS_UPDATES_AVAILABLE": "টুইঙ্কল ট্রে এর নতুন সংস্করণ উপলব্ধ!", "SETTINGS_UPDATES_NONE_AVAILABLE": "আপ টু ডেট বর্তমান সংস্করণে নিম্নলিখিত পরিবর্তনগুলি অন্তর্ভুক্ত রয়েছে:", "SETTINGS_UPDATES_DOWNLOADING": "আপডেট ডাউনলোড হচ্ছে…", "SETTINGS_UPDATES_DOWNLOAD": "ডাউনলোড এবং ইনস্টল করুন {{1}}", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "ট্রে আইকনে ক্লিক করার সময় বা আপনার ডিসপ্লে সনাক্ত না করার সময় যদি টুইঙ্কল ট্রে অপ্রতিক্রিয়াশীল হয়, আপনি কিছু মনিটর সনাক্তকরণ পদ্ধতি অক্ষম করার চেষ্টা করতে পারেন। পরিবর্তনগুলি কার্যকর হওয়ার জন্য টুইঙ্কল ট্রে পুনরায় চালু করুন৷ {{1}}", "GENERIC_PAUSE_TOD": "সময় সামঞ্জস্য বিরতি", "GENERIC_PAUSE_IDLE": "নিষ্ক্রিয় সনাক্তকরণ বিরাম দিন", "SETTINGS_GENERAL_TROUBLESHOOTING": "সমস্যা সমাধান", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "ওভারলে অক্ষম করুন", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "যদি টুইঙ্কল ট্রে-এর হটকি ওভারলে ফুলস্ক্রিন অ্যাপ্লিকেশনগুলিতে হস্তক্ষেপ করে, আপনি এটি এখানে নিষ্ক্রিয় করতে পারেন।", "SETTINGS_TIME_TRANSITON_TITLE": "উজ্জ্বলতা স্থানান্তর গতি", "SETTINGS_TIME_TRANSITON_DESC": "দিনের সময় সামঞ্জস্য সক্রিয় করা হলে উজ্জ্বলতা কত দ্রুত পরিবর্তন করা উচিত।", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "প্রদর্শন লুকান", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "আপনি যদি ফ্লাইআউট থেকে নির্দিষ্ট ডিসপ্লেগুলি লুকাতে চান, আপনি সেগুলিকে এখানে টগল করতে পারেন৷", "SETTINGS_TIME_ANIMATE_TITLE": "সময়ের মধ্যে অ্যানিমেট করুন", "SETTINGS_TIME_ANIMATE_DESC": "উজ্জ্বলতার মান বর্তমান এবং পরবর্তী নির্ধারিত ইভেন্টের মধ্যে অ্যানিমেটেড করা হবে। CPU ব্যবহার বাড়াতে পারে। এটি সক্রিয় থাকাকালীন ম্যানুয়াল উজ্জ্বলতা সামঞ্জস্যগুলি দ্রুত ওভাররাইট করা হবে৷", "GENERIC_SPEED_INSTANT": "তাৎক্ষণিক", "GENERIC_SPEED_SLOW": "ধীর", "GENERIC_SPEED_VERY_SLOW": "খুব ধীর", "GENERIC_SPEED_NORMAL": "স্বাভাবিক", "GENERIC_SPEED_FAST": "দ্রুত", "GENERIC_SPEED_VERY_FAST": "খুব দ্রুত", "GENERIC_DDC_WARNING": "ডিডিসি/সিআই বৈশিষ্ট্য যেমন পাওয়ার স্টেট নিয়ন্ত্রণ করা আপনার মনিটরকে প্রতিক্রিয়াহীন হতে পারে। আপনার নিজের ঝুঁকিতে ব্যবহার করুন।", "SETTINGS_UPDATES_BRANCH_STABLE": "স্থিতিশীল (ডিফল্ট)", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "মনিটর সনাক্তকরণ পদ্ধতি অক্ষম করুন", "SETTINGS_UPDATES_CHANNEL": "চ্যানেল আপডেট করুন", "SETTINGS_UPDATES_BRANCH_BETA": "বেটা", "SETTINGS_FEATURES_POWER_OFF": "বন্ধ করুন" } ================================================ FILE: src/localization/ckb.json ================================================ { "LANGUAGE": "کوردی (ناوەندی)", "GENERIC_OK": "باشە", "GENERIC_CANCEL": "هەڵوەشاندنەوە", "GENERIC_SAVE": "پاشەکەوتکردن", "GENERIC_CLEAR": "پاککردن", "GENERIC_OFF": "ناچالاک", "GENERIC_ON": "چالاک", "GENERIC_QUIT": "چوونەدەرەوە", "GENERIC_CLOSE": "داخستن", "GENERIC_SETTINGS": "ڕێکخستنەکان", "GENERIC_INSTALL": "دامەزراندن", "GENERIC_DISMISS": "لابردن", "GENERIC_DISPLAY_SINGLE": "پیشاندان", "GENERIC_ALL_DISPLAYS": "هەموو پیشاندانەکان", "GENERIC_REFRESH_DISPLAYS": "پیشاندانەکان نوێ بکەرەوە", "GENERIC_MINIMUM": "کەمترین", "GENERIC_MAXIMUM": "زۆرترین", "GENERIC_NO_DISPLAYS": "هیچ پیشاندانێک نەدۆزرایەوە. تکایە پیشاندانێک پەیوەست بکە بە کۆمپیوتەرەکەتەوە.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "هیچ شاشەیەکی گونجاو نەدۆزرایەوە. تکایە دڵنیابەرەوە کە «DDC/CI» بۆ شاشەکانت کارا کراوە.", "GENERIC_NO_DISPLAYS_SHORT": "هیچ شاشەیەکی گونجاو نەدۆزرایەوە.", "GENERIC_SECONDS": "چرکە", "GENERIC_MINUTES": "خولەک", "GENERIC_DDC_WARNING": "تایبەتمەندییەکانی DDC/CI وەک کۆنتڕۆڵکردنی ئاستی وزە دەتوانێت وا لە مۆنیتەرەکەت بکات کە لەکار بکەوێت. ئاگادار بە لە بەکارھێنانی.", "GENERIC_SPEED_INSTANT": "دەستبەجێ", "GENERIC_SPEED_SLOW": "خاو", "GENERIC_SPEED_VERY_SLOW": "زۆر خاو", "GENERIC_SPEED_NORMAL": "ئاسایی", "GENERIC_SPEED_FAST": "خێرا", "GENERIC_SPEED_VERY_FAST": "زۆر خێرا", "GENERIC_PAUSE_TOD": "ڕێکخستنەکانی کات ڕابگرە", "GENERIC_PAUSE_IDLE": "دۆزینەوەی ئایدڵ ڕابگرە", "PANEL_TITLE": "ڕێکخستنەکانی ڕووناکی", "PANEL_UPDATE_AVAILABLE": "وەشانێکی نوێ بەردەستە", "PANEL_BUTTON_LINK_LEVELS": "ئاستەکان ببەستەرەوە", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "شاشەکان بکوژێنەوە", "PANEL_LABEL_BRIGHTNESS": "ڕووناکی", "PANEL_LABEL_CONTRAST": "کۆنتراست", "PANEL_LABEL_OFF_ON": "ئاستی وزە", "PANEL_LABEL_COLOR_TEMPERATURE": "پلەی ڕەنگ", "PANEL_LABEL_VOLUME": "دەنگ", "PANEL_LABEL_TURN_OFF": "بیکوژێنەرەوە", "INTRO_TITLE": "سڵاو، توینکڵ ترەی!", "INTRO_INSTRUCTIONS": "ئایکۆنی بچووکی توینکڵ ترەی لەوانەیە شارابێتەوە، بۆیە باشترە بیخەیتە شوێنێکەوە کە بە ئاسای دەستت پێی بگات. ڕێنماییەکانی خوارەوە ببینە.", "SETTINGS_TITLE": "ڕێکخستنەکانی توینکڵ ترەی", "SETTINGS_SIDEBAR_GENERAL": "گشتی", "SETTINGS_SIDEBAR_MONITORS": "ڕێکخستنەکانی مۆنیتەر", "SETTINGS_SIDEBAR_FEATURES": "تایبەتمەندییەکانی DDC/CI", "SETTINGS_SIDEBAR_TIME": "ڕێکخستنەکانی کات", "SETTINGS_SIDEBAR_HOTKEYS": "قەدبڕەکان", "SETTINGS_SIDEBAR_UPDATES": "نوێکردنەوەکان", "SETTINGS_GENERAL_TITLE": "گشتی", "SETTINGS_GENERAL_STARTUP": "لەگەڵ داگیرساندا کارا ببە", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "ڕووناکی لەگەڵ داگیرساندا بەکار بکە", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "کۆتا ڕووناکیی زاندراو بھێنەرەوە بۆ هەریەکە لە شاشەکان کاتێک توینکڵ ترەی دەکرێتەوە.", "SETTINGS_GENERAL_THEME_TITLE": "شێواز", "SETTINGS_GENERAL_THEME_SYSTEM": "ھەڵبژاردەکانی سیستەم (بنچینەیی)", "SETTINGS_GENERAL_THEME_DARK": "تاریک", "SETTINGS_GENERAL_THEME_LIGHT": "ڕووناک", "SETTINGS_GENERAL_LANGUAGE_TITLE": "زمان", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "زمانی سیستەم (بنچینەیی)", "SETTINGS_GENERAL_RESET_TITLE": "لابردنی ڕێکخستنەکان", "SETTINGS_GENERAL_RESET_DESC": "کلیک لێرە بکە بۆ سڕینەوەی شێوەپێدانەکانت.", "SETTINGS_GENERAL_RESET_BUTTON": "لابردنی ڕێکخستنەکان", "SETTINGS_GENERAL_ACRYLIC_TITLE": "تەڵخیی ئاکریلیک", "SETTINGS_GENERAL_ACRYLIC_DESC": "تەڵخیی پشت باکگراوندە ڕوونەکان چالاک یان ناچالاک بکە لە توینکڵ ترەیدا.", "SETTINGS_GENERAL_MICA_TITLE": "تەڵخیی میکا", "SETTINGS_GENERAL_MICA_DESC": "تەڵخیی پشت باکگراوندەکان چالاک یان ناچالاک بکە لە توینکڵ ترەیدا.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "ئامارەکان", "SETTINGS_GENERAL_ANALYTICS_DESC": "زانیاریی بەکارهێنان بنێرە بۆ باشترکردنی توینکڵ تری. هیچ زانیارییەکی کەسی نانێردرێت. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "زیاتر بزانە", "SETTINGS_GENERAL_SCROLL_TITLE": "قەدبڕی کێشانی ئایکۆنی بەرکەش", "SETTINGS_GENERAL_SCROLL_DESC": "ڕووناکیی هەموو شاشەکان دیاری بکە بە یەک جار بە کێشان لەسەر ئایکۆنی بەرکەشی سیستەم. ئەمە لەگەڵ هەندێک ماوسدا کار ناکات.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "ئایکۆنی بەرکەش", "SETTINGS_GENERAL_TROUBLESHOOTING": "کێشەڕەوێنی", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "شێوازەکانی دۆزینەوەی مۆنیتەرەکان چالاک بکە", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "ئەگەر توینکڵ ترەی ناکارا بوو لەکاتی کلیککردن لە ئایکۆنی بەرکەش یان شاشەکانت نادۆزێتەوە، دەتوانیت هەندێک لە شێوازەکانی دۆزینەوەی مۆنیتەر ناچالاک بکەیت. توینکڵ ترەی دابخە و بیکەرەوە بۆ بینینی کاریگەرییەکان. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "ئۆڤەرلەی ناچالاک بکە", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "ئەگەر ئۆڤەرلەیی قەدبڕئ توینکڵ ترەی کێشە لەگەڵ بەرنامە فووڵسکرینەکاندا دروست دەکات، دەتوانیت لێرەوە ناچالاکی بکەیت.", "SETTINGS_MONITORS_RATE_TITLE": "ڕێژەی نوێکردنەوەی ڕووناکی", "SETTINGS_MONITORS_RATE_DESC": "چەنێک ڕووناکیی شاشەکە نوێ دەبێتەوە کاتێک بڕەکانیان دیاری دەکەیت. کاتەکەی زیاد بکە ئەگەر شاشەکانت پرتەپرت دەکەن.", "SETTINGS_MONITORS_RATE_0": "خەیاڵی", "SETTINGS_MONITORS_RATE_1": "خێرا (٢٥٠ مچ)", "SETTINGS_MONITORS_RATE_2": "ئاسایی (٥٠٠ مچ)", "SETTINGS_MONITORS_RATE_3": "خاو (١ چرکە)", "SETTINGS_MONITORS_RATE_4": "زۆر خاو (٢ چرکە)", "SETTINGS_MONITORS_RENAME_TITLE": "ناوگۆڕیی مۆنیتەرەکان", "SETTINGS_MONITORS_RENAME_DESC": "ئەگەر حەز دەکەیت ناوی جیاواز بۆ مۆنیتەرەکان دابنێیت (بۆ نموونە «مۆنیتەری چەپ»، «مۆنیتەری ناوەڕاست»)، دەتوابیت لە خوارەوە بینوسیت. ئەگەر خانەکە بە بەتاڵی جێبھێڵیت، ئەوا ناوەکەی دەگەڕێتەوە بۆ ناوە بنچینەییەکەی خۆی.", "SETTINGS_MONITORS_ENTER_NAME": "ناوێک بنووسە", "SETTINGS_MONITORS_REORDER_TITLE": "مۆنیتەرەکان ڕیز بکەرەوە", "SETTINGS_MONITORS_REORDER_DESC": "ڕیزبەندیی ئەو مۆنیتەرانە بگۆڕە کە لە ترەیەکەدا پیشان دراون. کلیک بکە و ڕایانبکێشە بۆ گۆڕانکاری.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "ڕووناکی ئاسایی بکەرەوە", "SETTINGS_MONITORS_NORMALIZE_DESC": "", "SETTINGS_MONITORS_DETAILS_NAME": "ناو", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "ناوی ناوەکی", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "شێوازی پەیوەندیکردن", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "دوایین ڕووناکی", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "بەرزترین ڕووناکی", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "ئاساییکردنەوەی ڕووناکی", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "شاشە ناچالاکە ناوەکییەکان بشارەوە", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "شاشەکان بشارەوە", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "", "SETTINGS_FEATURES_DESCRIPTION": "", "SETTINGS_FEATURES_UNSUPPORTED": "ئەک مۆنیتەرە پاڵپشتیی تایبەتمەندییەکانی DDC/CI ناکات.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "دوایین ڕووناکی بەدەست بھێنە", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "هەمیشە دوایین ئاستی ڕووناکی لە مۆنیتەرەکەوە بھێنە کاتێک پەڕەی ڕووناکی دەکەیتەوە. ئەمە چالاک بکە ئەگەر ئاستی ڕووناکی بە بەردەوامی دەگۆڕێت لە دەرەوەی توینکڵ ترەی (بۆ نموونە لەڕێی بەرنامەیەکی ترەوە).", "SETTINGS_TIME_TITLE": "ڕێکخستنەکانی کاتی ڕۆژ", "SETTINGS_TIME_DESC": "خۆکارانە ڕووناکی مۆنیتەرەکانت بکەرە ئاستێکی دیاریکراو لە کاتێکی خوازراودا. هەموو مۆنیتەرەکان دەخرێنە هەمان ئاستی ئاساییکراو.", "SETTINGS_TIME_ADD": "کاتێک زیاد بکە", "SETTINGS_TIME_REMOVE": "کات لاببە", "SETTINGS_TIME_INDIVIDUAL_TITLE": "ڕووناکی بۆ شاشەی تاک دیاری بکە", "SETTINGS_TIME_INDIVIDUAL_DESC": "ڕووناکی بەپێی شاشە ڕێکبخە لەجیاتیی هەموو شاشەکان بە یەک جار.", "SETTINGS_TIME_TRANSITON_TITLE": "خێرایی گۆڕانی ڕووناکی", "SETTINGS_TIME_TRANSITON_DESC": "خێرایی گۆڕانی ڕووناکی چەنێک بێت کاتێک ڕێکخستنەکانی کاتی ڕۆژ چالاکن.", "SETTINGS_TIME_STARTUP_TITLE": "دڵنیاکردنەوە لەکاتی کردنەوەی بەرنامە", "SETTINGS_TIME_STARTUP_DESC": "ڕووناکی ڕێکبخە تاکوو هەمان ئاستی دوایین کات بێت کاتێک توینکڵ ترەی دەکرێتەوە.", "SETTINGS_TIME_IDLE_TITLE": "دۆزینەوەی ئایدڵ ڕابگرە", "SETTINGS_TIME_IDLE_DESC": "ڕووناکیی هەموو شاشەکان کەم دەکرێتەوە کاتێک هیچ تێچوویەک نابیندرێت بۆ ماوەیەک.", "SETTINGS_TIME_ANIMATE_TITLE": "لە نێوان کاتەکاندا بجووڵێ", "SETTINGS_TIME_ANIMATE_DESC": "بڕەکانی ڕووناکی دەجووڵێن لە نێوان دوایین کات و کاتی دیاریکراوی دواتر. ئەمە لەوانەیە بەکارهێنانی سی پی یوو زیاد بکات. ڕێکخستنە دەستییەکانی ڕووناکی جێیان دەگیرێتەوە کاتێک ئەمە چالاکە.", "SETTINGS_HOTKEYS_TITLE": "قەدبڕەکان", "SETTINGS_HOTKEYS_DESC": "قەدبڕەکان دیاری بکە بۆ ڕێکخستنی ڕووناکیی یەک شاشە یاخوود هەموویان.", "SETTINGS_HOTKEYS_ADD": "زیادکردنی قەدبڕ", "SETTINGS_HOTKEYS_REMOVE": "لابردنی قەدبڕ", "SETTINGS_HOTKEYS_INCREASE": "زیادکردنی ڕووناکی", "SETTINGS_HOTKEYS_DECREASE": "کەمکردنی ڕووناکی", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "لێرە کلیلەکان تۆمار بکە", "SETTINGS_HOTKEYS_LEVEL_TITLE": "ڕێکخستنی ئاستی ڕووناکی", "SETTINGS_HOTKEYS_LEVEL_DESC": "چەنێک ڕووناکی ڕێک بخرێت کاتێک قەدبڕەکە بەکار دێنیت.", "SETTINGS_HOTKEYS_TOD_TITLE": "کرداری کوژاندنەوەی شاشەکان", "SETTINGS_HOTKEYS_TOD_DESC": "", "SETTINGS_HOTKEYS_TOD_NONE": "هیچ (ئایکۆن بشارەوە)", "SETTINGS_HOTKEYS_TOD_SOFT": "سیگناڵی نەرمامێر (بنچینەیی)", "SETTINGS_HOTKEYS_TOD_HARD": "", "SETTINGS_HOTKEYS_TOD_BOTH": "", "SETTINGS_HOTKEYS_TOD_NOTE": "", "SETTINGS_HOTKEYS_BREAK_TITLE": "", "SETTINGS_HOTKEYS_BREAK_DESC": "", "SETTINGS_UPDATES_TITLE": "نوێکردنەوەکان", "SETTINGS_UPDATES_VERSION": "تووینکڵ ترەیت هەیە {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "خۆکارانە بگەڕێ بۆ وەشانی نوێتر", "SETTINGS_UPDATES_AUTOMATIC_DESC": "کاتێک وەشانێکی نوێ بەردەست بێت، لە پانێڵی ڕووناکییەوە پیشان دەدرێت.", "SETTINGS_UPDATES_MS_STORE": "بۆ گەڕان بۆ وەشانی نوێ، سەردانی مایکرۆسۆفت ستۆر بکە.", "SETTINGS_UPDATES_AVAILABLE": "وەشانێکی نوێی تووینکڵ ترەی بەردەستە!", "SETTINGS_UPDATES_NONE_AVAILABLE": "وەشانەکەت نوێیە. ئەم وەشانە ئەم گۆڕانکارییانەی تێدا کراوە:", "SETTINGS_UPDATES_DOWNLOADING": "وەشانە نوێکە دادەبەزێت…", "SETTINGS_UPDATES_DOWNLOAD": "دابەزاندن و دامەزراندنی {{1}}", "SETTINGS_UPDATES_CHANNEL": "کەناڵی نوێکارییەکان", "SETTINGS_UPDATES_BRANCH_STABLE": "جێگیر (بنچینەیی)", "SETTINGS_UPDATES_BRANCH_BETA": "بێتا", "SETTINGS_FEATURES_POWER_OFF": "بیکوژێنەرەوە", "GENERIC_DELETE": "سڕینەوە", "SETTINGS_GENERAL_OVERLAY_TITLE": "ڕەفتاری ئۆڤەرلەیی بنچینەیی", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "گونجاوترین", "GENERIC_DEFAULT": "بنچینەیی", "GENERIC_OPTIONAL": "ئارەزوومەندانەیە", "SETTINGS_FEATURES_POWER_COMPAT": "گونجاوترین", "PANEL_LABEL_TURN_ON": "پێکردن", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "کاراکردنی زۆرەملێ", "SETTINGS_GENERAL_OVERLAY_DESC": "چەن بە زەبر هۆتکیی ڕووناکی هەوڵ دەدات کە لە سەروو بەرنامەکانی ترەوە دەربکەوێت. پێویست ناکات ئەمە ڕێکبخەیت.", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "هەمیشە هەوڵ بدە لە سەر ویندۆکانی ترەوە پیشانی بدەیت. ئەمە دەکرێت کێشە لەو یارییانەدا دروست بکات کە بە شێوەیەکی بنەڕەتی فووڵسکرینن. ئەمە دەکرێت دژە-فێڵیش کارا بکات لە چەند یارییەکدا.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "شێوازی دۆزینەوەی DDC/CIی کۆن", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "خۆکارانە ڕووناکی ڕێک بخە", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "شێوازی خۆکار بپەڕێنە بۆ شاشەی دیاریکراو", "SETTINGS_FEATURES_POWER_STANDBY": "ئامادەبەکار", "SETTINGS_FEATURES_ADD_VCP": "کۆدی VCP", "SETTINGS_FEATURES_VCP_EXPECTED": "بەها چاوەڕوانکراوەکان", "SETTINGS_TIME_LAT": "پانەهێڵ", "SETTINGS_GENERAL_REPORT_TITLE": "ڕاپۆرتێک دروست بکە", "SETTINGS_FEATURES_ADD": "زیادکردنی تایبەتمەندی", "SETTINGS_TIME_SUN_GET": "پۆتانەکان بهێنە", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "ئەگەر شاشەکەت نامۆیانە ڕەفتار دەکات دوای هەڵکردن/کوژاندنەوەی یان پچڕاندن/پەیوەستکردنی ڕەقئامێر، کوژاندنەوەی ئەمە لەوانەیە یارمەتیدەر بێت.", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "کێشانی پێچەوانە", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "ئەمە لە سەر زۆربەی ویندۆکانەوە دەردەکەوێت، بەڵام ئەو بەرنامانە نا کە بە \"هەمیشە لە سەرەوە\" دیاری کراون.", "SETTINGS_TIME_LONG": "درێژەهێڵ", "SETTINGS_HOTKEY_ADD_VALUE": "زیادکردنی بەها", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "شێوازی کۆنی وەشانی ١.١٥.٥ بەکار بێنە بۆ دۆزینەوەی شاشەی DDC/CI.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "ڕادەی کێشان", "SETTINGS_HOTKEY_VALUES": "بەهاکان", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "ژمارەیەک بنووسە", "SETTINGS_HOTKEY_VALUE": "بەها", "SETTINGS_HOTKEY_ACTION": "کردار", "SETTINGS_PROFILES_TITLE": "پڕۆفایلەکان", "SETTINGS_PROFILES_APP_PATH": "ڕێڕوەی بەرنامە", "SETTINGS_HOTKEY_ACTION_SET": "دانانی بەها", "SETTINGS_HOTKEY_ACTION_OFFSET": "ڕێکخستنی بەها", "SETTINGS_PROFILES_ADD": "پڕۆفایلی نوێ", "SETTINGS_PROFILES_NAME": "ناوی پڕۆفایل", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "لە قفڵکردنی شاشەدا ناچالاکی بکە", "SETTINGS_GENERAL_REPORT_DESC": "پەڕگەیەکی دەق پاشەکەوت بکە کە زانیاریی تێدایە لەسەر مۆنیتەرەکەت و ڕێکخستنەکانت بۆ ھەڵەدۆزی.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "ڕووناکی" } ================================================ FILE: src/localization/cs.json ================================================ { "LANGUAGE": "Čeština", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Storno", "GENERIC_SAVE": "Uložit", "GENERIC_CLEAR": "Vyčistit", "GENERIC_OFF": "Vypnuto", "GENERIC_ON": "Zapnuto", "GENERIC_QUIT": "Ukončit", "GENERIC_CLOSE": "Zavřít", "GENERIC_SETTINGS": "Nastavení", "GENERIC_INSTALL": "Nainstalovat", "GENERIC_DISMISS": "Ignorovat", "GENERIC_DISPLAY_SINGLE": "Monitor", "GENERIC_ALL_DISPLAYS": "Všechny monitory", "GENERIC_REFRESH_DISPLAYS": "Aktualizovat monitory", "GENERIC_MINIMUM": "Minimum", "GENERIC_MAXIMUM": "Maximum", "GENERIC_NO_DISPLAYS": "Nebyly nalezeny žádné monitory. Zkontrolujte spojení (kabely, nastavení monitorů, ...).", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Nebyly nalezeny žádné kompatibilní monitory. Zkontrolujte, zda vaše monitory podporují DDC/CI.", "GENERIC_NO_DISPLAYS_SHORT": "Nebyly detekovány žádné kompatibilní monitory.", "GENERIC_SECONDS": "sekund(y)", "GENERIC_MINUTES": "minut(y)", "GENERIC_DDC_WARNING": "Některé funkce DDC/CI, mohou způsobit, že monitor přestane reagovat. Používejte na vlastní nebezpečí.", "GENERIC_SPEED_INSTANT": "Instantní", "GENERIC_SPEED_SLOW": "Pomalá", "GENERIC_SPEED_VERY_SLOW": "Velmi pomalá", "GENERIC_SPEED_NORMAL": "Normální", "GENERIC_SPEED_FAST": "Rychlá", "GENERIC_SPEED_VERY_FAST": "Velmi rychlá", "PANEL_TITLE": "Úprava jasu", "PANEL_UPDATE_AVAILABLE": "Nová verze k dispozici", "PANEL_BUTTON_LINK_LEVELS": "Sloučit nastavení jasu všech monitorů", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Vypnout všechny monitory", "PANEL_LABEL_BRIGHTNESS": "Jas", "PANEL_LABEL_CONTRAST": "Kontrast", "PANEL_LABEL_OFF_ON": "Stav napájení", "PANEL_LABEL_COLOR_TEMPERATURE": "Teplota barvy", "PANEL_LABEL_VOLUME": "Hlasitost", "PANEL_LABEL_TURN_OFF": "Vypnout displej", "INTRO_TITLE": "Zdravím, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Twinkle Tray ikonka na liště je pravděpodobně schovaná, doporučím Vám, abyste si ji přesunuli na dostupnější místo. Podrobnější návod viz níže.", "SETTINGS_TITLE": "Twinkle Tray Nastavení", "SETTINGS_SIDEBAR_GENERAL": "Obecné", "SETTINGS_SIDEBAR_MONITORS": "Nastavení Monitorů", "SETTINGS_SIDEBAR_FEATURES": "Funkce DDC/CI", "SETTINGS_SIDEBAR_TIME": "Časovače", "SETTINGS_SIDEBAR_HOTKEYS": "Zkratky", "SETTINGS_SIDEBAR_UPDATES": "Aktualizace", "SETTINGS_GENERAL_TITLE": "Obecné", "SETTINGS_GENERAL_STARTUP": "Zapnout Twinkle Tray při zapnutí PC/přihlášení", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Obnovit jas při spuštění aplikace", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Obnovit poslední známý jas (zvlášť pro každý monitor) při spuštění aplikace.", "SETTINGS_GENERAL_THEME_TITLE": "Motiv", "SETTINGS_GENERAL_THEME_SYSTEM": "Dle systémového nastavení (výchozí)", "SETTINGS_GENERAL_THEME_DARK": "Tmavý", "SETTINGS_GENERAL_THEME_LIGHT": "Světlý", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Jazyk", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Dle systémového nastavení (výchozí)", "SETTINGS_GENERAL_RESET_TITLE": "Obnova nastavení", "SETTINGS_GENERAL_RESET_DESC": "Zmáčknutím tlačítka dojde k obnovení nastavení na výchozí hodnoty.", "SETTINGS_GENERAL_RESET_BUTTON": "Obnovit nastavení", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akrylový efekt rozmazání", "SETTINGS_GENERAL_ACRYLIC_DESC": "Vypne nebo zapne rozmazání za průhledným pozadím v aplikaci Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Mica efekt rozmazání", "SETTINGS_GENERAL_MICA_DESC": "Vypne nebo zapne rozmazání za pozadím v aplikaci Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Odesílání analytický dat", "SETTINGS_GENERAL_ANALYTICS_DESC": "Odesílání analytických dat nám umožňuje vylepšovat Twinkle Tray. Odesílaná data jsou anonymní. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Zjistit více", "SETTINGS_GENERAL_SCROLL_TITLE": "Skrolování přes ikonku na liště", "SETTINGS_GENERAL_SCROLL_DESC": "Úprava jasu všech monitorů naráz pomocí skrolování (touchpadem, kolečkem na myši) nad ikonkou na liště. Některé touchpady nemusí tuto funkci podporovat.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Ikonka na liště", "SETTINGS_GENERAL_TROUBLESHOOTING": "Řešení problémů", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Povolené metody detekce monitoru", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Pokud aplikace nereaguje nebo nedetekuje monitory, o nichž jste přesvědčeni, že by měly být podporovány, můžete níže vypnout konkrétní komunikační metody/protokoly. Poté restartujte aplikaci, aby se změny projevily. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Vypnout překrytí", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Pokud překryvná klávesová zkratka Twinkle Tray překáží aplikacím na celou obrazovku, můžete ji zde zakázat.", "SETTINGS_MONITORS_RATE_TITLE": "Četnost aktualizace nastavení monitorů", "SETTINGS_MONITORS_RATE_DESC": "Jak často se má odesílat nastavení do monitorů (během upravování hodnot). Zvolte delší dobu, pokud pozorujete flickering (problikávání).", "SETTINGS_MONITORS_RATE_0": "Téměř instantní", "SETTINGS_MONITORS_RATE_1": "Rychlá (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normální (500 ms)", "SETTINGS_MONITORS_RATE_3": "Pomalá (1 sekunda)", "SETTINGS_MONITORS_RATE_4": "Velmi pomalá (2 sekundy)", "SETTINGS_MONITORS_RENAME_TITLE": "Přejmenování monitorů", "SETTINGS_MONITORS_RENAME_DESC": "Níže je možné přejmenovat jednotlivé monitory dle vašich preferencí (např. \"Levý monitor\"). Vymazáním pole se vrátí jméno monitoru na výchozí hodnotu.", "SETTINGS_MONITORS_ENTER_NAME": "Napište jméno", "SETTINGS_MONITORS_REORDER_TITLE": "Uspořádání monitorů", "SETTINGS_MONITORS_REORDER_DESC": "Níže je možné přetažením přeuspořádat pořadí monitorů v nabídce lišty dle vaší libosti.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalizace jasu", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitory mají často různé rozsahy jasu. Omezením minimálního/maximálního jasu pro každý displej dosáhnete mnohem větší konzistence úrovní jasu mezi jednotlivými displeji.", "SETTINGS_MONITORS_DETAILS_NAME": "Jméno", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Interní jméno", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Komunikační metoda/protokol", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Současná hodnota jasu", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maximální hodnota jasu", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Rozsah jasu (viz \"Normalizace jasu\")", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Skrytí neaktivních monitorů", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Pokud je víko notebooku zavřené nebo je zabudovaný monitor vypnutý v nastavení operačního systému, nebude se zobrazovat nastavení jasu v nabídce lišty.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Skrytí monitorů", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Níže je možné vybrat monitory, které se nemají zobrazovat v nabídce lišty.", "SETTINGS_FEATURES_DESCRIPTION": "Níže můžete vybrat, které DDC/CI funkce se objeví u jednotlivých monitorů v nabídce lišty. Je možné, že některé monitory nepodporují některé funkce i přesto, že jsou v nabídce.", "SETTINGS_FEATURES_UNSUPPORTED": "Tento monitor nepodporuje DDC/CI funkce.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Zkontrolovat aktuální hodnoty", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Pokud je zapnuto, pak bude hodnota jasu obnovena vždy při otevření nabídky lišty. Doporučujeme zapnout, pokud je jas často upravován jinak, než pomocí Twinkle Tray.", "SETTINGS_TIME_TITLE": "Časovače", "SETTINGS_TIME_DESC": "Níže můžete přidat a upravit časy, při kterých se má automaticky nastavit jas všech/jednotlivých monitorů. Nastavená hodnota je procentuální vůči rozsahu jasu pro konkrétní monitor (viz \"Normalizace jasu\" v \"Nastavení monitorů\").", "SETTINGS_TIME_ADD": "Přidat časovač", "SETTINGS_TIME_REMOVE": "Odstranit časovač", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Režim časovače", "SETTINGS_TIME_INDIVIDUAL_DESC": "Je-li zapnuto, pak lze nastavit jas časovače pro každý monitor zvlášť.", "SETTINGS_TIME_TRANSITON_TITLE": "Rychlost přechodu jasu", "SETTINGS_TIME_TRANSITON_DESC": "Níže je možné vybrat, jak dlouho potrvá změna jasu při změně časovačů.", "SETTINGS_TIME_STARTUP_TITLE": "Kontrola časovačů při startu aplikace", "SETTINGS_TIME_STARTUP_DESC": "Při startu aplikace upraví jas dle nejvíce relevantního časovače (pozn. překladu: není upřesněno, co přesně se rozumí slovem relevantní).", "SETTINGS_TIME_IDLE_TITLE": "Detekce nepřítomnosti", "SETTINGS_TIME_IDLE_DESC": "Pokud nebude detekován delší dobu žádný vstup od uživatele, pak bude jas všech monitorů snížen.", "SETTINGS_HOTKEYS_TITLE": "Zkratky", "SETTINGS_HOTKEYS_DESC": "Níže můžete nastavit klávesové zkratky pro jednotlivé funkce.", "SETTINGS_HOTKEYS_ADD": "Přidat zkratku", "SETTINGS_HOTKEYS_REMOVE": "Odstranit zkratku", "SETTINGS_HOTKEYS_INCREASE": "Zvýšení jasu", "SETTINGS_HOTKEYS_DECREASE": "Snížení jasu", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Zmáčkni klávesy tu", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Velikost kroku jasu (při použití klávesové zkratky)", "SETTINGS_HOTKEYS_LEVEL_DESC": "O kolik se má posunout hodnota jasu při jednom zmáčknutí klávesové zkratky.", "SETTINGS_HOTKEYS_TOD_TITLE": "Akce tlačítka \"Vypnout všechny monitory\"", "SETTINGS_HOTKEYS_TOD_DESC": "Níže je možné vybrat akci při stisknutí tlačítka \"Vypnout všechny monitory\". \"Softwarový signál\" je ekvivalent zhasnutí monitoru při delší neaktivitě, použitím myši nebo klávesnice dojde k obnovení obrazu. \"Hardwarový signál\" je ekvivalent vypnutí monitoru pomocí tlačítka napájení.", "SETTINGS_HOTKEYS_TOD_NONE": "Žádná akce (tlačítko je skryté)", "SETTINGS_HOTKEYS_TOD_SOFT": "Softwarový signál (výchozí)", "SETTINGS_HOTKEYS_TOD_HARD": "Hardwarový* signál (pouze u DDC/CI protokolu)", "SETTINGS_HOTKEYS_TOD_BOTH": "Hardwarový* nebo softwarový signál", "SETTINGS_HOTKEYS_TOD_NOTE": "*Poznámka: Ne všechny DDC/CI monitory podporují funkci úplného vypnutí.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Použití klávesové zkratky ukončí \"Sloučit nastavení jasu všech monitorů\"", "SETTINGS_HOTKEYS_BREAK_DESC": "Při použití libovolné klávesové zkratky bude funkce \"Sloučit nastavení jasu všech monitorů\" vypnuta.", "SETTINGS_UPDATES_TITLE": "Aktualizace", "SETTINGS_UPDATES_VERSION": "Verze Twinkie Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automaticky kontroloval aktualizace", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Informace o dostupné aktualizace bude zobrazena v nabídce lišty.", "SETTINGS_UPDATES_MS_STORE": "Aktualizujte pomocí aplikace Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Je dostupná nová verze!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Je nainstalována nejnovější verze, změny při poslední aktualizaci:", "SETTINGS_UPDATES_DOWNLOADING": "Stahuji aktualizaci…", "SETTINGS_UPDATES_DOWNLOAD": "Dostupná verze (kliknutím instalovat): {{1}}", "GENERIC_PAUSE_TOD": "Nastavení času pauzy", "GENERIC_PAUSE_IDLE": "Nastavení detekce nepřítomnosti", "SETTINGS_TIME_ANIMATE_TITLE": "Plynulý přechod jasu", "SETTINGS_TIME_ANIMATE_DESC": "Při změně časovačů bude přechod jasu plynulý. Může zvýšit využití procesoru. Jakékoliv manuální změny jasu budou během aktivního přechodu následovně přepsány při další aktualizaci přechodu.", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabilní (release, výchozí)", "SETTINGS_UPDATES_CHANNEL": "Kanál aktualizací", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Vypnout displej", "PANEL_LABEL_TURN_ON": "Zapnout displej", "SETTINGS_FEATURES_POWER_TITLE": "Signál stavu napájení", "SETTINGS_FEATURES_POWER_STANDBY": "Pohotovost", "SETTINGS_FEATURES_POWER_COMPAT": "Nejvíce kompatibilní", "SETTINGS_HOTKEY_TARGET": "Cíl akce", "SETTINGS_HOTKEY_VALUE": "Hodnota", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Zadejte číslo", "SETTINGS_HOTKEY_VALUES": "Hodnoty", "SETTINGS_HOTKEY_ADD_VALUE": "Přidat hodnotu", "SETTINGS_HOTKEY_ACTION": "Akce", "SETTINGS_HOTKEY_ACTION_SET": "Nastavit hodnotu", "SETTINGS_HOTKEY_ACTION_OFFSET": "Upravit hodnotu", "SETTINGS_HOTKEY_ACTION_CYCLE": "Procházet seznam hodnot", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Nejvíce kompatibilní", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Jas", "GENERIC_DELETE": "Vymazat", "GENERIC_DEFAULT": "Výchozí", "GENERIC_OPTIONAL": "Volitelný", "GENERIC_CALIBRATION_POINT": "Kalibrační Bod", "GENERIC_SUPPORTED": "Podporováno", "GENERIC_ACTIVE": "Aktivní", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Detekuje změny stavu napájení monitorů. Vypnutí této funkce může pomoci, pokud dochází k chybám při vypínání/zapínání monitorů nebo při jejich nečinnosti. Pro uplatnění změny je nutné restartovat počítač.", "SETTINGS_GENERAL_OVERLAY_DESC": "Jak silně se bude překryvná vrstva klávesové zkratky pro jas snažit zobrazit přes jiné aplikace. Tuto nastavení byste neměli potřebovat upravovat.", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Vynutit překrytí", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Vždy se snažte zobrazit překryvnou vrstvu nad ostatními okny. To může způsobit problémy s exkluzivními hrami na celou obrazovku a jinými aplikacemi na celou obrazovku. V některých hrách to může také spustit anti-cheat.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Starší metoda detekce DDC/CI", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Použit starou metodu v1.15.5 pro detekci displejů DDC/CI.", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Pokud se váš monitor chová podivně po vypnutí/zapnutí nebo odpojení/připojení hardwaru, deaktivace tohoto může pomoci.", "SETTINGS_GENERAL_REPORT_TITLE": "Vygenerovat zprávu", "SETTINGS_GENERAL_REPORT_DESC": "Uložit textový soubor s informacemi o vašich monitorech a nastaveních pro ladění.", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Detekce aktualizací motivů", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Detekuje změny motivu/tapety/tématu ve Windows a aktualizuje ikonu v oznamovací oblasti a efekt Mica. Vypnutí této funkce může pomoci, pokud aplikace třetí strany často mění téma a zvyšuje tak využití procesoru.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Detekce stavu napájení monitoru", "SETTINGS_GENERAL_OVERLAY_TITLE": "Výchozí chování překrytí", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Překrytí se zobrazí nad většinou oken, ale nebude se vynucovat nad aplikacemi, které jsou označeny jako „vždy nahoře“.", "GENERIC_DETECTING_DISPLAYS": "Detekce displejů…", "GENERIC_ICON": "Ikona", "GENERIC_TEXT": "Text" } ================================================ FILE: src/localization/de.json ================================================ { "LANGUAGE": "Deutsch", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Abbrechen", "GENERIC_SAVE": "Speichern", "GENERIC_CLEAR": "Leeren", "GENERIC_OFF": "Aus", "GENERIC_ON": "Ein", "GENERIC_QUIT": "Beenden", "GENERIC_CLOSE": "Schließen", "GENERIC_SETTINGS": "Einstellungen", "GENERIC_INSTALL": "Installieren", "GENERIC_DISMISS": "Ignorieren", "GENERIC_DISPLAY_SINGLE": "Monitor", "GENERIC_ALL_DISPLAYS": "Alle Monitore", "GENERIC_MINIMUM": "min.", "GENERIC_MAXIMUM": "max.", "GENERIC_NO_DISPLAYS": "Keine Monitore gefunden. Bitte verbinden Sie einen Monitor mit Ihrem PC.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Keine kompatiblen Monitore gefunden. Bitte stellen Sie sicher, dass \"DDC/CI\" für Ihre Monitore aktiviert ist.", "GENERIC_NO_DISPLAYS_SHORT": "Keine kompatiblen Monitore gefunden.", "PANEL_TITLE": "Helligkeit anpassen", "PANEL_UPDATE_AVAILABLE": "Eine neue Version ist verfügbar", "PANEL_BUTTON_LINK_LEVELS": "Verbindungsebenen", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Monitore ausschalten", "INTRO_TITLE": "Hallo, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Das Taskleistensymbol von Twinkle Tray ist vermutlich versteckt, Sie sollten es an einen sichtbaren Ort verschieben, so dass Sie es einfach erreichen können. Siehe untenstehende Anweisungen.", "SETTINGS_TITLE": "Twinkle Tray-Einstellungen", "SETTINGS_SIDEBAR_GENERAL": "Allgemein", "SETTINGS_SIDEBAR_MONITORS": "Monitor-Einstellungen", "SETTINGS_SIDEBAR_TIME": "Zeit-Einstellungen", "SETTINGS_SIDEBAR_HOTKEYS": "Tastenkürzel & Verknüpfungen", "SETTINGS_SIDEBAR_UPDATES": "Aktualisierungen", "SETTINGS_GENERAL_TITLE": "Allgemein", "SETTINGS_GENERAL_STARTUP": "Mit Windows starten", "SETTINGS_GENERAL_THEME_TITLE": "Aussehen", "SETTINGS_GENERAL_THEME_SYSTEM": "Systemeinstellungen (Standard)", "SETTINGS_GENERAL_THEME_DARK": "Dunkel", "SETTINGS_GENERAL_THEME_LIGHT": "Hell", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Sprache", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Systemsprache (Standard)", "SETTINGS_GENERAL_RESET_TITLE": "Einstellungen zurücksetzen", "SETTINGS_GENERAL_RESET_DESC": "Hier klicken, um die Einstellungen zurückzusetzen.", "SETTINGS_GENERAL_RESET_BUTTON": "Einstellungen zurücksetzen", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analyse", "SETTINGS_GENERAL_ANALYTICS_DESC": "Nutzerdaten an Twinkle Tray senden, um Twinkle Tray zu verbessern. Es werden keine persönlichen Daten versendet. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Mehr erfahren", "SETTINGS_MONITORS_RATE_TITLE": "Helligkeitsaktualisierungs-Intervall", "SETTINGS_MONITORS_RATE_DESC": "Wie oft die Helligkeit Ihrer Monitore aktualisiert wird, während Sie diese einstellen. Erhöhen Sie diesen Wert, wenn Ihre Monitore flackern.", "SETTINGS_MONITORS_RATE_0": "Extrem schnell", "SETTINGS_MONITORS_RATE_1": "Schnell (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Langsam (1 Sekunde)", "SETTINGS_MONITORS_RATE_4": "Sehr langsam (2 Sekunden)", "SETTINGS_MONITORS_RENAME_TITLE": "Monitore umbenennen", "SETTINGS_MONITORS_RENAME_DESC": "Falls Sie einen eigenen Namen für jeden Monitor bevorzugen (z.B. \"Linker Monitor\", \"Mittlerer Monitor\"), können Sie den Namen unten eingeben. Falls Sie das Feld leer lassen, wird der ursprüngliche Name wiederhergestellt.", "SETTINGS_MONITORS_ENTER_NAME": "Namen eingeben", "SETTINGS_MONITORS_REORDER_TITLE": "Monitore neu anordnen", "SETTINGS_MONITORS_REORDER_DESC": "Verändern Sie die Reihenfolge der Monitore im Taskleistensymbol. Klicken und ziehen, um Änderungen vorzunehmen.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Helligkeit normalisieren", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitore haben oftmals verschiedene Helligkeits-Spektren. Die Helligkeitsstufen können einheitlicher gemacht werden, indem die minimale bzw. maximale Helligkeit der Monitore begrenzt wird. Ähnliche Monitore werden dieselben Einstellungen verwenden.", "SETTINGS_TIME_TITLE": "Tageszeitanpassungen", "SETTINGS_TIME_DESC": "Helligkeit je nach Uhrzeit auf eine bestimmte Helligkeit setzen. Alle Monitore werden dieselben, normalisierten Einstellungen verwenden.", "SETTINGS_TIME_ADD": "Uhrzeit hinzufügen", "SETTINGS_TIME_REMOVE": "Uhrzeit entfernen", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Die Helligkeit für einzelne Monitore einstellen", "SETTINGS_TIME_INDIVIDUAL_DESC": "Die Helligkeit für einzelne Monitore anpassen, anstelle aller Monitore auf einmal.", "SETTINGS_TIME_STARTUP_TITLE": "Beim Programmstart überprüfen", "SETTINGS_TIME_STARTUP_DESC": "Die Helligkeit automatisch der relevantesten Uhrzeit anpassen, wenn Twinkle Tray gestartet wird.", "SETTINGS_HOTKEYS_TITLE": "Tastenkürzel", "SETTINGS_HOTKEYS_DESC": "Tastenkombinationen für die Anpassung der Helligkeit einzelner oder aller Monitore.", "SETTINGS_HOTKEYS_ADD": "Tastenkombination hinzufügen", "SETTINGS_HOTKEYS_REMOVE": "Tastenkombination entfernen", "SETTINGS_HOTKEYS_INCREASE": "Helligkeit erhöhen", "SETTINGS_HOTKEYS_DECREASE": "Helligkeit verringern", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Hier Tasten drücken", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Anpassen der Helligkeitseinstellung", "SETTINGS_HOTKEYS_LEVEL_DESC": "Legt fest, wie stark die Helligkeit angepasst werden soll, wenn Tastenkombinationen gedrückt werden.", "SETTINGS_UPDATES_TITLE": "Aktualisierungen", "SETTINGS_UPDATES_VERSION": "Sie haben Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automatisch nach neuen Versionen suchen", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Wenn es eine neue Version gibt, wird dies im Helligkeits-Overlay angezeigt.", "SETTINGS_UPDATES_MS_STORE": "Um nach Aktualisierungen zu suchen, besuchen Sie die Microsoft-Store-App.", "SETTINGS_UPDATES_AVAILABLE": "Neue Version von Twinkle Tray verfügbar!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Auf dem neusten Stand. Die aktuelle Version von Twinkle Tray enthält folgende Änderungen:", "SETTINGS_UPDATES_DOWNLOADING": "Aktualisierung wird heruntergeladen…", "SETTINGS_UPDATES_DOWNLOAD": "Herunterladen & installieren {{1}}", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Taskleistensymbol", "SETTINGS_GENERAL_SCROLL_DESC": "Über dem Taskleistensymbol mit dem Mausrad drehen, um die Helligkeit aller Monitore auf einmal anzupassen. Nicht kompatibel mit einigen Touchpads.", "SETTINGS_GENERAL_SCROLL_TITLE": "Schnellzugriff: Mausrad über dem Taskleistensymbol", "SETTINGS_GENERAL_ACRYLIC_DESC": "Aktivieren oder deaktivieren Sie den Unschärfe-Effekt hinter transparenten Hintergründen von Twinkle Tray.", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Acryl-Unschärfe", "SETTINGS_MONITORS_FEATURES_DESCRIPTION": "Aktivieren oder deaktivieren Sie bestimmte DDC/CI-Funktionen im Helligkeitsfeld. Mindestens eine Funktion muss aktiviert sein, damit Ihr Monitor im Helligkeitsfeld angezeigt wird. Nicht alle Bildschirme unterstützen diese Funktionen, wie z. B. Laptop-/Tablet-Bildschirme.", "SETTINGS_MONITORS_FEATURES_TITLE": "DDC/CI-Funktionen", "PANEL_LABEL_COLOR_TEMPERATURE": "Farbtemperatur", "PANEL_LABEL_OFF_ON": "Energiezustand", "PANEL_LABEL_CONTRAST": "Kontrast", "PANEL_LABEL_BRIGHTNESS": "Helligkeit", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI-Funktionen", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Helligkeits-Normalisierung", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Interner Name", "SETTINGS_MONITORS_DETAILS_NAME": "Name", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Beim Start von Twinkle Tray letzte bekannte Helligkeit aller Monitore wiederherstellen.", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Helligkeit beim Start anwenden", "GENERIC_REFRESH_DISPLAYS": "Monitore aktualisieren", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Kommunikationsmethode", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Aktuelle Helligkeit", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maximale Helligkeit", "PANEL_LABEL_VOLUME": "Lautstärke", "SETTINGS_HOTKEYS_TOD_NOTE": "*Nicht alle DDC/CI-Monitore unterstützen diese Funktion.", "SETTINGS_FEATURES_DESCRIPTION": "Aktivieren oder Deaktivieren bestimmter DDC/CI-Funktionen für das Helligkeits-Overlay. Mindestens eine Funktion muss aktiviert sein, damit ein Monitor im Helligkeits-Overlay verfügbar ist. Nicht alle Bildschirme unterstützen diese Funktionen, bspw. Laptop- oder Tablet-Bildschirme.", "SETTINGS_HOTKEYS_TOD_NONE": "Keine (Symbol ausblenden)", "PANEL_LABEL_TURN_OFF": "Ausschalten", "SETTINGS_TIME_IDLE_DESC": "Wenn für eine gewisse Zeitspanne keine Eingaben erkannt wurden, wird die Helligkeit aller Anzeigen reduziert.", "SETTINGS_HOTKEYS_TOD_SOFT": "Software-Signal (Standard)", "SETTINGS_TIME_IDLE_TITLE": "Inaktivitäts-Erkennung", "SETTINGS_HOTKEYS_TOD_HARD": "Hardware*-Signal (nur DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Hardware-* & Software-Signal", "SETTINGS_HOTKEYS_BREAK_TITLE": "Tastenkombinationen heben Verknüpfungen von Werten auf", "SETTINGS_GENERAL_MICA_TITLE": "Mica-Unschärfe-Effekt", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Inaktive interne Anzeige ausblenden", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Aktuelle Werte überprüfen", "GENERIC_SECONDS": "Sekunden", "GENERIC_MINUTES": "Minuten", "SETTINGS_GENERAL_MICA_DESC": "Aktivieren oder deaktivieren des Mice-Unschärfe-Effekts bei Hintergründen von Twinkle Tray.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Immer die aktuellen Werte vom Monitor abfragen, wenn das Helligkeits-Overlay geöffnet wird. Diese Funktion aktivieren, wenn sich die Helligkeits-Einstellung (oder andere VCP-Codes, wie der Kontrast) häufig außerhalb von Twinkle Tray ändert.", "SETTINGS_FEATURES_UNSUPPORTED": "Dieser Monitor unterstützt keine DDC/CI-Funktionen.", "SETTINGS_HOTKEYS_BREAK_DESC": "Wenn eine Tastenkombination für einen Einzel-Monitor verwendet wird führt dies zur Aufhebung der \"Helligkeits-Verknüpfung\", falls diese aktiviert war.", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Den Helligkeitsregler ausblenden, wenn der Laptop zugeklappt ist oder die interne Anzeige deaktiviert wurde.", "SETTINGS_HOTKEYS_TOD_DESC": "Passt das Signal an, das bei Verwendung der Tastenkombination oder Symbols zum Ausschalten der Anzeige(n) gesendet wird. Das Software-Signal zeigt einen schwarzen Bildschirm an, bis eine Eingabe (z.B. Maus oder Tastatur) von Windows erkannt wird. Das Hardware-Signal schaltet die Stromversorgung der Monitore aus.", "SETTINGS_HOTKEYS_TOD_TITLE": "Ausschaltsignal", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Wenn Twinkle Tray beim Klicken auf das Tray-Symbol nicht reagiert oder Ihre Bildschirme nicht erkennt, können Sie versuchen, bestimmte Monitorerkennungsmethoden zu deaktivieren. Starten Sie Twinkle Tray neu, um die Änderungen anzuwenden. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Wenn das Helligkeits-Overlay von Twinkle Tray zu Problemen mit Vollbildanwendungen führt, können Sie es hier deaktivieren.", "SETTINGS_TIME_ANIMATE_DESC": "Die Helligkeitswerte werden zwischen dem aktuellen und dem nächsten geplanten Ereignis animiert. Kann die CPU-Auslastung erhöhen. Manuelle Helligkeitsanpassungen werden schnell überschrieben, solange dies aktiv ist.", "GENERIC_PAUSE_IDLE": "Inaktivitäts-Erkennung pausieren", "GENERIC_PAUSE_TOD": "Zeitanpassungen pausieren", "SETTINGS_GENERAL_TROUBLESHOOTING": "Fehlerbehebung", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Erkennungsmethoden für den Monitor aktiviert", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Overlay deaktivieren", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Monitore ausblenden", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Um bestimmte Monitore aus dem Overlay auszublenden können Sie diese hier auswählen.", "SETTINGS_TIME_TRANSITON_TITLE": "Helligkeits-Übergangsgeschwindigkeit", "SETTINGS_TIME_ANIMATE_TITLE": "Zwischen den Zeiten animieren", "GENERIC_SPEED_INSTANT": "Sofort", "GENERIC_SPEED_SLOW": "Langsam", "GENERIC_SPEED_VERY_SLOW": "Sehr langsam", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_SPEED_FAST": "Schnell", "GENERIC_SPEED_VERY_FAST": "Sehr schnell", "GENERIC_DDC_WARNING": "DDC/CI-Funktionen wie das Ein- und Ausschalten von Monitoren, können dazu führen, dass Ihr Monitor nicht mehr reagiert. Die Verwendung erfolgt auf eigene Gefahr.", "SETTINGS_TIME_TRANSITON_DESC": "Wie schnell die Helligkeit wechseln soll, wenn die Tageszeitanpassung ist.", "SETTINGS_UPDATES_BRANCH_STABLE": "Stable (Standard)", "SETTINGS_UPDATES_CHANNEL": "Aktualisierungs-Kanal", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "PANEL_LABEL_TURN_ON": "Einschalten", "SETTINGS_GENERAL_OVERLAY_TITLE": "Standard Overlay-Verhalten", "SETTINGS_FEATURES_POWER_TITLE": "Ein- und Ausschaltsignal", "SETTINGS_FEATURES_POWER_DESC": "Wenn Sie den DDC/CI-Befehl zum Ausschalten Ihres Monitors senden, wird/werden der/die folgende(n) Wert(e) gesendet.", "SETTINGS_FEATURES_POWER_STANDBY": "Energiesparmodus", "SETTINGS_FEATURES_POWER_WARNING": "Mit der \"Energiesparmodus\"-Option ist es wahrscheinlicher, dass sich der Monitor mit Twinkle Tray aus- und wieder einschalten lässt, jedoch reagieren viele Monitore darauf nicht richtig. Nutzung auf eigene Gefahr.", "SETTINGS_FEATURES_ADD": "Funktion hinzufügen", "SETTINGS_FEATURES_ADD_VCP": "VCP-Code", "SETTINGS_FEATURES_VCP_EXPECTED": "Erwartete Werte", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Scrollwert", "SETTINGS_PROFILES_ADD": "Neues Profil", "GENERIC_DELETE": "Löschen", "GENERIC_DEFAULT": "Standard", "GENERIC_OPTIONAL": "Optional", "SETTINGS_GENERAL_OVERLAY_DESC": "Wie fest das Helligkeits-Overlay versuchen wird, sich vor anderen Apps einzublenden. Eine Anpassung sollte nicht nötig sein.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Höchste Kompatibilität", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Das Overlay wird über den meisten anderen Fenstern angezeigt, außer bei Programmen, welche angeheftet (\"Immer im Vordergrund\") sind.", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Erzwungen", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Das Overlay immer über anderen Fenstern anzeigen. Dies kann zu Problemen mit Spielen und anderen Programmen im exklusiven Vollbild führen. Außerdem kann es in manchen Spielen Anti-Cheat-Maßnahmen auslösen.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Frühere DDC/CI-Erkennungsmethode", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Die veraltete v1.15.5 Methode zum Erkennen von DDC/CI-Monitoren verwenden.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Helligkeit automatisch anwenden", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Sie können versuchen, diese Einstellung zu deaktivieren, falls sich der Monitor nach dem Ein-/Ausschalten bzw. dem Verbinden oder Trennen von Hardware ungewöhnlich verhält.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Automatisches Anwenden für gewisse Monitore deaktivieren", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Helligkeit nach Ein-/Ausschalten oder anderen Hardware-Ereignissen für die folgenden Bildschirme nicht automatisch wiederherstellen. Dies umfasst auch die Inaktivitäts-Erkennung.", "SETTINGS_FEATURES_POWER_COMPAT": "Höchste Kompatibilität", "SETTINGS_FEATURES_ADD_DESC": "Geben Sie einen VCP-Code für die Funktion ein, welche Sie hinzufügen wollen. Bitte beachten Sie, dass Twinkle Tray nicht überprüft, ob der Monitor diesen VCP-Code tatsächlich unterstützt. Nutzung auf eigene Gefahr.", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP-Code (Bspw. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Diese Funktion ist bereits aktiv.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Alle VCP-Codes, welche dieser Monitor meldet", "SETTINGS_FEATURES_VCP_LIST_DESC": "Die folgende Liste zeigt alle verfügbaren VCP-Codes, welche dieser Monitor an Windows meldet. Twinkle Tray überprüft weder die Funktionalität noch Stabilität dieser VCP-Codes. Nutzung auf eigene Gefahr.", "SETTINGS_TIME_SUN_TITLE": "Koordinaten für Sonnenstand", "SETTINGS_TIME_SUN_DESC": "Um die „Sonnenposition“ für Zeitanpassungen zu verwenden muss Ihr aktueller Breiten- und Längengrad eingegeben werden, damit die korrekten Zeiten ermittelt werden können.", "SETTINGS_TIME_LAT": "Breitengrad", "SETTINGS_TIME_LONG": "Längengrad", "SETTINGS_TIME_SUN_GET": "Koordinaten abrufen", "SETTINGS_TIME_IDLE_FS_TITLE": "Programme im Vollbildmodus unterbinden die Inaktivitäts-Erkennung", "SETTINGS_TIME_IDLE_FS_DESC": "Programme im Vollbildmodus blockieren die Inaktivitäts-Erkennung. Dies bezieht sich nur auf das aktuell aktive/fokussierte Fenster.", "SETTINGS_HOTKEY_OFF_WARN": "Diese Aktion folgt der Einstellung der \"Monitore-Ausschalten-Aktion\". Für das Ausschalten bestimmter Monitore sind die Tastenkombinations-Aktionen\"Wert festlegen\" oder \"Durchwechseln\" besser geeignet.", "SETTINGS_HOTKEY_TARGET": "Aktionsziel", "SETTINGS_HOTKEY_VALUE": "Wert", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Zahl eingeben", "SETTINGS_HOTKEY_VALUES": "Werte", "SETTINGS_HOTKEY_ADD_VALUE": "Wert hinzufügen", "SETTINGS_HOTKEY_ACTION": "Aktion", "SETTINGS_HOTKEY_ACTION_SET": "Wert festlegen", "SETTINGS_HOTKEY_ACTION_OFFSET": "Wert anpassen", "SETTINGS_HOTKEY_ACTION_CYCLE": "Werte-Liste durchwechseln", "SETTINGS_PROFILES_TITLE": "Profile", "SETTINGS_PROFILES_DESC": "Automatisches Anpassen des Helligkeit- bzw. des Overlay-Tastenkombination-Verhaltens abhängig vom fokussierten Programmfenster. Sie können auch Profile zum Kontextmenü des Taskleistensymbols hinzufügen, um die Helligkeit schnell auf Werte dieser vordefinierten Profile festzulegen.", "SETTINGS_PROFILES_NAME": "Profil-Name", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Helligkeit festlegen, wenn aktiv", "SETTINGS_PROFILES_SHOW_MENU": "Im Kontextmenü des Taskleistensymboles einblenden", "SETTINGS_PROFILES_TRIGGER_TITLE": "Programm-Auslöser-Einstellungen", "SETTINGS_PROFILES_APP_PATH": "Programmpfad", "SETTINGS_PROFILES_APP_DESC": "Wenn Sie wollen, dass dieses Profil sich automatisch aktiviert, wenn ein bestimmtes Programm im Vordergrund ist, geben Sie bitte den vollen oder teilweisen Pfad der ausführbaren Datei (.exe) an.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Overlay-Typ überschreiben", "SETTINGS_PROFILES_OVERLAY_DESC": "Passt das Verhalten des Tastenkombinations-Overlays an, wenn das definierte Programm im Fokus ist. Diese Funktion ist nicht verfügbar, wenn das Profil manuell aktiviert wird.", "SETTINGS_FEATURES_POWER_OFF": "Ausschalten", "SETTINGS_GENERAL_REPORT_TITLE": "Bericht generieren", "SETTINGS_GENERAL_REPORT_DESC": "Zu Fehlerbehebungszwecken eine Textdatei mit Informationen über Monitore und Einstellungen speichern.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Medienwiedergabe verhindert Inaktivitäts-Erkennung", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Inaktivitäts-Erkennung deaktivieren, während Medien wiedergegeben werden. Dies schließt sowohl Video als auch Audiowiedergaben ein. Funktioniert nur, wenn Windows erkennt, dass Medien wiedergegeben werden.", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Bildlauf (Scrollen) invertieren", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Mausrad-Richtung invertieren, wenn die Helligkeit über das Symbolleisten-Icon angepasst wird.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Auf Sperrbildschirm deaktivieren", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Greifen Sie nicht auf Monitore zu, während die Benutzersitzung gesperrt ist, um Konflikte in Mehrbenutzerumgebungen zu vermeiden.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR Display Lagen", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Aktivier SDR Helligkeit Schieber für spezifisch Monitore. Die Monitore müssen haben HDR aktiviert in Fenster für dies zu arbeiten.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR Tauscht aus Primären Schieber", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Aufsicht SDR Helligkeit von hauptsächlich Helligkeit Schieber #während HDR ist tätig.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR Helligkeit", "GENERIC_NOT_SUPPORTED": "Nicht unterstützt", "GENERIC_SUPPORTED": "#Abgestützt", "GENERIC_UNSUPPORTED": "Unsupported", "GENERIC_ACTIVE": "Tätig", "GENERIC_DETECTING_DISPLAYS": "#Herausfinden Displays…", "PANEL_LABEL_INPUTS": "Inputs", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Fenster UI Stil", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Thema Update Entdeckung", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Findet heraus Akzent/Tapete/Thema Änderungen von Fenster zu verbessern die Tablett Ikone und #Glimmer Effekt. #Ausschalten dies darf helfen ob ein 3rd Party #App ist häufig das Thema wechseln, ansteigender #CPU Gebrauch.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "#Monitor #ausrüsten staatliche Entdeckung", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Findet heraus Änderungen zu den Kraft Staat von Monitore. #Ausschalten dies darf helfen ob du erfährst #wann Fehler Monitore sind abgestellt/weiter oder sind #leerlaufen. Bedürft einen #Neuanfang zu wirken.", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_TIME_USE_SUN_POSITION": "Nutzung Sonne Stelle", "SETTINGS_HOTKEY_ADD_ACTION": "Füg zu Aktion", "GENERIC_CALIBRATION_POINT": "Justierung Punkt", "GENERIC_SLIDER_INDICATOR_TYPE": "Schieber Anzeiger Typ", "GENERIC_ICON": "Ikone", "GENERIC_TEXT": "Text", "GENERIC_SLIDER_ICON": "Schieber Ikone", "GENERIC_SLIDER_TEXT": "Schieber Text", "GENERIC_SLIDER_NAME": "Betritt Namen für Schieber", "SETTINGS_MONITORS_CALIBRATION_DESC": "Jeder Monitor kann individuelle Justierung Punkte haben fügten zu zu kompensieren für Unterschiede in Helligkeit Kurven. Der Input Wert #hindeuten der Helligkeit Level auf dem Schieber, während ist der Ausgabe Wert die effektive Helligkeit Level beworben zu dem Monitor.", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "Verbunden zu Helligkeit", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Stopp nach diesen Helligkeit Level", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "Ob eure Monitor Nutzungen ein #atypisch VCP Code für Helligkeit (wie 0x13 oder 0x6B), oder ob du wolltest mögen zu remap der Helligkeit Schieber zu ein verschiedenes VCP Code, du kannst jenen Code betreten unten.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "#Verlassen #ausleeren für #voreingestellt (0x10). Finde #abgestützt Codes in der Liste unten." } ================================================ FILE: src/localization/el.json ================================================ { "LANGUAGE": "Greek", "GENERIC_OK": "ΟΚ", "GENERIC_CANCEL": "Ματαίωση", "GENERIC_SAVE": "Αποθήκευση", "GENERIC_CLEAR": "Καθαρισμός", "GENERIC_DELETE": "Διαγραφή", "GENERIC_OFF": "Κλειστό", "GENERIC_ON": "Ανοιχτό", "GENERIC_QUIT": "Έξοδος", "GENERIC_CLOSE": "Κλείσιμο", "GENERIC_SETTINGS": "Ρυθμίσεις", "GENERIC_INSTALL": "Εγκατάσταση", "GENERIC_DISMISS": "Απόρριψη", "GENERIC_DEFAULT": "Προεπιλεγμένο", "GENERIC_OPTIONAL": "Προαιρετικό", "GENERIC_DISPLAY_SINGLE": "Οθόνη", "GENERIC_ALL_DISPLAYS": "Όλες οι οθόνες", "GENERIC_REFRESH_DISPLAYS": "Ανανέωση οθονών", "GENERIC_MINIMUM": "Ελάχιστο", "GENERIC_MAXIMUM": "Μέγιστο", "GENERIC_NO_DISPLAYS": "Δεν εντοπίστηκαν οθόνες. Συνδέστε μια οθόνη στον υπολογιστή σας.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Δεν βρέθηκαν συμβατές οθόνες. Ελέγξτε ότι το \"DDC/CI\" είναι ενεργοποιημένο για τις οθόνες σας.", "GENERIC_NO_DISPLAYS_SHORT": "Δεν εντοπίστηκαν συμβατές οθόνες.", "GENERIC_SECONDS": "δευτερόλεπτα", "GENERIC_MINUTES": "λεπτά", "GENERIC_DDC_WARNING": "Οι λειτουργίες DDC/CI, όπως ο έλεγχος της κατάστασης τροφοδοσίας, μπορεί να κάνουν την οθόνη σας να μην αποκρίνεται. Χρησιμοποιήστε το με δική σας ευθύνη.", "GENERIC_SPEED_INSTANT": "Άμεσο", "GENERIC_SPEED_SLOW": "Αργό", "GENERIC_SPEED_VERY_SLOW": "Πολύ αργό", "GENERIC_SPEED_NORMAL": "Κανονικό", "GENERIC_SPEED_FAST": "Γρήγορο", "GENERIC_SPEED_VERY_FAST": "Πολύ γρήγορο", "GENERIC_PAUSE_TOD": "Παύση προσαρμογών χρόνου", "GENERIC_PAUSE_IDLE": "Παύση ανίχνευσης αδράνειας", "PANEL_TITLE": "Ρύθμιση φωτεινότητας", "PANEL_UPDATE_AVAILABLE": "Νέα έκδοση διαθέσιμη", "PANEL_BUTTON_LINK_LEVELS": "Επίπεδα σύνδεσης", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Απενεργοποιήστε τις οθόνες", "PANEL_LABEL_BRIGHTNESS": "Φωτεινότητα", "PANEL_LABEL_CONTRAST": "Αντίθεση", "PANEL_LABEL_OFF_ON": "Κατάσταση ισχύος", "PANEL_LABEL_COLOR_TEMPERATURE": "Θερμοκρασία χρώματος", "PANEL_LABEL_VOLUME": "Ενταση ήχου", "PANEL_LABEL_TURN_OFF": "Απενεργοποίηση", "PANEL_LABEL_TURN_ON": "Ενεργοποίηση", "INTRO_TITLE": "Γειά σου, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Το εικονίδιο συστήματος για το Twinkle Tray είναι πιθανώς κρυμμένο, επομένως θα πρέπει να το μετακινήσετε σε κάποιο μέρος όπου μπορείτε να έχετε εύκολη πρόσβαση. Δείτε παρακάτω για οδηγίες.", "SETTINGS_TITLE": "Ρυθμίσεις Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Γενικά", "SETTINGS_SIDEBAR_MONITORS": "Ρυθμίσεις οθόνης", "SETTINGS_SIDEBAR_FEATURES": "Δυνατότητες DDC/CI", "SETTINGS_SIDEBAR_TIME": "Ρυθμίσεις χρόνου", "SETTINGS_SIDEBAR_HOTKEYS": "Πλήκτρα συντόμευσης και συντομεύσεις", "SETTINGS_SIDEBAR_UPDATES": "Ενημερώσεις", "SETTINGS_GENERAL_TITLE": "Γενικά", "SETTINGS_GENERAL_STARTUP": "Αυτόματη εκκίνηση με τα Windows", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Εφαρμόστε φωτεινότητα κατά την εκκίνηση", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Επαναφέρετε την τελευταία γνωστή φωτεινότητα για κάθε οθόνη όταν ξεκινά το Twinkle Tray.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Απενεργοποίηση στην Οθόνη Κλειδώματος", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Να μην υπάρχει πρόσβαση στις οθόνες όσο το session είναι κλειδωμένο, ωστέ να αποφευχθούν συγκούσεις σε περιβάλλοντα πολλαπλών χρηστών.", "SETTINGS_GENERAL_THEME_TITLE": "Θέμα", "SETTINGS_GENERAL_THEME_SYSTEM": "Προτιμήσεις συστήματος (προεπιλογή)", "SETTINGS_GENERAL_THEME_DARK": "Σκούρο", "SETTINGS_GENERAL_THEME_LIGHT": "Ανοιχτό", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Γλώσσα", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Γλώσσα συστήματος (προεπιλογή)", "SETTINGS_GENERAL_RESET_TITLE": "Επαναφορά ρυθμίσεων", "SETTINGS_GENERAL_RESET_DESC": "Πατήστε αυτό το κουμπί για να διαγράψετε τις ρυθμίσεις σας.", "SETTINGS_GENERAL_RESET_BUTTON": "Επαναφορά ρυθμίσεων", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Ακρυλικό Θάμπωμα", "SETTINGS_GENERAL_ACRYLIC_DESC": "Ενεργοποιήστε ή απενεργοποιήστε το θάμπωμα πίσω από διαφανές φόντα στο Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Θόλωμα Mica", "SETTINGS_GENERAL_MICA_DESC": "Ενεργοποιήστε ή απενεργοποιήστε το θάμπωμα πίσω από διαφανές φόντο στο Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Αναλυτικά στοιχεία", "SETTINGS_GENERAL_ANALYTICS_DESC": "Στείλτε δεδομένα χρήσης για να βελτιώσετε το Twinkle Tray. Δεν αποστέλλονται προσωπικά στοιχεία. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Μάθε περισσότερα", "SETTINGS_GENERAL_SCROLL_TITLE": "Εικονίδιο συστήματος συντόμευσης κύλισης", "SETTINGS_GENERAL_SCROLL_DESC": "Προσαρμόστε τη φωτεινότητα όλων των οθονών ταυτόχρονα κάνοντας κύλιση πάνω από το εικονίδιο της γραμμής ειδοποιήσεων συστήματος. Αυτό δεν λειτουργεί με ορισμένα χειριστήρια αφής.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Εικονίδιο συστήματος", "SETTINGS_GENERAL_TROUBLESHOOTING": "Αντιμετώπιση προβλημάτων", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Ενεργοποιημένες μέθοδοι ανίχνευσης οθόνης", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Εάν το Twinkle Tray δεν ανταποκρίνεται όταν κάνετε κλικ στο εικονίδιο συστήματος ή δεν εντοπίζει τις οθόνες σας, μπορείτε να δοκιμάσετε να απενεργοποιήσετε ορισμένες μεθόδους ανίχνευσης οθόνης. Επανεκκινήστε το Twinkle Tray για να τεθούν σε ισχύ οι αλλαγές. {{1}}", "SETTINGS_GENERAL_OVERLAY_TITLE": "Προεπιλεγμένη συμπεριφορά επικάλυψης", "SETTINGS_GENERAL_OVERLAY_DESC": "Πόσο εξαναγκασμένα το πλήκτρο συντόμευσης της φωτεινότητας θα επιχειρήσει να σχεδίασει πάνω από άλλες εφαρμογές.", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Απενεργοποιήστε την επικάλυψη", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Εάν η επικάλυψη πλήκτρων συντόμευσης του Twinkle Tray παρεμβαίνει σε εφαρμογές πλήρους οθόνης, μπορείτε να το απενεργοποιήσετε εδώ.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Το πιο συμβατό", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Η επικάλυψη θα εμφανίζεται πάνω στα περισσότερα παράθυρα, αλλά δεν θα επιβάλλεται πάνω από εφαρμογές που είναι επισημασμένες με \"always on top\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Ενεργός εξαναγκασμός", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Πάντα να γίνεται προσπάθεια να φαίνεται η επικάλυψη πάνω από άλλα παράθυρα. Αυτή η επιλογή μπορεί να προκαλέσει προβλήματα με παιχνίδια αποκλειστικά πλήρης οθόνης και άλλες εφαρμογές πλήρης οθόνης. Επίσης μπορεί να ενεργοποιήσει το anti-cheat σε μερικά παιχνίδια.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Μέθοδος ανίχνευσης Legacy DDC/CI", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Χρήση της παλαιάς μεθόδου v1.15.5 για την ανίχνευση DDC/CI οθονών.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Αυτομάτη εφαρμογή φωτεινότητας", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Αν η οθόνη σας ανταποκρίνεται περίεργα μετά από απενεργοποίηση/ενεργοποίηση ή αποσύνδεση/σύνδεση υλικού, η απενεργοποίηση αυτής της επολογής ίσως βοηθήσει.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Παράληψη αυτόματης εφαρμογής σε συγκεκριμένες οθόνες", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Απενεργοποίηση αυτόματης εφαρμογής γνωστής φωτεινότητας μετά από περιστατικά υλικού/ενέργειας για συγκεκριμένες οθόνες. Αυτό συμπεριλαμβάνει την λειτουργία ανίχνευσης αδράνειας.", "SETTINGS_GENERAL_REPORT_TITLE": "Δημιουργία Αναφοράς", "SETTINGS_GENERAL_REPORT_DESC": "Αποθήκευση αρχείου κειμένου με τις πληροφορίες για όλες τις οθόνες σας και τις ρυθμίσεις για εντοπισμό σφαλμάτων.", "SETTINGS_MONITORS_RATE_TITLE": "Ρυθμός ενημέρωσης φωτεινότητας", "SETTINGS_MONITORS_RATE_DESC": "Πόσο συχνά θα ενημερώνεται η φωτεινότητα στις οθόνες σας καθώς προσαρμόζετε τις τιμές τους. Αυξήστε το χρόνο εάν οι οθόνες σας τρεμοπαίζουν.", "SETTINGS_MONITORS_RATE_0": "Πολύ γρήγορα", "SETTINGS_MONITORS_RATE_1": "Γρήγορο (250 ms)", "SETTINGS_MONITORS_RATE_2": "Κανονικό (500 ms)", "SETTINGS_MONITORS_RATE_3": "Αργό (1 second)", "SETTINGS_MONITORS_RATE_4": "Πολύ αργό (2 seconds)", "SETTINGS_MONITORS_RENAME_TITLE": "Μετονομασία οθονών", "SETTINGS_MONITORS_RENAME_DESC": "Αν προτιμάτε διαφορετικό όνομα για κάθε οθόνη (π.χ. \"Αριστερή οθόνη\", \"Μεσαία οθόνη\"), μπορείτε να το εισάγετε παρακάτω. Αν αφήσετε το πεδίο κενό θα επαναφέρει το αρχικό όνομα.", "SETTINGS_MONITORS_ENTER_NAME": "Εισάγετε όνομα", "SETTINGS_MONITORS_REORDER_TITLE": "Αναδιάταξη οθονών", "SETTINGS_MONITORS_REORDER_DESC": "Αλλάξτε τη σειρά εμφάνισης των οθονών στην περιοχή ειδοποιήσεων. Κάντε κλικ και σύρετε για να κάνετε αλλαγές.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Κανονικοποίηση Φωτεινότητας", "SETTINGS_MONITORS_NORMALIZE_DESC": "Οι οθόνες έχουν συχνά διαφορετικά εύρη φωτεινότητας. Περιορίζοντας την ελάχιστη/μέγιστη φωτεινότητα ανά οθόνη, τα επίπεδα φωτεινότητας μεταξύ των οθονών είναι πολύ πιο συνεπή. Παρόμοιες οθόνες θα χρησιμοποιούν τις ίδιες ρυθμίσεις.", "SETTINGS_MONITORS_DETAILS_NAME": "Όνομα", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Εσωτερικό Όνομα", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Μέθοδος Επικοινωνίας", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Τρέχουσα φωτεινότητα", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Μέγιστη φωτεινότητα", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Κανονικοποίηση φωτεινότητας", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Απόκρυψη ανενεργής εσωτερικής οθόνης", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Όταν το καπάκι είναι κλειστό ή η εσωτερική οθόνη έχει απενεργοποιηθεί στα Windows, αποκρύψτε το ρυθμιστικό φωτεινότητας στον πίνακα.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Απόκρυψη οθονών", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Εάν θέλετε να αποκρύψετε συγκεκριμένες οθόνες από το αναδυόμενο παράθυρο, μπορείτε να τις απενεργοποιήσετε εδώ.", "SETTINGS_FEATURES_DESCRIPTION": "Ενεργοποιήστε ή απενεργοποιήστε συγκεκριμένες λειτουργίες DDC/CI στον πίνακα φωτεινότητας. Τουλάχιστον μία δυνατότητα πρέπει να είναι ενεργοποιημένη για να εμφανίζεται η οθόνη σας στον πίνακα φωτεινότητας. Δεν υποστηρίζουν όλες οι οθόνες αυτές τις δυνατότητες, όπως οθόνες laptop/tablet.", "SETTINGS_FEATURES_UNSUPPORTED": "Αυτή η οθόνη δεν υποστηρίζει λειτουργίες DDC/CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Έλεγχος Τρεχουσών Τιμών", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Να λαμβάνετε πάντα το πιο πρόσφατο επίπεδο φωτεινότητας από την οθόνη όταν ανοίγετε τη σελίδα φωτεινότητας. Ενεργοποιήστε το εάν η φωτεινότητα (ή άλλοι κωδικοί VCP όπως η Αντίθεση) αλλάζει συχνά έξω από το Twinkle Tray (π.χ. άλλη εφαρμογή).", "SETTINGS_FEATURES_POWER_TITLE": "Σήμα Κατάστασης Τροφοδοσίας", "SETTINGS_FEATURES_POWER_DESC": "Όταν αποστέλλεται η εντολή DDC/CI για να απανεργοποιηθεί η οθόνη σας, οι ακόλουθες τιμές θα σταλθούν.", "SETTINGS_FEATURES_POWER_STANDBY": "Αναμονή", "SETTINGS_FEATURES_POWER_OFF": "Απενεργοποίηση", "SETTINGS_FEATURES_POWER_COMPAT": "Το πιο συμβατό", "SETTINGS_FEATURES_POWER_WARNING": "Η επιλογή \"Standby\" είνα πολύ πιθανό να επιτρέπει την απενεργοποίηση/ενεργοποίηση της οθόνης από το Twinkle Tray. Ωστόσο, πολλές οθόνες δεν ανταποκρίνονται σωστά στην αλλαγή της κατάστασης τροφοδοσίας. Χρησιμοποιήστε το με δική σας ευθύνη.", "SETTINGS_FEATURES_ADD": "Προσθήκη Δυνατότητας", "SETTINGS_FEATURES_ADD_DESC": "Εισάγετε το κωδικό VCP για την δυνατότηταπου θέλετε να προσθέσετε στην οθόνη σας. Παρακαλώ να σημειωθεί ότι το Twinkle Tray δεν επιβεβαιώνει ότι η οθόνη σας υποστηρίζει στην πραγματικότητα το κωδικό VCP. Χρησιμοποιήστε το με δική σας ευθύνη.", "SETTINGS_FEATURES_ADD_VCP": "Κωδικός VCP", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "Κωδικός VCP (Ex. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Αυτή η δυνατότητα είναι ήδη ενεργοποιημένη.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Όλοι οι κωδικοί VCP που δηλώνονται από την οθόνη", "SETTINGS_FEATURES_VCP_LIST_DESC": "Η ακόλουθη λίστα αποτελείται από διαθέσιμους κωδικούς VCP που δηλώνονται από την οθόνη στα Windows. Το Twinkle Tray δεν επιβεβαιώνει την λειτουργεικότητα ή την σταθερότητα αυτών των κωδικών VCP. Χρησιμοποιήστε το με δική σας ευθύνη.", "SETTINGS_FEATURES_VCP_EXPECTED": "Αναμενόμενες τιμές", "SETTINGS_TIME_TITLE": "Ρυθμίσεις ώρας ημέρας", "SETTINGS_TIME_DESC": "Ρυθμίστε αυτόματα τις οθόνες σας σε ένα συγκεκριμένο επίπεδο φωτεινότητας την επιθυμητή στιγμή. Όλες οι οθόνες θα ρυθμιστούν στα ίδια, κανονικοποιημένα επίπεδα.", "SETTINGS_TIME_ADD": "Προσθέστε ένα χρόνο", "SETTINGS_TIME_REMOVE": "Αφαιρέστε το χρόνο", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Ρυθμίστε τη φωτεινότητα για μεμονωμένες οθόνες", "SETTINGS_TIME_INDIVIDUAL_DESC": "Διαμορφώστε τη φωτεινότητα ανά οθόνη αντί για όλες τις οθόνες ταυτόχρονα.", "SETTINGS_TIME_TRANSITON_TITLE": "Ταχύτητα μετάβασης φωτεινότητας", "SETTINGS_TIME_TRANSITON_DESC": "Πόσο γρήγορα θα πρέπει να μεταβάλλεται η φωτεινότητα όταν ενεργοποιούνται οι ρυθμίσεις ώρας της ημέρας.", "SETTINGS_TIME_STARTUP_TITLE": "Ελέγξτε κατά την εκκίνηση της εφαρμογής", "SETTINGS_TIME_STARTUP_DESC": "Προσαρμόστε τη φωτεινότητα ώστε να ταιριάζει με την πιο σχετική ώρα κατά την εκκίνηση του Twinkle Tray.", "SETTINGS_TIME_IDLE_TITLE": "Ανίχνευση αδράνειας", "SETTINGS_TIME_IDLE_DESC": "Όταν δεν έχει εντοπιστεί είσοδος για κάποιο χρονικό διάστημα, η φωτεινότητα όλων των οθονών θα μειωθεί.", "SETTINGS_TIME_ANIMATE_TITLE": "Ζωντάνεμα μεταξύ των συμβάντων", "SETTINGS_TIME_ANIMATE_DESC": "Οι τιμές φωτεινότητας θα κινούνται μεταξύ του τρέχοντος και του επόμενου προγραμματισμένου συμβάντος. Μπορεί να αυξήσει τη χρήση της CPU. Οι χειροκίνητες ρυθμίσεις φωτεινότητας θα αντικατασταθούν γρήγορα ενώ αυτό είναι ενεργό.", "SETTINGS_TIME_SUN_TITLE": "Συντεταγμένες για την θέση του ηλίου", "SETTINGS_TIME_SUN_DESC": "Για να χρησιμοποιήσετε τις \"sun position\" για προσαρμογές ώρας, είσαγετε τo τρεχούμενο γεωγραφικό σας πλάτος και το γεωγραφικό σας μήκος ωστέ οι σωστές ώρες να μπορούν να καθοριστούν.", "SETTINGS_TIME_LAT": "Γεωγραφικό πλάτος", "SETTINGS_TIME_LONG": "Γεωγραφικό μήκος", "SETTINGS_TIME_SUN_GET": "Λάβε συντεταγμένες", "SETTINGS_TIME_IDLE_FS_TITLE": "Οι εφαρμογές πλήρους οθόνης να εμποδίζουν την ανίχνευση αδράνειας", "SETTINGS_TIME_IDLE_FS_DESC": "Οι εφαρμογές πλήρους οθόνης να εμποδίζουν την ανίχνευση αδράνειας. Αυτό εφαρμόζεται μόνο στο εστιασμένο παράθυρο.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Η αναπαραγωγή περιεχομένου να εμποδίζει την ανίχνεση αδράνειας", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Η ανίχνευση αδράνειας θα είναι απενεργοποιήμενη όταν υπάρχει οποιαδήποτε αναπαραγωγή περιεχομένου. Εφαρμόζεται μόνο όταν τα Windows εντοπίζουν ότι γίνεται αναπαραγωγή περιεχομένου.", "SETTINGS_HOTKEYS_TITLE": "Πλήκτρα συντόμευσης", "SETTINGS_HOTKEYS_DESC": "Διαμορφώστε τα πλήκτρα πρόσβασης για να προσαρμόσετε τη φωτεινότητα μιας ή όλων των οθονών.", "SETTINGS_HOTKEYS_ADD": "Προσθήκη Πλήκτρου Συντόμευσης", "SETTINGS_HOTKEYS_REMOVE": "Αφαίρεση πλήκτρου συντόμευσης", "SETTINGS_HOTKEYS_INCREASE": "Αύξηση φωτεινότητας", "SETTINGS_HOTKEYS_DECREASE": "Μείωση φωτεινότητας", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Πατήστε τα πλήκτρα εδώ", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Ρύθμιση επιπέδου φωτεινότητας", "SETTINGS_HOTKEYS_LEVEL_DESC": "Πόσο πρέπει να ρυθμίζεται η φωτεινότητα όταν χρησιμοποιείτε πλήκτρα συντόμευσης.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Ισοδυναμία σε κύλιση", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Αντιστροφή κύλισης", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Όταν κάνετε κύλιση πάνω από το εικονίδιο συστήματος, η κατεύθυνση κύλισης θα είναι αντίστροφη.", "SETTINGS_HOTKEYS_TOD_TITLE": "Απενεργοποιήστε τις οθόνες", "SETTINGS_HOTKEYS_TOD_DESC": "Προσαρμόστε το σήμα που αποστέλλεται όταν χρησιμοποιείτε το πλήκτρο πρόσβασης ή το εικονίδιο Απενεργοποίηση Οθονών. Το σήμα λογισμικού θα εμφανίσει μια μαύρη οθόνη μέχρι να εντοπιστεί η είσοδος (π.χ. ποντίκι ή πληκτρολόγιο) από τα Windows. Το σήμα υλικού θα απενεργοποιήσει την τροφοδοσία των οθονών.", "SETTINGS_HOTKEYS_TOD_NONE": "Κανένα (απόκρυψη εικονιδίου)", "SETTINGS_HOTKEYS_TOD_SOFT": "Σήμα λογισμικού (προεπιλογή)", "SETTINGS_HOTKEYS_TOD_HARD": "Σήμα υλικού* (μόνο DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Σήμα υλικού* και λογισμικού", "SETTINGS_HOTKEYS_TOD_NOTE": "*Σημείωση: Δεν υποστηρίζουν όλες οι οθόνες DDC/CI αυτή τη δυνατότητα.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Τα πλήκτρα συντόμευσης διακόπτουν τα συνδεδεμένα επίπεδα", "SETTINGS_HOTKEYS_BREAK_DESC": "Όταν χρησιμοποιείτε ένα πλήκτρο συντόμευσης για μία οθόνη και το \"συνδεδεμένα επίπεδα\" είναι ενεργό, θα απενεργοποιηθεί.", "SETTINGS_HOTKEY_OFF_WARN": "Αυτή η δράση θα χρησιμοποιεί την ρύθμιση κάτω από την επιλογή \"Turn Off Displays action\". Αντ'αυτού αν επιθυμείτε να απενεργοποιήσετε συγκεκριμένες οθόνες, χρησιμοποιείστε το \"Set\" ή το \"Cycle\" συντόμευσης δράσης αντί αυτού.", "SETTINGS_HOTKEY_TARGET": "Στόχος δράσης", "SETTINGS_HOTKEY_VALUE": "Τιμή", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Εισάγετε έναν αριθμό", "SETTINGS_HOTKEY_VALUES": "Τιμές", "SETTINGS_HOTKEY_ADD_VALUE": "Προσθήκη Τιμής", "SETTINGS_HOTKEY_ACTION": "Δράση", "SETTINGS_HOTKEY_ACTION_SET": "Εφαρμογή τιμής", "SETTINGS_HOTKEY_ACTION_OFFSET": "Προσαρμογή τιμής", "SETTINGS_HOTKEY_ACTION_CYCLE": "Λίστα τιμών", "SETTINGS_PROFILES_TITLE": "Προφίλ", "SETTINGS_PROFILES_DESC": "Αυτόματη προσαρμογή της φωτεινότητας ή την συμπεριφορά της συντόμευσης επικάλυψης βασισμένη στην εστιασμένη εφαρμογή. Μπορείτε ακόμα να προσθέσετε προφίλ στο δεξί-κλικ μενού του εικονιδίου συστήματος για να αλλάζετε γρήγορα την φωτεινότητα στα προκαθορισμένα προφίλ.", "SETTINGS_PROFILES_ADD": "Νέο Προφίλ", "SETTINGS_PROFILES_NAME": "Όνομα Προφίλ", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Εφαρμογή φωτεινότητας όταν είναι ενεργοποιημένη", "SETTINGS_PROFILES_SHOW_MENU": "Προβολή στο δεξί-κλικ μενού στο εικονίδιο συστήματος", "SETTINGS_PROFILES_TRIGGER_TITLE": "Ρυθμίσεις ενεργοποίησης εφαρμογής", "SETTINGS_PROFILES_APP_PATH": "Διαδρομή/Path εφαρμογής", "SETTINGS_PROFILES_APP_DESC": "Αν θέλετε αυτό το προφίλ να ενεργοποιείται αυτόματα όταν μια συγκεκριμένη εφαρμογή είναι εστιασμένη, εισάγετε από κάτω την ολοκληρή ή την μερικη διαδρόμη της εφαρμογής αυτής(EXE).", "SETTINGS_PROFILES_OVERLAY_TITLE": "Τύπος παράκαμψης επικάλυψης", "SETTINGS_PROFILES_OVERLAY_DESC": "Αλλάζει την συμπεριφορά του πλήκτρου συντόμευσης επικάλυψης όταν η συγκεκριμένη εφαρμογή είναι εστιασμένη. Η δυνατότητα δεν λειτουργεί όταν το προφίλ είναι ενεργοποιημένο χειροκίνητα.", "SETTINGS_UPDATES_TITLE": "Ενημερώσεις", "SETTINGS_UPDATES_VERSION": "Έχετε το Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Αυτόματος έλεγχος για νέες εκδόσεις", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Όταν υπάρχει μια νέα έκδοση, θα εμφανίζεται στον πίνακα φωτεινότητας.", "SETTINGS_UPDATES_MS_STORE": "Για να ελέγξετε για νέες εκδόσεις, επισκεφτείτε την εφαρμογή Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Νέα έκδοση του Twinkle Tray είναι διαθέσιμη!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Ενημερωμένο. Η τρέχουσα έκδοση περιλαμβάνει τις ακόλουθες αλλαγές:", "SETTINGS_UPDATES_DOWNLOADING": "Λήψη ενημέρωσης…", "SETTINGS_UPDATES_DOWNLOAD": "Λήψη και Εγκατάσταση {{1}}", "SETTINGS_UPDATES_CHANNEL": "Κανάλι Ενημέρωσης", "SETTINGS_UPDATES_BRANCH_STABLE": "Σταθερό (προεπιλογή)", "SETTINGS_UPDATES_BRANCH_BETA": "έκδοση ΒΕΤΑ", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "Ρυθμίσεις Οθόνης HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Ενεργοποίηση ρυθμίσεων φωτεινότητας SDR για συγκεκριμνένες οθόνες. Για να λειτουργήσει, οι οθόνες πρέπει να έχουν ενεργοποιημένη τη ρύθμιση HDR στις ρυθμίσεις των Windows.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "Το SDR αντικαθιστά την κύρια μπάρα ρύθμισης", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Αν είναι ενεργοποιημένο το HDR, θα γίνει έλεγχος της SDR φωτεινότητας με την μπάρα ρύθμισης κύριας φωτεινότητας.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR Φωτεινότητα" } ================================================ FILE: src/localization/en-GB.json ================================================ { "LANGUAGE": "English (UK)", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Cancel", "GENERIC_SAVE": "Save", "GENERIC_CLEAR": "Clear", "GENERIC_DELETE": "Delete", "GENERIC_OFF": "Off", "GENERIC_ON": "On", "GENERIC_QUIT": "Quit", "GENERIC_CLOSE": "Close", "GENERIC_SETTINGS": "Settings", "GENERIC_INSTALL": "Install", "GENERIC_DISMISS": "Dismiss", "GENERIC_DEFAULT": "Default", "GENERIC_OPTIONAL": "Optional", "GENERIC_DISPLAY_SINGLE": "Display", "GENERIC_ALL_DISPLAYS": "All Displays", "GENERIC_REFRESH_DISPLAYS": "Refresh displays", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Max", "GENERIC_CALIBRATION_POINT": "Calibration Point", "GENERIC_NO_DISPLAYS": "No displays detected. Please connect a display to your PC.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "No compatible displays found. Please check that \"DDC/CI\" is enabled for your displays.", "GENERIC_NO_DISPLAYS_SHORT": "No compatible displays detected.", "GENERIC_NOT_SUPPORTED": "Not supported", "GENERIC_SUPPORTED": "Supported", "GENERIC_UNSUPPORTED": "Unsupported", "GENERIC_ACTIVE": "Active", "GENERIC_SECONDS": "seconds", "GENERIC_MINUTES": "minutes", "GENERIC_DDC_WARNING": "DDC/CI features can cause your monitor to become unresponsive. Use at your own risk.", "GENERIC_SPEED_INSTANT": "Instant", "GENERIC_SPEED_SLOW": "Slow", "GENERIC_SPEED_VERY_SLOW": "Very Slow", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_SPEED_FAST": "Fast", "GENERIC_SPEED_VERY_FAST": "Very fast", "GENERIC_PAUSE_TOD": "Pause Time Adjustments", "GENERIC_PAUSE_IDLE": "Pause Idle Detection", "GENERIC_DETECTING_DISPLAYS": "Detecting displays…", "GENERIC_SLIDER_INDICATOR_TYPE": "Slider Indicator Type", "GENERIC_ICON": "Icon", "GENERIC_TEXT": "Text", "GENERIC_SLIDER_ICON": "Slider Icon", "GENERIC_SLIDER_TEXT": "Slider Text", "GENERIC_SLIDER_NAME": "Enter name for slider", "PANEL_TITLE": "Adjust Brightness", "PANEL_UPDATE_AVAILABLE": "New version available", "PANEL_BUTTON_LINK_LEVELS": "Link levels", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Turn off displays", "PANEL_LABEL_BRIGHTNESS": "Brightness", "PANEL_LABEL_CONTRAST": "Contrast", "PANEL_LABEL_INPUTS": "Inputs", "PANEL_LABEL_OFF_ON": "Power State", "PANEL_LABEL_COLOR_TEMPERATURE": "Colour Temperature", "PANEL_LABEL_VOLUME": "Volume", "PANEL_LABEL_TURN_OFF": "Power off", "PANEL_LABEL_TURN_ON": "Power on", "INTRO_TITLE": "Hello, Twinkle Tray!", "INTRO_INSTRUCTIONS": "The tray icon for Twinkle Tray is probably hidden, so you should move it to some place you can easily access it. See below for instructions.", "SETTINGS_TITLE": "Twinkle Tray Settings", "SETTINGS_SIDEBAR_GENERAL": "General", "SETTINGS_SIDEBAR_MONITORS": "Monitor Settings", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI Features", "SETTINGS_SIDEBAR_TIME": "Time Adjustments", "SETTINGS_SIDEBAR_HOTKEYS": "Hotkeys & Shortcuts", "SETTINGS_SIDEBAR_UPDATES": "Updates", "SETTINGS_GENERAL_TITLE": "General", "SETTINGS_GENERAL_STARTUP": "Launch at startup", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Apply brightness at startup", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Restore the last known brightness for each display when Twinkle Tray starts.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Disable on Lock Screen", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Don't access monitors while the user session is locked to avoid conflicts in multi-user environments.", "SETTINGS_GENERAL_THEME_TITLE": "Theme", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Windows UI Style", "SETTINGS_GENERAL_THEME_SYSTEM": "System preferences (default)", "SETTINGS_GENERAL_THEME_DARK": "Dark", "SETTINGS_GENERAL_THEME_LIGHT": "Light", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Language", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "System language (default)", "SETTINGS_GENERAL_RESET_TITLE": "Reset settings", "SETTINGS_GENERAL_RESET_DESC": "Hit this button to clear your config.", "SETTINGS_GENERAL_RESET_BUTTON": "Reset settings", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Acrylic Blur", "SETTINGS_GENERAL_ACRYLIC_DESC": "Enable or disable the blur behind transparent backgrounds in Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Mica Blur", "SETTINGS_GENERAL_MICA_DESC": "Enable or disable the blur behind backgrounds in Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analytics", "SETTINGS_GENERAL_ANALYTICS_DESC": "Send usage data to help improve Twinkle Tray. No personal info is sent. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Learn more", "SETTINGS_GENERAL_SCROLL_TITLE": "Tray icon scroll shortcut", "SETTINGS_GENERAL_SCROLL_DESC": "Adjust the brightness of all displays at once by scrolling over the system tray icon. This does not work with some trackpads.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Tray icon", "SETTINGS_GENERAL_TROUBLESHOOTING": "Troubleshooting", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Enabled monitor detection methods", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "If Twinkle Tray is unresponsive when clicking on the tray icon or not detecting your displays, you can try disabling certain monitor detection methods. Restart Twinkle Tray for changes to take effect. {{1}}", "SETTINGS_GENERAL_OVERLAY_TITLE": "Default overlay behaviour", "SETTINGS_GENERAL_OVERLAY_DESC": "How forcefully the brightness hotkey overlay will attempt to display over other apps. You should not need to adjust this.", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Disable overlay", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "If Twinkle Tray's hotkey overlay is interfering with fullscreen applications, you can disable it here.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Most compatible", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "The overlay will display over most windows, but will not force itself above apps that are marked as \"always on top\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Forced on", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Always try to show the overlay on top of other windows. This can cause issues with exclusive fullscreen games and other fullscreen apps. It can also trigger anti-cheat in some games.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Legacy DDC/CI detection method", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Use the old v1.15.5 method of detecting DDC/CI displays.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Auto-apply brightness", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "If your monitor responds strangely after turning it off/on or disconnecting/connecting hardware, disabling this may help.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Skip auto-apply to specific monitors", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Disable auto-applying known brightness after all hardware/power events for specific monitors. This include the idle detection feature.", "SETTINGS_GENERAL_REPORT_TITLE": "Generate Report", "SETTINGS_GENERAL_REPORT_DESC": "Save a text file with information about your monitors and settings for debugging.", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Theme update detection", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Detects accent/wallpaper/theme changes from Windows to update the tray icon and Mica effect. Disabling this may help if a 3rd party app is frequently changing the theme, increasing CPU usage.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Monitor power state detection", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Detects changes to the power state of monitors. Disabling this may help if you experience errors when monitors are turned off/on or are idle. Requires a restart to take effect.", "SETTINGS_MONITORS_RATE_TITLE": "Brightness update rate", "SETTINGS_MONITORS_RATE_DESC": "How often the brightness will be updated on your displays as you're adjusting their values. Increase the time if your displays are flickering.", "SETTINGS_MONITORS_RATE_0": "Ludicrous", "SETTINGS_MONITORS_RATE_1": "Fast (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Slow (1 second)", "SETTINGS_MONITORS_RATE_4": "Very Slow (2 seconds)", "SETTINGS_MONITORS_RENAME_TITLE": "Rename Monitors", "SETTINGS_MONITORS_RENAME_DESC": "If you'd prefer a different name for each monitor (ex \"Left Monitor\", \"Middle Monitor\"), you can enter it below. Leaving the field empty will restore the original name.", "SETTINGS_MONITORS_ENTER_NAME": "Enter name", "SETTINGS_MONITORS_REORDER_TITLE": "Reorder Monitors", "SETTINGS_MONITORS_REORDER_DESC": "Change the order that monitors are displayed in the tray. Click and drag to make changes.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalise Brightness", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitors often have different brightness ranges. By limiting the min/max brightness per display, the brightness levels between displays is much more consistent.", "SETTINGS_MONITORS_CALIBRATION_DESC": "Each monitor can have individual calibration points added to compensate for differences in brightness curves. The input value is the brightness level indicated on the slider, while the output value is the actual brightness level applied to the monitor.", "SETTINGS_MONITORS_DETAILS_NAME": "Name", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Internal Name", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Communication Method", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Current Brightness", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Max Brightness", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Brightness Normalisation", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Hide Inactive Internal Display", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "When the lid is closed or the internal display has been disabled in Windows, hide the brightness slider in the panel.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Hide Displays", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "If you would like to hide specific displays from the flyout, you can toggle them off here.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR Display Settings", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Enable SDR brightness sliders for specific monitors. The monitors must have HDR enabled in Windows for this to work.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR Replaces Primary Slider", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Control SDR brightness from main brightness slider while HDR is active.", "SETTINGS_FEATURES_DESCRIPTION": "Enable or disable specific DDC/CI features in the brightness panel. At least one feature must be enabled for your monitor to show up in the brightness panel. Not all displays support these features, such as laptop/tablet displays.", "SETTINGS_FEATURES_UNSUPPORTED": "This monitor does not support DDC/CI features.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Check Current Values", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Always get the latest values from the monitor when opening the brightness panel. Enable this if the brightness (or other VCP codes like contrast) frequently change from outside of Twinkle Tray.", "SETTINGS_FEATURES_POWER_TITLE": "Power State Signal", "SETTINGS_FEATURES_POWER_DESC": "When sending the DDC/CI command to turn off your display, the following value(s) will be sent.", "SETTINGS_FEATURES_POWER_STANDBY": "Standby", "SETTINGS_FEATURES_POWER_OFF": "Power off", "SETTINGS_FEATURES_POWER_COMPAT": "Most compatible", "SETTINGS_FEATURES_POWER_WARNING": "The \"Standby\" option is more likely to allow toggling the monitor on/off from Twinkle Tray. However, many monitors do not respond correctly to changing power state. Use at your own risk.", "SETTINGS_FEATURES_ADD": "Add Feature", "SETTINGS_FEATURES_ADD_DESC": "Enter the VCP code for the feature you would like to add to your display. Please note that Twinkle Tray does not validate if your display actually supports this VCP code. Use at your own risk.", "SETTINGS_FEATURES_ADD_VCP": "VCP Code", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP code (Ex. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "This feature is already active.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "All VCP codes reported by this display", "SETTINGS_FEATURES_VCP_LIST_DESC": "The following is a list of available VCP codes reported by this display to Windows. Twinkle Tray does not validate the functionality or stability of these VCP codes. Use them at your own risk.", "SETTINGS_FEATURES_VCP_EXPECTED": "Expected values", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR Brightness", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "Linked to brightness", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Stop after this brightness level", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "If your monitor uses a non-standard VCP code for brightness (such as 0x13 or 0x6B), or if you would like to remap the brightness slider to a different VCP code, you can enter that code below.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "Leave empty for default (0x10). Find supported codes in the list below.", "SETTINGS_TIME_TITLE": "Time of Day Adjustments", "SETTINGS_TIME_DESC": "Automatically set your monitors to a specific brightness level at a desired time. All monitors will be set to the same, normalised levels.", "SETTINGS_TIME_ADD": "Add a time", "SETTINGS_TIME_REMOVE": "Remove time", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Set brightness for individual displays", "SETTINGS_TIME_INDIVIDUAL_DESC": "Configure the brightness per display instead of for all displays at once.", "SETTINGS_TIME_TRANSITON_TITLE": "Brightness transition speed", "SETTINGS_TIME_TRANSITON_DESC": "How quickly brightness should transition when time of day adjustments are activated.", "SETTINGS_TIME_STARTUP_TITLE": "Check at app startup", "SETTINGS_TIME_STARTUP_DESC": "Adjust the brightness to match the most relevant time when Twinkle Tray starts.", "SETTINGS_TIME_IDLE_TITLE": "Idle Detection", "SETTINGS_TIME_IDLE_DESC": "When no input has been detected for a period of time, the brightness of all displays will be reduced.", "SETTINGS_TIME_ANIMATE_TITLE": "Animate between times", "SETTINGS_TIME_ANIMATE_DESC": "Brightness values will be animated between the current and next scheduled event. May increase CPU usage. Manual brightness adjustments will quickly be overwritten while this is active.", "SETTINGS_TIME_SUN_TITLE": "Coordinates for sun position", "SETTINGS_TIME_SUN_DESC": "To use \"sun position\" for time adjustments, enter your current latitude and longitude so the correct times can be determined.", "SETTINGS_TIME_USE_SUN_POSITION": "Use sun position", "SETTINGS_TIME_LAT": "Latitude", "SETTINGS_TIME_LONG": "Longitude", "SETTINGS_TIME_SUN_GET": "Get coordinates", "SETTINGS_TIME_IDLE_FS_TITLE": "Fullscreen apps block idle detection", "SETTINGS_TIME_IDLE_FS_DESC": "Fullscreen apps block idle detection. This only applies to the focused window.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Media blocks idle detection", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Idle detection will be disabled while any media is playing. This includes both video and audio. This only applies when Windows reports that media is playing.", "SETTINGS_HOTKEYS_TITLE": "Hotkeys", "SETTINGS_HOTKEYS_DESC": "Configure hotkeys to adjust the brightness of one or all displays.", "SETTINGS_HOTKEYS_ADD": "Add Hotkey", "SETTINGS_HOTKEYS_REMOVE": "Remove hotkey", "SETTINGS_HOTKEYS_INCREASE": "Increase Brightness", "SETTINGS_HOTKEYS_DECREASE": "Decrease Brightness", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Press keys here", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Brightness level adjustment", "SETTINGS_HOTKEYS_LEVEL_DESC": "How much the brightness should be adjusted when using hotkeys.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Amount to scroll", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Invert scroll", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "When scrolling over the system tray icon, the scroll direction will be reversed.", "SETTINGS_HOTKEYS_TOD_TITLE": "Turn Off Displays action", "SETTINGS_HOTKEYS_TOD_DESC": "Customise the signal sent when using the Turn Off Displays hotkey or icon. The software signal will display a black screen until input (ex. mouse or keyboard) is detected by Windows. The hardware signal will turn off power to the monitors.", "SETTINGS_HOTKEYS_TOD_NONE": "None (hide icon)", "SETTINGS_HOTKEYS_TOD_SOFT": "Software signal (default)", "SETTINGS_HOTKEYS_TOD_HARD": "Hardware* signal (DDC/CI only)", "SETTINGS_HOTKEYS_TOD_BOTH": "Hardware* & software signal", "SETTINGS_HOTKEYS_TOD_NOTE": "*Note: Not all DDC/CI monitors support this feature.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Hotkeys break linked levels", "SETTINGS_HOTKEYS_BREAK_DESC": "When using a hotkey for a single display and \"linked levels\" is active, it will be deactivated.", "SETTINGS_HOTKEY_OFF_WARN": "This action will use the option selected under \"Turn Off Displays action\". If you wish to turn off specific displays instead, use the \"Set\" or \"Cycle\" Hotkey Action instead.", "SETTINGS_HOTKEY_TARGET": "Action Target", "SETTINGS_HOTKEY_VALUE": "Value", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Enter a number", "SETTINGS_HOTKEY_VALUES": "Values", "SETTINGS_HOTKEY_ADD_VALUE": "Add Value", "SETTINGS_HOTKEY_ADD_ACTION": "Add Action", "SETTINGS_HOTKEY_ACTION": "Action", "SETTINGS_HOTKEY_ACTION_SET": "Set value", "SETTINGS_HOTKEY_ACTION_OFFSET": "Adjust value", "SETTINGS_HOTKEY_ACTION_CYCLE": "Cycle list of values", "SETTINGS_PROFILES_TITLE": "Profiles", "SETTINGS_PROFILES_DESC": "Automatically adjust the brightness or shortcut overlay behaviour depending on the focused app. You can also add profiles to the right-click menu in the system tray to quickly change the brightness to pre-defined profiles.", "SETTINGS_PROFILES_ADD": "New Profile", "SETTINGS_PROFILES_NAME": "Profile Name", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Set brightness when active", "SETTINGS_PROFILES_SHOW_MENU": "Show in right-click tray menu", "SETTINGS_PROFILES_TRIGGER_TITLE": "App trigger settings", "SETTINGS_PROFILES_APP_PATH": "App path", "SETTINGS_PROFILES_APP_DESC": "If you want this profile to activate automatically when a specific app is focused, enter the full or partial path of the EXE below.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Override overlay type", "SETTINGS_PROFILES_OVERLAY_DESC": "Changes the behaviour of the hotkey overlay when the specified app is focused. This feature does not work when the profile is manually activated.", "SETTINGS_UPDATES_TITLE": "Updates", "SETTINGS_UPDATES_VERSION": "You have Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automatically check for new versions", "SETTINGS_UPDATES_AUTOMATIC_DESC": "When there is a new version, it will be shown in the brightness panel.", "SETTINGS_UPDATES_MS_STORE": "To check for new versions, visit the Microsoft Store app.", "SETTINGS_UPDATES_AVAILABLE": "New version of Twinkle Tray available!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Up to date. The current version includes the following changes:", "SETTINGS_UPDATES_DOWNLOADING": "Downloading update…", "SETTINGS_UPDATES_DOWNLOAD": "Download & Install {{1}}", "SETTINGS_UPDATES_CHANNEL": "Update channel", "SETTINGS_UPDATES_BRANCH_STABLE": "Stable (default)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta" } ================================================ FILE: src/localization/en.json ================================================ { "LANGUAGE": "English", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Cancel", "GENERIC_SAVE": "Save", "GENERIC_CLEAR": "Clear", "GENERIC_DELETE": "Delete", "GENERIC_OFF": "Off", "GENERIC_ON": "On", "GENERIC_QUIT": "Quit", "GENERIC_CLOSE": "Close", "GENERIC_SETTINGS": "Settings", "GENERIC_INSTALL": "Install", "GENERIC_DISMISS": "Dismiss", "GENERIC_DEFAULT": "Default", "GENERIC_OPTIONAL": "Optional", "GENERIC_DISPLAY_SINGLE": "Display", "GENERIC_ALL_DISPLAYS": "All Displays", "GENERIC_REFRESH_DISPLAYS": "Refresh displays", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Max", "GENERIC_CALIBRATION_POINT": "Calibration Point", "GENERIC_NO_DISPLAYS": "No displays detected. Please connect a display to your PC.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "No compatible displays found. Please check that \"DDC/CI\" is enabled for your displays.", "GENERIC_NO_DISPLAYS_SHORT": "No compatible displays detected.", "GENERIC_NOT_SUPPORTED": "Not supported", "GENERIC_SUPPORTED": "Supported", "GENERIC_UNSUPPORTED": "Unsupported", "GENERIC_ACTIVE": "Active", "GENERIC_SECONDS": "seconds", "GENERIC_MINUTES": "minutes", "GENERIC_DDC_WARNING": "DDC/CI features can cause your monitor to become unresponsive. Use at your own risk.", "GENERIC_SPEED_INSTANT": "Instant", "GENERIC_SPEED_SLOW": "Slow", "GENERIC_SPEED_VERY_SLOW": "Very Slow", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_SPEED_FAST": "Fast", "GENERIC_SPEED_VERY_FAST": "Very fast", "GENERIC_PAUSE_TOD": "Pause Time Adjustments", "GENERIC_PAUSE_IDLE": "Pause Idle Detection", "GENERIC_DETECTING_DISPLAYS": "Detecting displays…", "GENERIC_SLIDER_INDICATOR_TYPE": "Slider Indicator Type", "GENERIC_ICON": "Icon", "GENERIC_TEXT": "Text", "GENERIC_SLIDER_ICON": "Slider Icon", "GENERIC_SLIDER_TEXT": "Slider Text", "GENERIC_SLIDER_NAME": "Enter name for slider", "PANEL_TITLE": "Adjust Brightness", "PANEL_UPDATE_AVAILABLE": "New version available", "PANEL_BUTTON_LINK_LEVELS": "Link levels", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Turn off displays", "PANEL_LABEL_BRIGHTNESS": "Brightness", "PANEL_LABEL_CONTRAST": "Contrast", "PANEL_LABEL_INPUTS": "Inputs", "PANEL_LABEL_OFF_ON": "Power State", "PANEL_LABEL_COLOR_TEMPERATURE": "Color Temperature", "PANEL_LABEL_VOLUME": "Volume", "PANEL_LABEL_TURN_OFF": "Power off", "PANEL_LABEL_TURN_ON": "Power on", "INTRO_TITLE": "Hello, Twinkle Tray!", "INTRO_INSTRUCTIONS": "The tray icon for Twinkle Tray is probably hidden, so you should move it to some place you can easily access it. See below for instructions.", "SETTINGS_TITLE": "Twinkle Tray Settings", "SETTINGS_SIDEBAR_GENERAL": "General", "SETTINGS_SIDEBAR_MONITORS": "Monitor Settings", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI Features", "SETTINGS_SIDEBAR_TIME": "Time Adjustments", "SETTINGS_SIDEBAR_HOTKEYS": "Hotkeys & Shortcuts", "SETTINGS_SIDEBAR_UPDATES": "Updates", "SETTINGS_GENERAL_TITLE": "General", "SETTINGS_GENERAL_STARTUP": "Launch at startup", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Apply brightness at startup", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Restore the last known brightness for each display when Twinkle Tray starts.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Disable on Lock Screen", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Don't access monitors while the user session is locked to avoid conflicts in multi-user environments.", "SETTINGS_GENERAL_THEME_TITLE": "Theme", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Windows UI Style", "SETTINGS_GENERAL_THEME_SYSTEM": "System preferences (default)", "SETTINGS_GENERAL_THEME_DARK": "Dark", "SETTINGS_GENERAL_THEME_LIGHT": "Light", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Language", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "System language (default)", "SETTINGS_GENERAL_RESET_TITLE": "Reset settings", "SETTINGS_GENERAL_RESET_DESC": "Hit this button to clear your config.", "SETTINGS_GENERAL_RESET_BUTTON": "Reset settings", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Acrylic Blur", "SETTINGS_GENERAL_ACRYLIC_DESC": "Enable or disable the blur behind transparent backgrounds in Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Mica Blur", "SETTINGS_GENERAL_MICA_DESC": "Enable or disable the blur behind backgrounds in Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analytics", "SETTINGS_GENERAL_ANALYTICS_DESC": "Send usage data to help improve Twinkle Tray. No personal info is sent. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Learn more", "SETTINGS_GENERAL_SCROLL_TITLE": "Tray icon scroll shortcut", "SETTINGS_GENERAL_SCROLL_DESC": "Adjust the brightness of all displays at once by scrolling over the system tray icon. This does not work with some trackpads.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Tray icon", "SETTINGS_GENERAL_TROUBLESHOOTING": "Troubleshooting", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Enabled monitor detection methods", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "If Twinkle Tray is unresponsive when clicking on the tray icon or not detecting your displays, you can try disabling certain monitor detection methods. Restart Twinkle Tray for changes to take effect. {{1}}", "SETTINGS_GENERAL_OVERLAY_TITLE": "Default overlay behavior", "SETTINGS_GENERAL_OVERLAY_DESC": "How forcefully the brightness hotkey overlay will attempt to display over other apps. You should not need to adjust this.", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Disable overlay", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "If Twinkle Tray's hotkey overlay is interfering with fullscreen applications, you can disable it here.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Most compatible", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "The overlay will display over most windows, but will not force itself above apps that are marked as \"always on top\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Forced on", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Always try to show the overlay on top of other windows. This can cause issues with exclusive fullscreen games and other fullscreen apps. It can also trigger anti-cheat in some games.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Legacy DDC/CI detection method", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Use the old v1.15.5 method of detecting DDC/CI displays.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Auto-apply brightness", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "If your monitor responds strangely after turning it off/on or disconnecting/connecting hardware, disabling this may help.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Skip auto-apply to specific monitors", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Disable auto-applying known brightness after all hardware/power events for specific monitors. This include the idle detection feature.", "SETTINGS_GENERAL_REPORT_TITLE": "Generate Report", "SETTINGS_GENERAL_REPORT_DESC": "Save a text file with information about your monitors and settings for debugging.", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Theme update detection", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Detects accent/wallpaper/theme changes from Windows to update the tray icon and Mica effect. Disabling this may help if a 3rd party app is frequently changing the theme, increasing CPU usage.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Monitor power state detection", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Detects changes to the power state of monitors. Disabling this may help if you experience errors when monitors are turned off/on or are idle. Requires a restart to take effect.", "SETTINGS_MONITORS_RATE_TITLE": "Brightness update rate", "SETTINGS_MONITORS_RATE_DESC": "How often the brightness will be updated on your displays as you're adjusting their values. Increase the time if your displays are flickering.", "SETTINGS_MONITORS_RATE_0": "Ludicrous", "SETTINGS_MONITORS_RATE_1": "Fast (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Slow (1 second)", "SETTINGS_MONITORS_RATE_4": "Very Slow (2 seconds)", "SETTINGS_MONITORS_RENAME_TITLE": "Rename Monitors", "SETTINGS_MONITORS_RENAME_DESC": "If you'd prefer a different name for each monitor (ex \"Left Monitor\", \"Middle Monitor\"), you can enter it below. Leaving the field empty will restore the original name.", "SETTINGS_MONITORS_ENTER_NAME": "Enter name", "SETTINGS_MONITORS_REORDER_TITLE": "Reorder Monitors", "SETTINGS_MONITORS_REORDER_DESC": "Change the order that monitors are displayed in the tray. Click and drag to make changes.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalize Brightness", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitors often have different brightness ranges. By limiting the min/max brightness per display, the brightness levels between displays is much more consistent.", "SETTINGS_MONITORS_CALIBRATION_DESC": "Each monitor can have individual calibration points added to compensate for differences in brightness curves. The input value is the brightness level indicated on the slider, while the output value is the actual brightness level applied to the monitor.", "SETTINGS_MONITORS_DETAILS_NAME": "Name", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Internal Name", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Communication Method", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Current Brightness", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Max Brightness", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Brightness Normalization", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Hide Inactive Internal Display", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "When the lid is closed or the internal display has been disabled in Windows, hide the brightness slider in the panel.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Hide Displays", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "If you would like to hide specific displays from the flyout, you can toggle them off here.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR Display Settings", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Enable SDR brightness sliders for specific monitors. The monitors must have HDR enabled in Windows for this to work.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR Replaces Primary Slider", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Control SDR brightness from main brightness slider while HDR is active.", "SETTINGS_FEATURES_DESCRIPTION": "Enable or disable specific DDC/CI features in the brightness panel. At least one feature must be enabled for your monitor to show up in the brightness panel. Not all displays support these features, such as laptop/tablet displays.", "SETTINGS_FEATURES_UNSUPPORTED": "This monitor does not support DDC/CI features.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Check Current Values", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Always get the latest values from the monitor when opening the brightness panel. Enable this if the brightness (or other VCP codes like contrast) frequently change from outside of Twinkle Tray.", "SETTINGS_FEATURES_POWER_TITLE": "Power State Signal", "SETTINGS_FEATURES_POWER_DESC": "When sending the DDC/CI command to turn off your display, the following value(s) will be sent.", "SETTINGS_FEATURES_POWER_STANDBY": "Standby", "SETTINGS_FEATURES_POWER_OFF": "Power off", "SETTINGS_FEATURES_POWER_COMPAT": "Most compatible", "SETTINGS_FEATURES_POWER_WARNING": "The \"Standby\" option is more likely to allow toggling the monitor on/off from Twinkle Tray. However, many monitors do not respond correctly to changing power state. Use at your own risk.", "SETTINGS_FEATURES_ADD": "Add Feature", "SETTINGS_FEATURES_ADD_DESC": "Enter the VCP code for the feature you would like to add to your display. Please note that Twinkle Tray does not validate if your display actually supports this VCP code. Use at your own risk.", "SETTINGS_FEATURES_ADD_VCP": "VCP Code", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP code (Ex. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "This feature is already active.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "All VCP codes reported by this display", "SETTINGS_FEATURES_VCP_LIST_DESC": "The following is a list of available VCP codes reported by this display to Windows. Twinkle Tray does not validate the functionality or stability of these VCP codes. Use them at your own risk.", "SETTINGS_FEATURES_VCP_EXPECTED": "Expected values", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR Brightness", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "Linked to brightness", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Stop after this brightness level", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "If your monitor uses a non-standard VCP code for brightness (such as 0x13 or 0x6B), or if you would like to remap the brightness slider to a different VCP code, you can enter that code below.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "Leave empty for default (0x10). Find supported codes in the list below.", "SETTINGS_TIME_TITLE": "Time of Day Adjustments", "SETTINGS_TIME_DESC": "Automatically set your monitors to a specific brightness level at a desired time. All monitors will be set to the same, normalized levels.", "SETTINGS_TIME_ADD": "Add a time", "SETTINGS_TIME_REMOVE": "Remove time", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Set brightness for individual displays", "SETTINGS_TIME_INDIVIDUAL_DESC": "Configure the brightness per display instead of for all displays at once.", "SETTINGS_TIME_TRANSITON_TITLE": "Brightness transition speed", "SETTINGS_TIME_TRANSITON_DESC": "How quickly brightness should transition when time of day adjustments are activated.", "SETTINGS_TIME_STARTUP_TITLE": "Check at app startup", "SETTINGS_TIME_STARTUP_DESC": "Adjust the brightness to match the most relevant time when Twinkle Tray starts.", "SETTINGS_TIME_IDLE_TITLE": "Idle Detection", "SETTINGS_TIME_IDLE_DESC": "When no input has been detected for a period of time, the brightness of all displays will be reduced.", "SETTINGS_TIME_ANIMATE_TITLE": "Animate between times", "SETTINGS_TIME_ANIMATE_DESC": "Brightness values will be animated between the current and next scheduled event. May increase CPU usage. Manual brightness adjustments will quickly be overwritten while this is active.", "SETTINGS_TIME_SUN_TITLE": "Coordinates for sun position", "SETTINGS_TIME_SUN_DESC": "To use \"sun position\" for time adjustments, enter your current latitude and longitude so the correct times can be determined.", "SETTINGS_TIME_USE_SUN_POSITION": "Use sun position", "SETTINGS_TIME_LAT": "Latitude", "SETTINGS_TIME_LONG": "Longitude", "SETTINGS_TIME_SUN_GET": "Get coordinates", "SETTINGS_TIME_IDLE_FS_TITLE": "Fullscreen apps block idle detection", "SETTINGS_TIME_IDLE_FS_DESC": "Fullscreen apps block idle detection. This only applies to the focused window.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Media blocks idle detection", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Idle detection will be disabled while any media is playing. This includes both video and audio. This only applies when Windows reports that media is playing.", "SETTINGS_HOTKEYS_TITLE": "Hotkeys", "SETTINGS_HOTKEYS_DESC": "Configure hotkeys to adjust the brightness of one or all displays.", "SETTINGS_HOTKEYS_ADD": "Add Hotkey", "SETTINGS_HOTKEYS_REMOVE": "Remove hotkey", "SETTINGS_HOTKEYS_INCREASE": "Increase Brightness", "SETTINGS_HOTKEYS_DECREASE": "Decrease Brightness", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Press keys here", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Brightness level adjustment", "SETTINGS_HOTKEYS_LEVEL_DESC": "How much the brightness should be adjusted when using hotkeys.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Amount to scroll", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Invert scroll", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "When scrolling over the system tray icon, the scroll direction will be reversed.", "SETTINGS_HOTKEYS_TOD_TITLE": "Turn Off Displays action", "SETTINGS_HOTKEYS_TOD_DESC": "Customize the signal sent when using the Turn Off Displays hotkey or icon. The software signal will display a black screen until input (ex. mouse or keyboard) is detected by Windows. The hardware signal will turn off power to the monitors.", "SETTINGS_HOTKEYS_TOD_NONE": "None (hide icon)", "SETTINGS_HOTKEYS_TOD_SOFT": "Software signal (default)", "SETTINGS_HOTKEYS_TOD_HARD": "Hardware* signal (DDC/CI only)", "SETTINGS_HOTKEYS_TOD_BOTH": "Hardware* & software signal", "SETTINGS_HOTKEYS_TOD_NOTE": "*Note: Not all DDC/CI monitors support this feature.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Hotkeys break linked levels", "SETTINGS_HOTKEYS_BREAK_DESC": "When using a hotkey for a single display and \"linked levels\" is active, it will be deactivated.", "SETTINGS_HOTKEY_OFF_WARN": "This action will use the option selected under \"Turn Off Displays action\". If you wish to turn off specific displays instead, use the \"Set\" or \"Cycle\" Hotkey Action instead.", "SETTINGS_HOTKEY_TARGET": "Action Target", "SETTINGS_HOTKEY_VALUE": "Value", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Enter a number", "SETTINGS_HOTKEY_VALUES": "Values", "SETTINGS_HOTKEY_ADD_VALUE": "Add Value", "SETTINGS_HOTKEY_ADD_ACTION": "Add Action", "SETTINGS_HOTKEY_ACTION": "Action", "SETTINGS_HOTKEY_ACTION_SET": "Set value", "SETTINGS_HOTKEY_ACTION_OFFSET": "Adjust value", "SETTINGS_HOTKEY_ACTION_CYCLE": "Cycle list of values", "SETTINGS_PROFILES_TITLE": "Profiles", "SETTINGS_PROFILES_DESC": "Automatically adjust the brightness or shortcut overlay behavior depending on the focused app. You can also add profiles to the right-click menu in the system tray to quickly change the brightness to pre-defined profiles.", "SETTINGS_PROFILES_ADD": "New Profile", "SETTINGS_PROFILES_NAME": "Profile Name", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Set brightness when active", "SETTINGS_PROFILES_SHOW_MENU": "Show in right-click tray menu", "SETTINGS_PROFILES_TRIGGER_TITLE": "App trigger settings", "SETTINGS_PROFILES_APP_PATH": "App path", "SETTINGS_PROFILES_APP_DESC": "If you want this profile to activate automatically when a specific app is focused, enter the full or partial path of the EXE below.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Override overlay type", "SETTINGS_PROFILES_OVERLAY_DESC": "Changes the behavior of the hotkey overlay when the specified app is focused. This feature does not work when the profile is manually activated.", "SETTINGS_UPDATES_TITLE": "Updates", "SETTINGS_UPDATES_VERSION": "You have Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automatically check for new versions", "SETTINGS_UPDATES_AUTOMATIC_DESC": "When there is a new version, it will be shown in the brightness panel.", "SETTINGS_UPDATES_MS_STORE": "To check for new versions, visit the Microsoft Store app.", "SETTINGS_UPDATES_AVAILABLE": "New version of Twinkle Tray available!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Up to date. The current version includes the following changes:", "SETTINGS_UPDATES_DOWNLOADING": "Downloading update…", "SETTINGS_UPDATES_DOWNLOAD": "Download & Install {{1}}", "SETTINGS_UPDATES_CHANNEL": "Update channel", "SETTINGS_UPDATES_BRANCH_STABLE": "Stable (default)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta" } ================================================ FILE: src/localization/es.json ================================================ { "LANGUAGE": "Español", "GENERIC_OK": "Aceptar", "GENERIC_CANCEL": "Cancelar", "GENERIC_SAVE": "Guardar", "GENERIC_CLEAR": "Borrar", "GENERIC_OFF": "Apagado", "GENERIC_ON": "Encendido", "GENERIC_QUIT": "Salir", "GENERIC_CLOSE": "Cerrar", "GENERIC_SETTINGS": "Configuración", "GENERIC_INSTALL": "Instalar", "GENERIC_DISMISS": "Descartar", "GENERIC_DISPLAY_SINGLE": "Pantalla", "GENERIC_ALL_DISPLAYS": "Todas las pantallas", "GENERIC_MINIMUM": "Mín", "GENERIC_MAXIMUM": "Máx", "GENERIC_NO_DISPLAYS": "No se han detectado pantallas. Por favor, conecte una pantalla a su PC.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "No se han encontrado pantallas compatibles. Por favor, compruebe que \"DDC/CI\" esté activado en su pantalla.", "GENERIC_NO_DISPLAYS_SHORT": "No se han detectado pantallas compatibles.", "PANEL_TITLE": "Ajustar brillo", "PANEL_UPDATE_AVAILABLE": "Nueva versión disponible", "PANEL_BUTTON_LINK_LEVELS": "Niveles de enlace", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Apagar pantallas", "INTRO_TITLE": "¡Le damos la bienvenida a Twinkle Tray!", "INTRO_INSTRUCTIONS": "Es probable que el icono de Twinkle Tray en la barra de tareas esté oculto, debería moverlo a un lugar fácilmente accesible. Mire las instrucciones debajo.", "SETTINGS_TITLE": "Configuración de Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "General", "SETTINGS_SIDEBAR_MONITORS": "Ajustes de pantalla", "SETTINGS_SIDEBAR_TIME": "Configuración horaria", "SETTINGS_SIDEBAR_HOTKEYS": "Teclas de acceso rápido", "SETTINGS_SIDEBAR_UPDATES": "Actualizaciones", "SETTINGS_GENERAL_TITLE": "General", "SETTINGS_GENERAL_STARTUP": "Iniciar con Windows", "SETTINGS_GENERAL_THEME_TITLE": "Tema de la aplicación", "SETTINGS_GENERAL_THEME_SYSTEM": "Preferencia del sistema (Predeterminado)", "SETTINGS_GENERAL_THEME_DARK": "Oscuro", "SETTINGS_GENERAL_THEME_LIGHT": "Claro", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Idioma", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Idioma del sistema (Predeterminado)", "SETTINGS_GENERAL_RESET_TITLE": "Restablecer ajustes", "SETTINGS_GENERAL_RESET_DESC": "Pulse este botón para borrar sus ajustes.", "SETTINGS_GENERAL_RESET_BUTTON": "Restablecer ajustes", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analíticas", "SETTINGS_GENERAL_ANALYTICS_DESC": "Envíe datos de uso para ayudar a mejorar Twinkle Tray. No se enviará información personal. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Más información", "SETTINGS_MONITORS_RATE_TITLE": "Tasa de actualización del brillo", "SETTINGS_MONITORS_RATE_DESC": "La frecuencia con la que se actualiza el brillo del monitor. Si la pantalla parpadea, aumente la frecuencia de actualización del brillo.", "SETTINGS_MONITORS_RATE_0": "Muy rápido", "SETTINGS_MONITORS_RATE_1": "Rápido (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Lento (1 segundos)", "SETTINGS_MONITORS_RATE_4": "Muy lento (2 segundos)", "SETTINGS_MONITORS_RENAME_TITLE": "Renombrar pantallas", "SETTINGS_MONITORS_RENAME_DESC": "Si prefiere un nombre diferente para sus pantallas (ej \"Pantalla izquierda\" \"Pantalla central\"), puede modificarlo debajo. Si deja el campo vacío, se restablecerá el nombre original.", "SETTINGS_MONITORS_ENTER_NAME": "Introduce el nombre", "SETTINGS_MONITORS_REORDER_TITLE": "Reordenar pantallas", "SETTINGS_MONITORS_REORDER_DESC": "Cambie el orden en el que sus pantallas serán mostradas en la bandeja del sistema. Haga click y arrastre para hacer cambios.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalizar brillo", "SETTINGS_MONITORS_NORMALIZE_DESC": "Los monitores suelen tener distintos rangos de brillo. Al limitar el brillo mínimo/máximo por pantalla, los niveles de brillo entre pantallas son mucho más uniformes. Pantallas similares utilizarán los mismos ajustes.", "SETTINGS_TIME_TITLE": "Configuración de la hora del día", "SETTINGS_TIME_DESC": "Ajusta automáticamente tus monitores a un nivel de brillo específico en el momento deseado. Todas las pantallas se ajustarán a los mismos niveles normalizados.", "SETTINGS_TIME_ADD": "Añadir horario", "SETTINGS_TIME_REMOVE": "Borrar horario", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Ajustar brillo individualmente", "SETTINGS_TIME_INDIVIDUAL_DESC": "Configure el brillo por pantalla en lugar de para todas las pantallas a la vez.", "SETTINGS_TIME_STARTUP_TITLE": "Comprobar al iniciar la aplicación", "SETTINGS_TIME_STARTUP_DESC": "Ajusta el brillo al valor del horario más relevante cuándo Twinkle Tray se inicia.", "SETTINGS_HOTKEYS_TITLE": "Atajos de teclado", "SETTINGS_HOTKEYS_DESC": "Configure combinaciones de teclas para ajustar el brillo de sus pantallas, individualmente o de manera conjunta.", "SETTINGS_HOTKEYS_ADD": "Agregar atajo de teclado", "SETTINGS_HOTKEYS_REMOVE": "Borrar atajo de teclado", "SETTINGS_HOTKEYS_INCREASE": "Aumentar brillo", "SETTINGS_HOTKEYS_DECREASE": "Reducir brillo", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Pulse la combinación de teclas aquí", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Ajuste del nivel de brillo", "SETTINGS_HOTKEYS_LEVEL_DESC": "Cómo deberá ser ajustado el brillo al usar atajos de teclado.", "SETTINGS_UPDATES_TITLE": "Actualizaciones", "SETTINGS_UPDATES_VERSION": "Su versión de Twinkle Tray es {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Comprobar actualizaciones automáticamente", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Cuando haya una nueva versión, se mostrará en el panel de brillo.", "SETTINGS_UPDATES_MS_STORE": "Para comprobar si hay actualizaciones, visite la aplicación Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "¡Hay una actualización disponible para Twinkle Tray!", "SETTINGS_UPDATES_NONE_AVAILABLE": "No hay actualizaciones disponibles en este momento. Esta versión de Twinkle Tray incluye los cambios siguientes:", "SETTINGS_UPDATES_DOWNLOADING": "Descargando actualización…", "SETTINGS_UPDATES_DOWNLOAD": "Descargar e instalar {{1}}", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Icono de barra de tareas", "SETTINGS_GENERAL_SCROLL_DESC": "Ajuste el brillo de todas las pantallas a la vez haciendo scroll sobre el icono de bandeja del sistema. No funciona con algunos trackpads.", "SETTINGS_GENERAL_SCROLL_TITLE": "Atajo de scroll del icono de la barra de tareas", "SETTINGS_GENERAL_ACRYLIC_DESC": "Active o desactive el efecto de desenfoque del fondo transparente en Twinkle Tray.", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Desenfoque acrílico", "SETTINGS_MONITORS_FEATURES_DESCRIPTION": "Activa o Deshabilita las características específicas de DDC/CI en el panel de brillo. Al menos una función debe estar activada para que el monitor aparezca en el panel de brillo. No todas las pantallas son compatibles con estas funciones, como las pantallas de los portátiles o tabletas.", "SETTINGS_MONITORS_FEATURES_TITLE": "Funciones DDC/CI", "PANEL_LABEL_COLOR_TEMPERATURE": "Temperatura de color", "PANEL_LABEL_OFF_ON": "Estado de energía", "PANEL_LABEL_CONTRAST": "Contraste", "PANEL_LABEL_BRIGHTNESS": "Brillo", "SETTINGS_SIDEBAR_FEATURES": "Características DDC/CI", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Restaurar el último brillo conocido para cada pantalla cuando se inicia Twinkle Tray.", "SETTINGS_FEATURES_DESCRIPTION": "Activar o desactivar características específicas de DDC/CI en el panel de brillo. Al menos una característica tiene que estar activa en la pantalla para que aparezca en el panel de brillo. No todas las pantallas tienen soporte para estas características, como las pantallas de portátiles y tablets.", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalización del brillo", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Brillo máximo", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Brillo actual", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Método de comunicación", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Nombre interno", "SETTINGS_MONITORS_DETAILS_NAME": "Nombre", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Aplicar brillo al inicio", "PANEL_LABEL_VOLUME": "Volumen", "GENERIC_REFRESH_DISPLAYS": "Actualizar pantallas", "SETTINGS_HOTKEYS_TOD_TITLE": "Apagar Acciones de pantallas", "SETTINGS_HOTKEYS_TOD_NONE": "Ninguno (ocultar icono)", "SETTINGS_HOTKEYS_TOD_SOFT": "Señal por software (por defecto)", "SETTINGS_HOTKEYS_TOD_BOTH": "Señal por software y hardware*", "SETTINGS_HOTKEYS_TOD_HARD": "Señal por hardware* (solo DDC/CI)", "SETTINGS_HOTKEYS_TOD_NOTE": "*Nota: No todas las pantallas con DDC/CI soportan esta característica.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Las teclas de acceso rápido rompen los niveles vinculados", "SETTINGS_HOTKEYS_TOD_DESC": "Personaliza la señal enviada cuando se usa el acceso rápido (tecla o icono) para apagar. La señal del programa mostrará una pantalla en negro hasta que Windows reciba una entrada (ej. teclado o ratón). La señal por hardware apagará las pantallas.", "GENERIC_MINUTES": "minutos", "SETTINGS_GENERAL_MICA_TITLE": "Material Mica", "SETTINGS_GENERAL_MICA_DESC": "Active o desactive el efecto de desenfoque detrás del fondo en Twinkle Tray.", "GENERIC_SECONDS": "segundos", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Verifique los valores actuales", "PANEL_LABEL_TURN_OFF": "Apagar", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Ocultar pantalla integrada inactiva", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Obtener siempre los últimos valores de la pantalla al abrir el panel de brillo. Habilite esta opción si el brillo (u otros códigos VCP como el contraste) cambian con frecuencia por fuera de Twinkle Tray.", "SETTINGS_TIME_IDLE_TITLE": "Detección de inactividad", "SETTINGS_TIME_IDLE_DESC": "Cuando no se detecta ninguna entrada durante un periodo de tiempo, el brillo de todas las pantallas se reduce.", "SETTINGS_HOTKEYS_BREAK_DESC": "Cuando se usa una tecla de acceso rápido para una sola pantalla y los \"niveles vinculados\" están activos, se desactivará.", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Cuando la tapa está cerrada o la pantalla integrada ha sido desactivada en Windows, oculta el deslizador de brillo en el panel.", "SETTINGS_FEATURES_UNSUPPORTED": "Esta pantalla no es compatible con las funciones DDC/CI.", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Si Twinkle Tray no responde al hacer clic en el icono de la bandeja o no detecta sus pantallas, puede intentar desactivar ciertos métodos de detección de pantallas. Reinicie Twinkle Tray para que los cambios surtan efecto. {{1}}", "GENERIC_PAUSE_TOD": "Pausar ajustes por horario", "GENERIC_PAUSE_IDLE": "Pausar detección de inactividad", "SETTINGS_GENERAL_TROUBLESHOOTING": "Solución de problemas", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Métodos de detección de pantallas habilitados", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Desactivar superposición", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Si la superposición por atajo de teclado de Twinkle Tray interfiere con las aplicaciones a pantalla completa, puedes desactivarla aquí.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Ocultar pantallas", "SETTINGS_TIME_TRANSITON_TITLE": "Velocidad de transición de brillo", "SETTINGS_TIME_TRANSITON_DESC": "Con qué rapidez debe cambiar el brillo cuando se activan los ajustes de la hora del día.", "SETTINGS_TIME_ANIMATE_TITLE": "Animar entre horarios", "SETTINGS_TIME_ANIMATE_DESC": "Los valores de brillo se animarán entre el evento actual y el siguiente programado. Puede aumentar el uso de la CPU. Los ajustes manuales de brillo se sobrescribirán rápidamente mientras esté activo.", "GENERIC_SPEED_INSTANT": "Instantánea", "GENERIC_SPEED_SLOW": "Lento", "GENERIC_SPEED_VERY_SLOW": "Muy lento", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_SPEED_FAST": "Rápido", "GENERIC_SPEED_VERY_FAST": "Muy rápido", "GENERIC_DDC_WARNING": "Las características DDC/CI, como el encendido/apagado de la pantalla, pueden hacer que la pantalla deje de responder. Utilícelo bajo su propia responsabilidad.", "SETTINGS_UPDATES_BRANCH_STABLE": "Estable (por defecto)", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Si desea ocultar determinadas pantallas del menú desplegable, puede desactivarlas aquí.", "SETTINGS_UPDATES_CHANNEL": "Canal de actualización", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "GENERIC_DELETE": "Eliminar", "GENERIC_DEFAULT": "Default", "SETTINGS_GENERAL_OVERLAY_TITLE": "Comportamiento de superposición por defecto", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Más compatible", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "La superposición se mostrará encima más ventanas, pero no se forzará por encima de aplicaciones que estén marcadas como \"siempre arriba\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Forzado encima", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Método de detección DDC/CI Legacy", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Auto-aplicar brillo", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Desactivar la auto-aplicación de brillo conocido después de todos los eventos de hardware/energía para pantallas específicas. Esto incluye la función de detección de inactividad.", "SETTINGS_FEATURES_POWER_TITLE": "Señal de estado de energía", "SETTINGS_FEATURES_POWER_DESC": "Al enviar el comando DDC/CI para apagar su pantalla, se enviarán los siguientes valores.", "SETTINGS_FEATURES_POWER_STANDBY": "En espera", "SETTINGS_FEATURES_POWER_COMPAT": "Más compatible", "SETTINGS_FEATURES_POWER_WARNING": "La opción \"Standby\" es más probable que permita encender/apagar la pantalla desde Twinkle Tray. Sin embargo, muchos monitores no responden correctamente al cambio de estado de encendido. Utilícelo bajo su propia responsabilidad.", "SETTINGS_FEATURES_ADD": "Añade Característica", "SETTINGS_TIME_SUN_TITLE": "Coordenadas para la posición del sol", "SETTINGS_TIME_LAT": "Latitud", "SETTINGS_HOTKEY_ACTION": "Acción", "SETTINGS_HOTKEY_ACTION_SET": "Set valor", "SETTINGS_FEATURES_ADD_VCP": "Código VCP", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "Código VCP (Ej. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Esta característica ya está activa.", "SETTINGS_TIME_LONG": "Longitud", "GENERIC_OPTIONAL": "Opcional", "PANEL_LABEL_TURN_ON": "Encender", "SETTINGS_GENERAL_OVERLAY_DESC": "La fuerza con la que la superposición de teclas de acceso rápido de brillo intentará mostrarse sobre otras aplicaciones. No debería ser necesario ajustarlo.", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Intentar siempre mostrar la superposición sobre otras ventanas. Esto puede causar problemas con juegos exclusivos para pantalla completa y otras aplicaciones de pantalla completa. También puede alertar los sistemas antitrampas en algunos juegos.", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Utilizar el antiguo método v1.15.5 de detección de pantallas DDC/CI.", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Si su pantalla responde de forma extraña después de apagarlo o desconectando/conectando hardware, desactivar esto puede ayudar.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Omitir Auto-aplicar en pantallas específicas", "SETTINGS_GENERAL_REPORT_TITLE": "Generar Informe", "SETTINGS_GENERAL_REPORT_DESC": "Guarda un archivo de texto con información sobre tus pantallas y configuraciones para depuración.", "SETTINGS_FEATURES_ADD_DESC": "Introduzca el código VCP de la función que desea añadir a su pantalla. Tenga en cuenta que Twinkle Tray no valida si su pantalla es realmente compatible con este código VCP. Utilícelo bajo su propia responsabilidad.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Todos los códigos informados por esta pantalla", "SETTINGS_FEATURES_VCP_LIST_DESC": "La siguiente es una lista de códigos VCP disponibles reportados por esta pantalla a Windows. Twinkle Tray no valida la funcionalidad o estabilidad de estos códigos VCP. Utilícelos bajo su propia responsabilidad.", "SETTINGS_FEATURES_VCP_EXPECTED": "Valores esperados", "SETTINGS_TIME_SUN_DESC": "Para utilizar la posición del sol para ajustar la hora, introduce tu latitud y longitud para que se puedan determinar las horas correctas.", "SETTINGS_TIME_SUN_GET": "Obtener coordenadas", "SETTINGS_TIME_IDLE_FS_TITLE": "Las aplicaciones a pantalla completa bloquean la detección de inactividad", "SETTINGS_TIME_IDLE_FS_DESC": "Las aplicaciones a pantalla completa bloquean la detección de inactividad. Esto solo se aplica a la ventana enfocada.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Distancia del desplazamiento al hacer scroll", "SETTINGS_HOTKEY_OFF_WARN": "Esta acción utilizará la opción seleccionada en \"Apagar Acciones de pantallas\". Si desea apagar pantallas específicas en su lugar, utilice la acción de tecla de acceso rápido \"Set\" o \"Cycle\".", "SETTINGS_HOTKEY_TARGET": "Objetivo de acción", "SETTINGS_HOTKEY_VALUE": "Valor", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Introduce un número", "SETTINGS_HOTKEY_VALUES": "Valores", "SETTINGS_HOTKEY_ADD_VALUE": "Añadir Valor", "SETTINGS_HOTKEY_ACTION_OFFSET": "Ajustar valor", "SETTINGS_HOTKEY_ACTION_CYCLE": "Lista de ciclo de valores", "SETTINGS_PROFILES_TITLE": "Perfiles", "SETTINGS_PROFILES_DESC": "Ajusta automáticamente el brillo o el comportamiento de la superposición de accesos directos en función de la aplicación en la que te centres. También puedes añadir perfiles al menú contextual de la bandeja del sistema para cambiar rápidamente el brillo a perfiles predefinidos.", "SETTINGS_PROFILES_ADD": "Nuevo Perfil", "SETTINGS_PROFILES_NAME": "Nombre de perfil", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Set brillo cuándo esté activo", "SETTINGS_PROFILES_SHOW_MENU": "Mostrar con click derecho sobre el icono en bandeja del sistema", "SETTINGS_PROFILES_TRIGGER_TITLE": "Gatillantes de configuracion de la App", "SETTINGS_PROFILES_APP_PATH": "Ruta de aplicación", "SETTINGS_PROFILES_APP_DESC": "Si deseas que este perfil se active automáticamente cuando se enfoque en una aplicación específica, ingresa a continuación la ruta completa o parcial del EXE.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Sobrescribir tipo de superposición", "SETTINGS_PROFILES_OVERLAY_DESC": "Cambia el comportamiento de la superposición de teclas de acceso rápido cuando la app especificada está enfocada. Esta función no funciona cuando el perfil se activa manualmente.", "SETTINGS_FEATURES_POWER_OFF": "Apagar", "SETTINGS_TIME_IDLE_MEDIA_DESC": "La detección de inactividad se desactivará mientras se esté reproduciendo cualquier contenido multimedia. Esto incluye tanto vídeo como audio. Esto solo se aplica cuando Windows informa de que se está reproduciendo algún contenido multimedia.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Multimedia bloquea la detección de inactividad", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Invertir scroll", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Al hacer scroll sobre el icono de bandeja del sistema, la dirección del desplazamiento será invertida.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Inutiliza encima Pantalla de Cerradura", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "No accede monitores mientras la sesión de usuario está cerrada para evitar conflictos en multi-entornos de usuario.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR Encuadres de exposición", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Habilita SDR brillo sliders para monitores concretos. Los monitores tienen que haber HDR habilitados en Ventanas para este para obrar.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR Reemplaza Primario Slider", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Control SDR brillo de brillo principal slider mientras HDR es activo.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR Brillo", "GENERIC_NOT_SUPPORTED": "No apoyado", "GENERIC_SUPPORTED": "Soportado", "GENERIC_UNSUPPORTED": "Unsupported", "GENERIC_ACTIVE": "Activo", "GENERIC_DETECTING_DISPLAYS": "Detectando exposiciones…", "PANEL_LABEL_INPUTS": "Entradas", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Windows UI Moda", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Detección de actualización del tema", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Detecta acento/wallpaper/cambios de tema de Ventanas para actualizar el icono de bandeja y Mica efecto. Inutilizando esto puede ayudar si una 3.ª aplicación de fiesta frecuentemente está cambiando el tema, aumentando CPU uso.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Monitor poder detección estatal", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Detecta cambios al estado de poder de monitores. Inutilizando esto puede ayudar si experimentas errores cuándo los monitores están girados fuera/encima o es idle. Requiere un retomar para tomar efecto.", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_TIME_USE_SUN_POSITION": "#Puesto de sol del uso", "SETTINGS_HOTKEY_ADD_ACTION": "Añade Acción", "GENERIC_CALIBRATION_POINT": "Punto de calibración", "GENERIC_SLIDER_INDICATOR_TYPE": "Slider Tipo de indicador", "GENERIC_ICON": "Icono", "GENERIC_TEXT": "Texto", "GENERIC_SLIDER_ICON": "Slider Icono", "GENERIC_SLIDER_TEXT": "Slider Texto", "GENERIC_SLIDER_NAME": "Introduce nombre para slider", "SETTINGS_MONITORS_CALIBRATION_DESC": "Cada monitor puede tener puntos de calibración individual añadieron para compensar para diferencias en curvas de brillo. El valor de entrada es el nivel de brillo indicado en el slider, mientras el valor de salida es el nivel de brillo real aplicó al monitor.", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "Enlazado a brillo", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Parón después de este nivel de brillo", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "Si vuestro monitor utiliza un no-estándar VCP código para brillo (como 0x13 o 0x6B), o si te gustaría a remap el brillo slider a un diferente VCP código, puedes introducir aquel código abajo.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "Deja vacío para default (0x10). Encuentra códigos soportados en la lista abajo." } ================================================ FILE: src/localization/fa.json ================================================ { "LANGUAGE": "پارسی", "GENERIC_OK": "پذیرفتن", "GENERIC_CANCEL": "لغو", "GENERIC_SAVE": "ذخیره", "GENERIC_CLEAR": "پاک‌کردن", "GENERIC_OFF": "خاموش", "GENERIC_ON": "روشن", "GENERIC_QUIT": "خروج", "GENERIC_CLOSE": "بستن", "GENERIC_SETTINGS": "تنظیمات", "GENERIC_INSTALL": "نصب", "GENERIC_DISMISS": "نادیده گرفتن", "GENERIC_DISPLAY_SINGLE": "نمایشگر", "GENERIC_ALL_DISPLAYS": "همه‌ی نمایشگرها", "GENERIC_REFRESH_DISPLAYS": "بازفراخوانی نمایشگر‌ها", "GENERIC_MINIMUM": "کم‌ترین", "GENERIC_MAXIMUM": "بیشترین", "GENERIC_NO_DISPLAYS": "نمایشگری یافت نشد. لطفاً یک نمایگشر به رایانه‌ی خود متصل کنید.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "نمایشگر سازگار با برنامه یافت نشد. لطفاً بررسی کنید که «DCC/CI» برای نمایشگر‌هایتان فعال باشد.", "GENERIC_NO_DISPLAYS_SHORT": "نمایشگر سازگار با برنامه یافت نشد.", "GENERIC_SECONDS": "ثانیه", "GENERIC_MINUTES": "دقیقه", "GENERIC_DDC_WARNING": "قابلیت‌هایی از «DDC/CI» مانند کنترل وضعیت خاموش و روشن بودن، می‌توانند نمایشگر شما را در وضعیت غیر پاسخگو قرار دهند. با مسئولیت خوتان استفاده کنید.", "GENERIC_SPEED_INSTANT": "بلافاصله", "GENERIC_SPEED_SLOW": "آهسته", "GENERIC_SPEED_VERY_SLOW": "بسیار آهسته", "GENERIC_SPEED_NORMAL": "عادی", "GENERIC_SPEED_FAST": "تند", "GENERIC_SPEED_VERY_FAST": "بسیار تند", "GENERIC_PAUSE_TOD": "در همگام‌سازی با زمان درنگ‌کن", "GENERIC_PAUSE_IDLE": "متوقف سازی تشخیص بلااستفاده", "PANEL_TITLE": "تنظیم روشنایی", "PANEL_UPDATE_AVAILABLE": "نسخه جدیدی آمده", "PANEL_BUTTON_LINK_LEVELS": "‌همگام‌سازی تراز روشنایی", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "خاموش‌کردن نمایشگرها", "PANEL_LABEL_BRIGHTNESS": "روشنایی", "PANEL_LABEL_CONTRAST": "کنتراست", "PANEL_LABEL_OFF_ON": "وضعیت نمایشگر", "PANEL_LABEL_COLOR_TEMPERATURE": "دمای رنگ", "PANEL_LABEL_VOLUME": "صدا", "PANEL_LABEL_TURN_OFF": "خاموش‌کردن", "INTRO_TITLE": "سلام Twinkle Tray!", "INTRO_INSTRUCTIONS": "احتمالا آیکون Twinkle Tray مخفی است. بهتر است آن را به یک مکان جدید ببرید که به راحتی قابل دسترس باشد. برای راهنمایی به زیر مراجعه کنید.", "SETTINGS_TITLE": "تنظیمات Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "تنظیمات کلی", "SETTINGS_SIDEBAR_MONITORS": "تنظیمات نمایشگر", "SETTINGS_SIDEBAR_FEATURES": "ویژگی های DDC/CI", "SETTINGS_SIDEBAR_TIME": "تنظیم زمان", "SETTINGS_SIDEBAR_HOTKEYS": "کلیدها و میانبرها", "SETTINGS_SIDEBAR_UPDATES": "به‌روز رسانی", "SETTINGS_GENERAL_TITLE": "تنظیمات کلی", "SETTINGS_GENERAL_STARTUP": "راه اندازی در زمان روشن شدن", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "اعمال روشنایی در زمان روشن شدن", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "هنگام اجرای Twinkle Tray، میزان روشنایی هر نمایشگر به آخرین مقدار ذخیره شده، بازگردانی شود.", "SETTINGS_GENERAL_THEME_TITLE": "تِم", "SETTINGS_GENERAL_THEME_SYSTEM": "تنظیمات سیستم (پیش فرض)", "SETTINGS_GENERAL_THEME_DARK": "تاریک", "SETTINGS_GENERAL_THEME_LIGHT": "روشن", "SETTINGS_GENERAL_LANGUAGE_TITLE": "زبان", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "زبان سیستم (پیش فرض)", "SETTINGS_GENERAL_RESET_TITLE": "ریست کردن تنظیمات", "SETTINGS_GENERAL_RESET_DESC": "روی این کلید بزنید تا تنظیمات پاک شود.", "SETTINGS_GENERAL_RESET_BUTTON": "ریست کردن تنظیمات", "SETTINGS_GENERAL_ACRYLIC_TITLE": "بلور اکلیلریک", "SETTINGS_GENERAL_ACRYLIC_DESC": "فعال یا غیر فعال کردن بلور پشت پس زمینه‌های شفاف در Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "بلور میکا", "SETTINGS_GENERAL_MICA_DESC": "فعال یا غیر فعال کردن بلور پشت پس زمینه‌های شفاف در Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "", "SETTINGS_GENERAL_ANALYTICS_DESC": "فرستادن اطلاعات استفاده از برنامه برای کمک به بهتر کردن آن {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "یادگیری بیشتر", "SETTINGS_GENERAL_SCROLL_TITLE": "", "SETTINGS_GENERAL_SCROLL_DESC": "", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "", "SETTINGS_GENERAL_TROUBLESHOOTING": "عیب یابی", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "شیوه های فعال شده برای نشخیص نمایشگر ها", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "اگر توینکل‌تری هنگام کلیک روی نماد سینی یا شناسایی‌نکردن نمایشگرهای شما پاسخ نمی دهد، می توانید روش های تشخیص مانیتور خاصی را خاموش کنید. برای اعمال تغییرات، Twinkle Tray را دوباره راه‌اندازی کنید. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "رفتار هم‌پوشانی پیش‌فرض", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "اگر کلید میانبر نمایش کادر(overlay) تنظیم روشنایی با برنامه های تمام صفحه تداخل دارد، می توانید آن را از اینجا غیر فعال کنید.", "SETTINGS_MONITORS_RATE_TITLE": "نرخ به روز رسانی روشنایی", "SETTINGS_MONITORS_RATE_DESC": "", "SETTINGS_MONITORS_RATE_0": "بسیار سریع", "SETTINGS_MONITORS_RATE_1": "سریع(۲۵۰ میلی ثانیه)", "SETTINGS_MONITORS_RATE_2": "عادی(۵۰۰ میلی ثانیه)", "SETTINGS_MONITORS_RATE_3": "کند(۱ ثانیه)", "SETTINGS_MONITORS_RATE_4": "خیلی کند(۲ ثانیه)", "SETTINGS_MONITORS_RENAME_TITLE": "تغییر نام نمایشگر ها", "SETTINGS_MONITORS_RENAME_DESC": "اگر ترجیح می‌دهید که از نام های متفاوتی برای نمایشگر ها استفاده کنید(مانند «نمایشگر چپ» یا «نمایشگر راست»)، می‌توانید این اسامی را در پایین وارد کنید. خالی گذاشتن فیلد ها باعث می‌شود اسامی پیش فرض ورد استفاده قرار بگیرند.", "SETTINGS_MONITORS_ENTER_NAME": "نام را وارد کنید", "SETTINGS_MONITORS_REORDER_TITLE": "تغییر ترتیب نمایشگر ها", "SETTINGS_MONITORS_REORDER_DESC": "", "SETTINGS_MONITORS_NORMALIZE_TITLE": "تغییر بازه مقدار روشنایی نمایشگر ها", "SETTINGS_MONITORS_NORMALIZE_DESC": "نمایشگر ها اغلب بازه روشنایی متفاوتی دارند. با محدود کردن مقدار روشنایی حداکثر یا حداقل برای هر نمایشگر، بازه روشنایی نمایشگر ها شبیه هم و یکپارچه تر می‌شود. نمایشگر های مشابه از تنظیمات یکسانی استفاده خواهند کرد.", "SETTINGS_MONITORS_DETAILS_NAME": "نام", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "روشنایی فعلی", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "حداکثر روشنایی", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "تغییر بازه روشنایی", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "پنهان کردن نمایشگر ها", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "", "SETTINGS_FEATURES_DESCRIPTION": "", "SETTINGS_FEATURES_UNSUPPORTED": "این نمایشگر از قابلیت های DCC/CI پشتیبانی نمی‌کند.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "", "SETTINGS_TIME_TITLE": "تغییرات با زمان های روز", "SETTINGS_TIME_DESC": "", "SETTINGS_TIME_ADD": "افزودن زمان", "SETTINGS_TIME_REMOVE": "پاک‌کردن زمان", "SETTINGS_TIME_INDIVIDUAL_TITLE": "تنظیم روشنایی برا نمایشگر های مشخص", "SETTINGS_TIME_INDIVIDUAL_DESC": "روشنایی را برای هر نمایشگر جداگانه تنظیم کن. (در مقابل تنظیم همه نمایشگر ها با هم)", "SETTINGS_TIME_TRANSITON_TITLE": "سرعت تفییر روشنایی", "SETTINGS_TIME_TRANSITON_DESC": "", "SETTINGS_TIME_STARTUP_TITLE": "", "SETTINGS_TIME_STARTUP_DESC": "", "SETTINGS_TIME_IDLE_TITLE": "تشخیص حالت بیکار", "SETTINGS_TIME_IDLE_DESC": "وقتی برای یک مدت زمانی، هیچ ورودی تشخیص داده نشود، روشنایی تمام نمایشگر ها کاهش داده می‌شود.", "SETTINGS_TIME_ANIMATE_TITLE": "", "SETTINGS_TIME_ANIMATE_DESC": "", "SETTINGS_HOTKEYS_TITLE": "کلید های میانبر", "SETTINGS_HOTKEYS_DESC": "کلید های میانبر را برای تغییر روشنایی یک یا همه نمایشگر ها تنظیم کنید.", "SETTINGS_HOTKEYS_ADD": "اضافه کردن کلید میانبر", "SETTINGS_HOTKEYS_REMOVE": "حذف کلید میانبر", "SETTINGS_HOTKEYS_INCREASE": "افزایش روشنایی", "SETTINGS_HOTKEYS_DECREASE": "کاهش روشنایی", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "کلید ها را اینجا فشار دهید", "SETTINGS_HOTKEYS_LEVEL_TITLE": "تغییر سطح روشنایی", "SETTINGS_HOTKEYS_LEVEL_DESC": "هنگام استفاده از کلید های میانبر، روشنایی چقدر باید تغییر کند.", "SETTINGS_HOTKEYS_TOD_TITLE": "", "SETTINGS_HOTKEYS_TOD_DESC": "", "SETTINGS_HOTKEYS_TOD_NONE": "", "SETTINGS_HOTKEYS_TOD_SOFT": "", "SETTINGS_HOTKEYS_TOD_HARD": "", "SETTINGS_HOTKEYS_TOD_BOTH": "", "SETTINGS_HOTKEYS_TOD_NOTE": "", "SETTINGS_HOTKEYS_BREAK_TITLE": "", "SETTINGS_HOTKEYS_BREAK_DESC": "", "SETTINGS_UPDATES_TITLE": "به‌روز رسانی", "SETTINGS_UPDATES_VERSION": "شما Twinkle Tray {{1}} را دارید.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "به صورت خودکار وجود نسخه‌های جدید رو چک کن", "SETTINGS_UPDATES_AUTOMATIC_DESC": "وقتی نسخه جدید در دسترس باشد، در پنل روشنایی نشان داده خواهد شد.", "SETTINGS_UPDATES_MS_STORE": "برای چک کردن نسخه جدید، به اپ مایکروسافت استور مراجعه کنید.", "SETTINGS_UPDATES_AVAILABLE": "نسخه جدیدی از Twinkle Tray در دسترس است!", "SETTINGS_UPDATES_NONE_AVAILABLE": "آخرین نسخه. نسخه کنونی شامل این تغییرات است:", "SETTINGS_UPDATES_DOWNLOADING": "در حال دانلود آپدیت…", "SETTINGS_UPDATES_DOWNLOAD": "دانلود و نصب {{1}}", "SETTINGS_UPDATES_CHANNEL": "کانال آپدیت", "SETTINGS_UPDATES_BRANCH_STABLE": "پایدار (پیش فرض)", "SETTINGS_UPDATES_BRANCH_BETA": "آزمایشی", "SETTINGS_FEATURES_POWER_OFF": "خاموش کردن", "GENERIC_DEFAULT": "پیش فرض", "GENERIC_OPTIONAL": "اختیاری", "PANEL_LABEL_TURN_ON": "روشن کردن", "GENERIC_DELETE": "حذف", "SETTINGS_TIME_LAT": "عرض جغرافیایی", "SETTINGS_TIME_LONG": "طول", "SETTINGS_TIME_SUN_GET": "گرفتن مختصات", "SETTINGS_TIME_IDLE_FS_TITLE": "نرم‌افزارهای تمام صفحه، سیستم تشخیص حالت بیکار را از کار می‌اندازد", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "سازگار ترین", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "اجبار شده", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "کادر تنظیم روشنایی بالا تر از اغلب برنامه ها نمایش داده می‌شود، به جز برنامه هایی که با «همیشه بالا ترین» نشان داده شده اند.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "روش قدیمی تشخیص «DDC/CI»", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "همیشه تا حد امکان کادر(overlay) تنظیم روشنایی را بالای بقیه پنجره ها نمایش بده. این گزینه می‌تواند در کارکرد بازی ها و برنامه های تمام صفحه مشکل ایجاد کند. همچنین می‌تواند سیستم آنتی چیت بعضی بازی ها را فعال کند.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "اعمال کردن خودکار روشنایی", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "استفاده از روش قدیمی(نسخه 1.15.5) برای تشخیص نمایشگر های «DDC/CI».", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "غیر فعال کردن اعمال خودکار برای نمایشگر های مشخص", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "غیر فعال کردن اعمال خودکار روشنایی بعد از تغییر وضعیت اتصال یا روشن بودن برای نمایشگر های مشخص. این گزینه شامل قابلیت تشخیص بی استفاده ماندن دستگاه است.", "SETTINGS_GENERAL_REPORT_TITLE": "ساخت گزارش", "SETTINGS_GENERAL_REPORT_DESC": "ذخیره یک فایل متنی حاوی اطلاعات در مورد نمایشگر های شما و تنظیمات لازم برای دیباگ کردن.", "SETTINGS_FEATURES_ADD": "افزودن قابلیت", "SETTINGS_FEATURES_ADD_VCP": "کد VCP", "SETTINGS_FEATURES_ADD_EXISTS": "این قابلیت هم اکنون فعال است.", "SETTINGS_TIME_SUN_TITLE": "مختصات برای موقعیت خورشید", "SETTINGS_TIME_SUN_DESC": "برای استفاده از«موقعیت خورشید» برای تنظیم میزان روشنایی، طول و عرض جغرافیایی خود را وارد کنید تا اوقات روز قابل مشخص کردن باشند.", "SETTINGS_PROFILES_NAME": "نام پروفایل", "SETTINGS_PROFILES_TITLE": "پروفایل ها", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "در صورتی که نمایشگر شما پس از خاموش، روشن، قطع یا وصل شدن رفتار عجیبی از خود نشان می‌دهد، غیر فعال کردن این گزینه ممکن است کمک کند.", "SETTINGS_HOTKEY_VALUE": "مقدار", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "یک عدد وارد کنید", "SETTINGS_HOTKEY_ADD_VALUE": "اضافه کردن مقدار", "SETTINGS_HOTKEY_VALUES": "مقدار ها", "SETTINGS_PROFILES_ADD": "پروفایل جدید", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "تنظیم روشنایی هنگام فعال بودن", "SETTINGS_PROFILES_TRIGGER_TITLE": "تنظیمات فعال کردن با برنامه", "SETTINGS_PROFILES_APP_PATH": "اضافه کردن مسیر", "SETTINGS_FEATURES_POWER_COMPAT": "سازگار ترین", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "روشنایی" } ================================================ FILE: src/localization/fi.json ================================================ { "LANGUAGE": "Suomi", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Peruuta", "GENERIC_SAVE": "Tallenna", "GENERIC_CLEAR": "Tyhjennä", "GENERIC_OFF": "Pois", "GENERIC_ON": "Päällä", "GENERIC_QUIT": "Poistu", "GENERIC_CLOSE": "Sulje", "GENERIC_SETTINGS": "Asetukset", "GENERIC_INSTALL": "Asenna", "GENERIC_DISMISS": "Hylkää", "GENERIC_DISPLAY_SINGLE": "Näyttö", "GENERIC_ALL_DISPLAYS": "Kaikki näytöt", "GENERIC_REFRESH_DISPLAYS": "Virkistä näytöt", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Max", "GENERIC_NO_DISPLAYS": "Näyttöjä ei havaittu. Liitä näyttö tietokoneeseesi.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Yhteensopivia näyttöjä ei löytynyt. Tarkista, että \"DDC/CI\" on käytössä näytöissäsi.", "GENERIC_NO_DISPLAYS_SHORT": "Yhteensopivia näyttöjä ei havaittu.", "GENERIC_SECONDS": "sekuntia", "GENERIC_MINUTES": "minuuttia", "GENERIC_DDC_WARNING": "DDC/CI-ominaisuudet voivat aiheuttaa että näyttö lakkaa reagoimasta. Käytä omalla vastuullasi.", "GENERIC_SPEED_INSTANT": "Välitön", "GENERIC_SPEED_SLOW": "Hidas", "GENERIC_SPEED_VERY_SLOW": "Erittäin hidas", "GENERIC_SPEED_NORMAL": "Normaali", "GENERIC_SPEED_FAST": "Nopea", "GENERIC_SPEED_VERY_FAST": "Erittäin nopea", "GENERIC_PAUSE_TOD": "Keskeytysajan säädöt", "GENERIC_PAUSE_IDLE": "Keskeytä toimettomuuden tunnistus", "PANEL_TITLE": "Säädä kirkkautta", "PANEL_UPDATE_AVAILABLE": "Uusi versio saatavilla", "PANEL_BUTTON_LINK_LEVELS": "Linkitetyt tasot", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Sammuta näytöt", "PANEL_LABEL_BRIGHTNESS": "Kirkkaus", "PANEL_LABEL_CONTRAST": "Kontrasti", "PANEL_LABEL_OFF_ON": "Virran tila", "PANEL_LABEL_COLOR_TEMPERATURE": "Värilämpötila", "PANEL_LABEL_VOLUME": "Voimakkuus", "PANEL_LABEL_TURN_OFF": "Sammuta", "INTRO_TITLE": "Hei, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Twinkle Trayn tehtäväpalkin kuvake on todennäköisesti piilotettu, joten sinun tulee siirtää se paikkaan, josta pääset siihen helposti käsiksi. Katso ohjeet alta.", "SETTINGS_TITLE": "Twinkle Trayn asetukset", "SETTINGS_SIDEBAR_GENERAL": "Yleisasetukset", "SETTINGS_SIDEBAR_MONITORS": "Näytön asetukset", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI-ominaisuudet", "SETTINGS_SIDEBAR_TIME": "Ajan säädöt", "SETTINGS_SIDEBAR_HOTKEYS": "Pikanäppäimet & oikopolut", "SETTINGS_SIDEBAR_UPDATES": "Päivitykset", "SETTINGS_GENERAL_TITLE": "Yleiset", "SETTINGS_GENERAL_STARTUP": "Käynnistä tietokoneen käynnistyksen yhteydessä", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Käytä kirkkautta käynnistyksen yhteydessä", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Palauta kunkin näytön viimeisin tunnistettu kirkkaus, kun Twinkle Tray käynnistyy.", "SETTINGS_GENERAL_THEME_TITLE": "Teema", "SETTINGS_GENERAL_THEME_SYSTEM": "Järjestelmäasetukset (oletus)", "SETTINGS_GENERAL_THEME_DARK": "Tumma", "SETTINGS_GENERAL_THEME_LIGHT": "Vaalea", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Kieli", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Järjestelmän kieli (oletus)", "SETTINGS_GENERAL_RESET_TITLE": "Palauta asetukset", "SETTINGS_GENERAL_RESET_DESC": "Paina tätä painiketta tyhjentääksesi asetukset.", "SETTINGS_GENERAL_RESET_BUTTON": "Palauta asetukset", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akryylinen sumennus", "SETTINGS_GENERAL_ACRYLIC_DESC": "Ota käyttöön tai poista käytöstä läpinäkyvien taustojen sumennus Twinkle Trayssa.", "SETTINGS_GENERAL_MICA_TITLE": "Kiiltosumennos", "SETTINGS_GENERAL_MICA_DESC": "Ota käyttöön tai poista käytöstä Twinkle Trayn taustan takana oleva sumennus.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analytiikkatiedot", "SETTINGS_GENERAL_ANALYTICS_DESC": "Lähetä käyttötietoja parantaaksesi Twinkle Tray:ä. Henkilötietoja ei lähetetä. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Lue lisää", "SETTINGS_GENERAL_SCROLL_TITLE": "Tehtäväpalkin kuvakkeen vierityspikakuvake", "SETTINGS_GENERAL_SCROLL_DESC": "Säädä kaikkien näyttöjen kirkkautta kerralla vierittämällä ilmaisinalueen kuvakkeen yli. Tämä ei toimi joidenkin tasohiirien kanssa.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Ilmaisinalueen kuvake", "SETTINGS_GENERAL_TROUBLESHOOTING": "Vianetsintä", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Käytössä olevat näytön tunnistusmenetelmät", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Jos Twinkle Tray ei vastaa, kun napsautat ilmoituspalkin kuvaketta tai et havaitse näyttöjäsi, voit yrittää poistaa käytöstä tietyt näytön tunnistusmenetelmät. Käynnistä Twinkle Tray uudelleen, jotta muutokset tulevat voimaan. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Poista peittokuva käytöstä", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Jos Twinkle Trayn pikanäppäimet häiritsee koko näytön sovelluksia, voit poistaa ne käytöstä täällä.", "SETTINGS_MONITORS_RATE_TITLE": "Kirkkauden päivitysnopeus", "SETTINGS_MONITORS_RATE_DESC": "Kuinka usein näyttösi kirkkaus päivitetään, kun säädät niiden arvoja. Pidennä aikaa, jos näytöt vilkkuvat.", "SETTINGS_MONITORS_RATE_0": "Naurettava", "SETTINGS_MONITORS_RATE_1": "Nopea (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normaali (500 ms)", "SETTINGS_MONITORS_RATE_3": "Hidas (1 sekunti)", "SETTINGS_MONITORS_RATE_4": "Erittäin hidas (2 sekuntia)", "SETTINGS_MONITORS_RENAME_TITLE": "Nimeä näytöt uudelleen", "SETTINGS_MONITORS_RENAME_DESC": "Jos haluat eri nimen jokaiselle näytölle (esim. \"Vasen näyttö\", \"Keskinäyttö\"), voit kirjoittaa sen alle. Kentän jättäminen tyhjäksi palauttaa alkuperäisen nimen.", "SETTINGS_MONITORS_ENTER_NAME": "Kirjoita nimi", "SETTINGS_MONITORS_REORDER_TITLE": "Järjestä näytöt uudelleen", "SETTINGS_MONITORS_REORDER_DESC": "Muuta näyttöjen järjestystä kuvakkeessa. Napsauta ja vedä tehdäksesi muutoksia.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalisoi kirkkaus", "SETTINGS_MONITORS_NORMALIZE_DESC": "Näytöissä on usein erilaiset kirkkausalueet. Rajoittamalla näytön minimi-/maksimikirkkautta näyttöjen väliset kirkkaustasot ovat paljon yhdenmukaisempia. Samanlaiset näytöt käyttävät samoja asetuksia.", "SETTINGS_MONITORS_DETAILS_NAME": "Nimi", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Sisäinen nimi", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Viestintämenetelmä", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Nykyinen kirkkaus", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maksimi kirkkaus", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Kirkkauden normalisointi", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Piilota ei-aktiivinen sisäinen näyttö", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Kun kansi on suljettu tai sisäinen näyttö on poistettu käytöstä Windowsissa, piilota paneelin kirkkauden liukusäädin.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Piilota näytöt", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Jos haluat piilottaa tietyt näytöt, voit kytkeä ne pois päältä tästä.", "SETTINGS_FEATURES_DESCRIPTION": "Ota käyttöön tai poista käytöstä tietyt DDC/CI-ominaisuudet kirkkauspaneelissa. Vähintään yhden ominaisuuden on oltava käytössä, jotta näyttösi näkyy kirkkauspaneelissa. Kaikki näytöt eivät tue näitä ominaisuuksia, kuten kannettavan tietokoneen/tabletin näytöt.", "SETTINGS_FEATURES_UNSUPPORTED": "Tämä näyttö ei tue DDC/CI-ominaisuuksia.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Tarkista nykyiset arvot", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Hae aina uusimmat arvot näytöstä, kun avaat kirkkauspaneelin. Ota tämä käyttöön, jos kirkkaus (tai muut VCP-koodit, kuten kontrasti) muuttuvat usein Twinkle Trayn ulkopuolelta.", "SETTINGS_TIME_TITLE": "Kellonaikaan perustuvat säädöt", "SETTINGS_TIME_DESC": "Aseta näytöt automaattisesti tietylle kirkkaustasolle haluttuun aikaan. Kaikki näytöt asetetaan samalle normalisoidulle tasolle.", "SETTINGS_TIME_ADD": "Lisää aika", "SETTINGS_TIME_REMOVE": "Poista aika", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Aseta yksittäisten näyttöjen kirkkaus", "SETTINGS_TIME_INDIVIDUAL_DESC": "Määritä kirkkaus näyttöä kohden kaikkien näyttöjen yhtäaikaisen sijaan.", "SETTINGS_TIME_TRANSITON_TITLE": "Kirkkauden siirtymänopeus", "SETTINGS_TIME_TRANSITON_DESC": "Kuinka nopeasti kirkkauden tulisi muuttua, kun kellonajan säädöt ovat käytössä.", "SETTINGS_TIME_STARTUP_TITLE": "Tarkista sovelluksen käynnistyksen yhteydessä", "SETTINGS_TIME_STARTUP_DESC": "Säädä kirkkaus vastaamaan sopivinta ajankohtaa, kun Twinkle Tray käynnistyy.", "SETTINGS_TIME_IDLE_TITLE": "Toimettomuuden tunnistus", "SETTINGS_TIME_IDLE_DESC": "Jos käyttöä ei havaita vähään aikaan, kaikkien näyttöjen kirkkaus vähenee.", "SETTINGS_TIME_ANIMATE_TITLE": "Animoi aikojen välillä", "SETTINGS_TIME_ANIMATE_DESC": "Kirkkausarvot animoidaan nykyisen ja seuraavan ajoitetun tapahtuman välillä. Saattaa lisätä suorittimen käyttöä. Manuaaliset kirkkauden säädöt korvataan nopeasti, kun tämä on aktiivinen.", "SETTINGS_HOTKEYS_TITLE": "Pikanäppäimet", "SETTINGS_HOTKEYS_DESC": "Määritä pikanäppäimet säätämään yhden tai kaikkien näyttöjen kirkkautta.", "SETTINGS_HOTKEYS_ADD": "Lisää pikanäppäin", "SETTINGS_HOTKEYS_REMOVE": "Poista pikanäppäin", "SETTINGS_HOTKEYS_INCREASE": "Lisää kirkkautta", "SETTINGS_HOTKEYS_DECREASE": "Vähennä kirkkautta", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Paina näppäimiä tässä", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Kirkkaustason säätö", "SETTINGS_HOTKEYS_LEVEL_DESC": "Kuinka paljon kirkkautta säädetään pikanäppäimiä käytettäessä.", "SETTINGS_HOTKEYS_TOD_TITLE": "Sammuta näytöt toiminto", "SETTINGS_HOTKEYS_TOD_DESC": "Mukauta lähetettävää signaalia, kun käytät Sammuta näytöt -pikanäppäintä tai -kuvaketta. Ohjelmistosignaali näyttää mustan näytön, kunnes Windows havaitsee syötteen (esim. hiiri tai näppäimistö). Laitteistosignaali katkaisee virran monitoreista.", "SETTINGS_HOTKEYS_TOD_NONE": "Ei mitään (piilota kuvake)", "SETTINGS_HOTKEYS_TOD_SOFT": "Ohjelmistosignaali (oletus)", "SETTINGS_HOTKEYS_TOD_HARD": "Laitteisto* signaali (vain DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Laitteisto* ja ohjelmistosignaali", "SETTINGS_HOTKEYS_TOD_NOTE": "*Huomaa: Kaikki DDC/CI-näytöt eivät tue tätä ominaisuutta.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Pikanäppäimet rikkovat linkitetyt tasot", "SETTINGS_HOTKEYS_BREAK_DESC": "Kun pikanäppäintä käytetään yksittäiselle näytölle ja \"linkitetty taso\" on aktiivinen, se poistetaan käytöstä.", "SETTINGS_UPDATES_TITLE": "Päivitykset", "SETTINGS_UPDATES_VERSION": "Sinulla on Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Tarkista automaattisesti uudet versiot", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Kun uusi versio on saatavilla, se näkyy kirkkauspaneelissa.", "SETTINGS_UPDATES_MS_STORE": "Tarkista uudet versiot Microsoft Storesta.", "SETTINGS_UPDATES_AVAILABLE": "Uusi versio Twinkle Traysta saatavilla!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Ajan tasalla. Nykyinen versio sisältää seuraavat muutokset:", "SETTINGS_UPDATES_DOWNLOADING": "Ladataan päivitystä…", "SETTINGS_UPDATES_DOWNLOAD": "Lataa ja asenna {{1}}", "SETTINGS_UPDATES_CHANNEL": "Päivityskanava", "SETTINGS_UPDATES_BRANCH_STABLE": "Vakaa (oletus)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Sammuta", "GENERIC_DELETE": "Poista", "GENERIC_DEFAULT": "Oletus", "GENERIC_OPTIONAL": "Valinnainen", "PANEL_LABEL_TURN_ON": "Käynnistä", "SETTINGS_GENERAL_OVERLAY_TITLE": "Peittokuvan oletuskäyttäytyminen", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Yhteensopivin", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Peittokuva näkyy useimpien ikkunoiden päällä, mutta se ei pakota itseään sovellusten yläpuolelle, jotka on merkitty \"aina päällä\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Pakotettu päälle", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Vanha DDC/CI-tunnistusmenetelmä", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Käytä vanhaa v1.15.5-menetelmää DDC/CI-näyttöjen tunnistamiseen.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Lisää kirkkautta automaattisesti", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Jos näyttösi reagoi oudosti sen sammuttamisen/käynnistyksen tai laitteiston irrottamisen/liittämisen jälkeen, tämän poistaminen käytöstä voi auttaa.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Ohita automaattinen lisäys tietyille näytöille", "SETTINGS_FEATURES_POWER_TITLE": "Virtatilan signaali", "SETTINGS_FEATURES_POWER_DESC": "Kun lähetät DDC/CI-komennon näytön sammuttamiseksi, seuraavat arvot lähetetään.", "SETTINGS_HOTKEY_ACTION_OFFSET": "Säädä arvoa", "SETTINGS_GENERAL_REPORT_TITLE": "Luo raportti", "SETTINGS_FEATURES_POWER_STANDBY": "Valmiustila", "SETTINGS_FEATURES_POWER_COMPAT": "Yhteensopivin", "SETTINGS_FEATURES_ADD": "Lisää ominaisuus", "SETTINGS_FEATURES_ADD_VCP": "VCP-koodi", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP-koodi (esim. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Tämä ominaisuus on jo aktiivinen.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Kaikki tämän näytön ilmoittamat VCP-koodit", "SETTINGS_FEATURES_VCP_LIST_DESC": "Seuraavassa on luettelo käytettävissä olevista VCP-koodeista, jotka tämä näyttö ilmoittaa Windowsille. Twinkle Tray ei vahvista näiden VCP-koodien toimivuutta tai vakautta. Käytä niitä omalla vastuullasi.", "SETTINGS_FEATURES_VCP_EXPECTED": "Odotetut arvot", "SETTINGS_TIME_SUN_TITLE": "Auringon sijainnin koordinaatit", "SETTINGS_TIME_LAT": "Leveysaste", "SETTINGS_TIME_LONG": "Pituusaste", "SETTINGS_TIME_SUN_GET": "Hae koordinaatit", "SETTINGS_HOTKEY_TARGET": "Määritä komento", "SETTINGS_HOTKEY_VALUES": "Arvot", "SETTINGS_GENERAL_OVERLAY_DESC": "Kuinka voimakkaasti kirkkauden pikanäppäinpeitto yrittää näyttää muiden sovellusten päällä. Sinun ei tarvitse säätää tätä.", "SETTINGS_PROFILES_DESC": "Säädä kirkkautta tai pikakuvakkeen peittokuvaa automaattisesti kohdistetusta sovelluksesta riippuen. Voit myös lisätä profiileja ilmaisinalueen hiiren kakkospainikkeella olevaan valikkoon muuttaaksesi kirkkauden nopeasti ennalta määritettyihin profiileihin.", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Yritä aina näyttää peittokuva muiden ikkunoiden päällä. Tämä voi aiheuttaa ongelmia eksklusiivisissa koko näytön peleissä ja muissa koko näytön sovelluksissa. Se voi myös laukaista huijauksen eston joissakin peleissä.", "SETTINGS_GENERAL_REPORT_DESC": "Tallenna tekstitiedosto, jossa on tietoja näytöistäsi ja virheenkorjausasetuksista.", "SETTINGS_FEATURES_POWER_WARNING": "\"Valmiustila\" -vaihtoehto mahdollistaa todennäköisemmin näytön kytkemisen päälle/pois Twinkle Traysta. Monet näytöt eivät kuitenkaan reagoi oikein muuttuvaan virtatilaan. Käytä omalla vastuullasi.", "SETTINGS_FEATURES_ADD_DESC": "Anna sen ominaisuuden VCP-koodi, jonka haluat lisätä näyttöön. Huomaa, että Twinkle Tray ei vahvista, tukeeko näyttö todella tätä VCP-koodia. Käytä omalla vastuullasi.", "SETTINGS_TIME_SUN_DESC": "Jos haluat käyttää \"auringon sijaintia\" ajan säätämiseen, anna nykyinen leveys- ja pituusaste, jotta oikeat ajat voidaan määrittää.", "SETTINGS_TIME_IDLE_FS_TITLE": "Koko näytön sovellukset estävät käyttämättömyyden tunnistuksen", "SETTINGS_TIME_IDLE_FS_DESC": "Koko näytön sovellukset estävät käyttämättömän käytön. Tämä koskee vain tarkennettua ikkunaa.", "SETTINGS_HOTKEY_OFF_WARN": "Tämä toiminto käyttää kohdassa \"Näytöt pois päältä -toiminto\" valittua vaihtoehtoa. Jos haluat sen sijaan sammuttaa tietyt näytöt, käytä sen sijaan \"Aseta\" tai \"Kierrä\"-pikanäppäintoimintoa.", "SETTINGS_PROFILES_OVERLAY_DESC": "Muuttaa pikanäppäinpeittokuvan toimintaa, kun määritetty sovellus on kohdistettu. Tämä ominaisuus ei toimi, kun profiili on aktivoitu manuaalisesti.", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Poista käytöstä tunnetun kirkkauden automaattinen käyttöönotto kaikkien laitteisto-/virtatapahtumien jälkeen tietyissä näytöissä. Tämä sisältää käyttämättömyyden tunnistusominaisuuden.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Rullattava määrä", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Media estää toimettomuuden havaitsemisen", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Toimettomuuden tunnistus poistetaan käytöstä, kun mediaa toistetaan. Tämä sisältää sekä videon että äänen. Tämä pätee vain, kun Windows ilmoittaa, että mediaa toistetaan.", "SETTINGS_PROFILES_APP_PATH": "Sovelluksen polku", "SETTINGS_PROFILES_APP_DESC": "Jos haluat tämän profiilin aktivoituvan automaattisesti, kun tietty sovellus on kohdistettu, syötä EXE:n koko tai osittainen polku alle.", "SETTINGS_HOTKEY_VALUE": "Arvo", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Lisää numero", "SETTINGS_HOTKEY_ADD_VALUE": "Lisää arvo", "SETTINGS_HOTKEY_ACTION": "Toiminto", "SETTINGS_HOTKEY_ACTION_SET": "Aseta arvo", "SETTINGS_HOTKEY_ACTION_CYCLE": "Kierrä arvoluettelo", "SETTINGS_PROFILES_TITLE": "Profiilit", "SETTINGS_PROFILES_ADD": "Uusi profiili", "SETTINGS_PROFILES_NAME": "Profiilin nimi", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Aseta kirkkaus kun aktiivisena", "SETTINGS_PROFILES_SHOW_MENU": "Näytä hiiren kakkospainikkeen valikossa", "SETTINGS_PROFILES_TRIGGER_TITLE": "Sovelluksen käynnistysasetukset", "SETTINGS_PROFILES_OVERLAY_TITLE": "Ohita peittokuvatyyppi", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Käännä vieritys", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Kun vierität ilmaisinalueen kuvaketta, vierityssuunta vaihtuu.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Poista käytöstä lukitusnäytössä", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Älä käytä monitoreja, kun käyttäjäistunto on lukittu välttääksesi ristiriidat usean käyttäjän ympäristöissä.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR-näytön asetukset", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Ota SDR-kirkkauden liukusäätimet käyttöön. Näytöissä on oltava HDR käytössä Windowsissa, jotta tämä toimisi.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR Korvaa ensisijaisen liukusäätimen", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Ohjaa SDR-kirkkautta kirkkauden pääliukusäätimellä, kun HDR on aktiivinen.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR-kirkkaus", "GENERIC_NOT_SUPPORTED": "Ei tuettu", "GENERIC_SUPPORTED": "Tuettu", "GENERIC_UNSUPPORTED": "Ei tuettu", "GENERIC_ACTIVE": "Aktiivinen", "GENERIC_DETECTING_DISPLAYS": "Havaitaan näyttöjä…", "PANEL_LABEL_INPUTS": "Liitännät", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Ikkunan teema", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Teeman päivityksen tunnistus", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Havaitsee korostuksen, taustakuvan, teeman muutokset Windowsista ja päivittää tehtäväpalkin ilmoitusalueen ja Mica effektin. Tämän poistaminen käytöstä voi parantaa suorituskykyä.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Havaitse virransäästötilan muutokset", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Havaitse näyttöjen virransäästötilojen muutokset. Tämän poistaminen käytöstä voi auttaa, jos kohtaat virheitä, kun näytöt sammutetaan/käynnistetään tai ne ovat käyttämättömänä. Vaatii uudelleenkäynnistyksen.", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_TIME_USE_SUN_POSITION": "Käytä auringon sijaintia", "SETTINGS_HOTKEY_ADD_ACTION": "Lisää toiminto" } ================================================ FILE: src/localization/fr.json ================================================ { "LANGUAGE": "Français", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Annuler", "GENERIC_SAVE": "Enregistrer", "GENERIC_CLEAR": "Effacer", "GENERIC_OFF": "Non", "GENERIC_ON": "Oui", "GENERIC_QUIT": "Quitter", "GENERIC_CLOSE": "Fermer", "GENERIC_SETTINGS": "Paramètres", "GENERIC_INSTALL": "Installer", "GENERIC_DISMISS": "Annuler", "GENERIC_DISPLAY_SINGLE": "Écran", "GENERIC_ALL_DISPLAYS": "Tous les écrans", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Max", "GENERIC_NO_DISPLAYS": "Aucun écran détecté. Veuillez connecter un écran à votre ordinateur.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Aucun écran compatible détecté. Veuillez vérifier que \"DDC/CI\" est activé pour votre écran.", "GENERIC_NO_DISPLAYS_SHORT": "Aucun écran compatible détecté.", "PANEL_TITLE": "Ajuster la luminosité", "PANEL_UPDATE_AVAILABLE": "Une nouvelle version est disponible", "PANEL_BUTTON_LINK_LEVELS": "Synchroniser les niveaux", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Éteindre les écrans", "INTRO_TITLE": "Bienvenue, Twinkle Tray !", "INTRO_INSTRUCTIONS": "L'icône de la zone de notification pour Twinkle Tray est probablement cachée. Vous devrez sûrement la déplacer du menu pour y avoir accès plus facilement. Vous pouvez retrouver les instructions ci-dessous.", "SETTINGS_TITLE": "Paramètres de Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Général", "SETTINGS_SIDEBAR_MONITORS": "Paramètres du moniteur", "SETTINGS_SIDEBAR_TIME": "Ajustement selon l'heure", "SETTINGS_SIDEBAR_HOTKEYS": "Raccourcis", "SETTINGS_SIDEBAR_UPDATES": "Mises à jour", "SETTINGS_GENERAL_TITLE": "Général", "SETTINGS_GENERAL_STARTUP": "Lancement au démarrage", "SETTINGS_GENERAL_THEME_TITLE": "Thème", "SETTINGS_GENERAL_THEME_SYSTEM": "Préférences du système (par défaut)", "SETTINGS_GENERAL_THEME_DARK": "Mode sombre", "SETTINGS_GENERAL_THEME_LIGHT": "Mode clair", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Langue", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Langue du système (par défaut)", "SETTINGS_GENERAL_RESET_TITLE": "Réinitialiser", "SETTINGS_GENERAL_RESET_DESC": "Ce bouton permet d'effacer vos réglages.", "SETTINGS_GENERAL_RESET_BUTTON": "Réinitialiser les paramètres", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Données d'analyse", "SETTINGS_GENERAL_ANALYTICS_DESC": "Envoyer des données d'utilisation pour aider à améliorer Twinkle Tray. Aucune donnée personnelle n'est envoyée. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "En savoir plus", "SETTINGS_MONITORS_RATE_TITLE": "Fréquence de mise à jour de la luminosité", "SETTINGS_MONITORS_RATE_DESC": "La fréquence à laquelle la luminosité sera mise à jour sur vos écrans lorsque vous ajustez leurs valeurs. Augmentez la durée si vos écrans clignotent.", "SETTINGS_MONITORS_RATE_0": "Vitesse de la lumière", "SETTINGS_MONITORS_RATE_1": "Rapide (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Lent (1 seconde)", "SETTINGS_MONITORS_RATE_4": "Très lent (2 secondes)", "SETTINGS_MONITORS_RENAME_TITLE": "Renommer les écrans", "SETTINGS_MONITORS_RENAME_DESC": "Si vous préférez un nom différent pour chaque écran (ex : \"écran gauche\", \"écran central\"), vous pouvez le saisir ci-dessous. Si vous laissez le champ vide, le nom d'origine sera rétabli.", "SETTINGS_MONITORS_ENTER_NAME": "Choisir un nom", "SETTINGS_MONITORS_REORDER_TITLE": "Réorganiser les écrans", "SETTINGS_MONITORS_REORDER_DESC": "Modifier l'ordre d'affichage des moniteurs dans le menu. Cliquez et faites glisser pour effectuer des modifications.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normaliser la luminosité", "SETTINGS_MONITORS_NORMALIZE_DESC": "Les écrans ont souvent des plages de luminosité différentes. En limitant la luminosité min/max par écran, les niveaux de luminosité entre les écrans sont beaucoup plus cohérents. Des écrans similaires utiliseront les mêmes réglages.", "SETTINGS_TIME_TITLE": "Ajustement selon l'heure", "SETTINGS_TIME_DESC": "Réglez automatiquement vos écrans à un niveau de luminosité spécifique à un moment donné. Tous les écrans seront réglés sur les mêmes niveaux normalisés.", "SETTINGS_TIME_ADD": "Ajouter une période", "SETTINGS_TIME_REMOVE": "Supprimer la période", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Régler la luminosité des écrans individuellement", "SETTINGS_TIME_INDIVIDUAL_DESC": "Configurer la luminosité pour chaque écran au lieu de tous à la fois.", "SETTINGS_TIME_STARTUP_TITLE": "Vérifier au démarrage de l'application", "SETTINGS_TIME_STARTUP_DESC": "Réglez la luminosité pour qu'elle corresponde au moment le plus pertinent quand Twinkle Tray démarre.", "SETTINGS_HOTKEYS_TITLE": "Raccourcis clavier", "SETTINGS_HOTKEYS_DESC": "Configurez les touches de raccourci pour régler la luminosité d'un ou de tous les écrans.", "SETTINGS_HOTKEYS_ADD": "Ajouter un raccourci", "SETTINGS_HOTKEYS_REMOVE": "Supprimer le raccourci", "SETTINGS_HOTKEYS_INCREASE": "Augmenter la luminosité", "SETTINGS_HOTKEYS_DECREASE": "Réduire la luminosité", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Appuyer sur une touche", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Réglage du niveau de luminosité", "SETTINGS_HOTKEYS_LEVEL_DESC": "De combien la luminosité doit-elle être ajustée lors de l'utilisation des raccourcis clavier.", "SETTINGS_UPDATES_TITLE": "Mises à jour", "SETTINGS_UPDATES_VERSION": "Vous avez Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Rechercher automatiquement une nouvelle version", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Quand il y a une nouvelle version, elle est indiquée dans le panneau de luminosité.", "SETTINGS_UPDATES_MS_STORE": "Pour rechercher une nouvelle version, consultez le Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Une nouvelle version de Twinkle Tray est disponible !", "SETTINGS_UPDATES_NONE_AVAILABLE": "À jour. Cette version de Twinkle Tray comprend les changements suivants :", "SETTINGS_UPDATES_DOWNLOADING": "Téléchargement de la mise à jour…", "SETTINGS_UPDATES_DOWNLOAD": "Télécharger & Installer {{1}}", "SETTINGS_GENERAL_SCROLL_TITLE": "Raccourci de défilement de la souris sur l'icône dans la zone de notification", "SETTINGS_GENERAL_SCROLL_DESC": "Régler la luminosité de tous les écrans à la fois en faisant défiler la souris sur l'icône dans la zone de notification. Cela ne fonctionne pas avec certains trackpads.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Icône dans la zone de notification", "SETTINGS_GENERAL_ACRYLIC_DESC": "Activer ou désactiver le flou derrière les arrière-plans transparents dans Twinkle Tray.", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Flou acrylique", "SETTINGS_MONITORS_FEATURES_DESCRIPTION": "Activer ou désactiver des fonctionnalités DDC/CI spécifiques dans le panneau de luminosité. Au moins une fonctionnalité doit être activée pour que votre écran s'affiche dans le panneau de luminosité. Tous les écrans ne supportent pas ces fonctionnalités, tels que les écrans d'ordinateur portable/tablette.", "SETTINGS_MONITORS_FEATURES_TITLE": "Fonctionnalités DDC/CI", "PANEL_LABEL_COLOR_TEMPERATURE": "Température de couleur", "PANEL_LABEL_OFF_ON": "État de l'alimentation", "PANEL_LABEL_CONTRAST": "Contraste", "PANEL_LABEL_BRIGHTNESS": "Luminosité", "SETTINGS_SIDEBAR_FEATURES": "Fonctionnalités DDC/CI", "GENERIC_REFRESH_DISPLAYS": "Rafraichir la liste des écrans", "SETTINGS_HOTKEYS_BREAK_DESC": "Lors de l'utilisation d'une touche d'un raccourci pour un écran unique, la synchronisation des niveaux est désactivé.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Les raccourcis désactivent la synchronisation", "SETTINGS_HOTKEYS_TOD_NOTE": "*Note : Cette fonctionnalité n'est pas prise en charge par touts les écrans DDC/CI.", "SETTINGS_HOTKEYS_TOD_BOTH": "Signal matériel* et logiciel", "SETTINGS_HOTKEYS_TOD_HARD": "Signal matériel* (DDC/CI uniquement)", "SETTINGS_HOTKEYS_TOD_SOFT": "Signal logiciel (par défaut)", "SETTINGS_HOTKEYS_TOD_NONE": "Aucun (masquer l'icône)", "SETTINGS_HOTKEYS_TOD_DESC": "Personnaliser le signal envoyé lors de l'utilisation du raccourci clavier ou de l'icône Éteindre les écrans. Le signal logiciel affiche un écran noir jusqu'à qu'une interaction de l'utilisateur (ex. clavier ou souris) ne soit détecté par Windows. Le signal matériel éteint l'alimentation des écrans.", "SETTINGS_HOTKEYS_TOD_TITLE": "Action d'arrêt des écrans", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalisation de la luminosité", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Luminosité maximale", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Luminosité actuelle", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Méthode de communication", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Nom interne", "SETTINGS_MONITORS_DETAILS_NAME": "Nom", "SETTINGS_FEATURES_DESCRIPTION": "Activer ou désactiver certaines fonctionnalités DDC/CI dans le menu de configuration de la luminosité. Au moins une fonctionnalité doit être sélectionnée pour votre moniteur pour pouvoir apparaitre dans le menu de configuration de la luminosité. Ces fonctionnalités ne sont pas supportées par tous les écrans, notamment les ordinateurs portables et les tablettes.", "PANEL_LABEL_VOLUME": "Volume", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Restaurer la dernière luminosité connue pour chaque moniteur lorsque Twinkle Tray démarre.", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Appliquer la luminosité au démarrage", "GENERIC_MINUTES": "minutes", "SETTINGS_TIME_IDLE_DESC": "Quand aucune entrée n'est détectée pendant un certain temps, la luminosité de tous les affichages sera réduite.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Toujours récupérer les dernières valeurs des moniteurs à l'ouverture de la page de la luminosité. Activez cette option si la luminosité (ou d’autres codes VCP tels que le contraste) est souvent modifiée hors de Twinkle Tray.", "SETTINGS_FEATURES_UNSUPPORTED": "Cet écran ne supporte pas les fonctionnalités DDC/CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Vérifier les valeurs actuelles", "PANEL_LABEL_TURN_OFF": "Éteindre", "SETTINGS_TIME_IDLE_TITLE": "Détection d'Inactivité", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Lorsque le capot se ferme ou que l'écran interne a été désactivé par Windows, cacher la jauge de luminosité dans le panneau.", "SETTINGS_GENERAL_MICA_DESC": "Active ou désactive le flou derrière l'arrière-plan dans Twinkle Tray.", "GENERIC_SECONDS": "secondes", "SETTINGS_GENERAL_MICA_TITLE": "Flou Mica", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Cacher l'affichage interne inactif", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Si Twinkle Tray ne répond pas lorsque vous cliquez sur l'icône de la barre d'état ou ne détecte pas vos écrans, vous pouvez essayer de désactiver certaines méthodes de détection des écrans. Redémarrez Twinkle Tray pour que les modifications soient prises en compte. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Si la superposition des touches de raccourci de Twinkle Tray interfère avec les applications plein écran, vous pouvez la désactiver ici.", "SETTINGS_TIME_ANIMATE_DESC": "Les valeurs de luminosité seront animées entre l'événement actuel et le prochain événement programmé. Peut augmenter l'utilisation du CPU. Les réglages manuels de la luminosité seront rapidement écrasés lorsque cette fonction est active.", "GENERIC_PAUSE_TOD": "Ajustements du temps de pause", "GENERIC_PAUSE_IDLE": "Pause Détection de l'inactivité", "SETTINGS_GENERAL_TROUBLESHOOTING": "Dépannage", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Méthodes de détection des moniteurs activées", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Désactiver la superposition", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Masquer les affichages", "SETTINGS_TIME_TRANSITON_TITLE": "Vitesse de transition de la luminosité", "SETTINGS_TIME_TRANSITON_DESC": "La vitesse de transition de la luminosité lorsque les réglages de l'heure du jour sont activés.", "SETTINGS_TIME_ANIMATE_TITLE": "Animer entre les temps", "GENERIC_SPEED_INSTANT": "Instantané", "GENERIC_SPEED_SLOW": "Lent", "GENERIC_SPEED_VERY_SLOW": "Très lent", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_SPEED_FAST": "Rapidement", "GENERIC_SPEED_VERY_FAST": "Très rapide", "GENERIC_DDC_WARNING": "Les fonctions DDC/CI telles que le contrôle de l'état d'alimentation peuvent rendre votre moniteur insensible. Utilisez-les à vos risques et périls.", "SETTINGS_UPDATES_BRANCH_STABLE": "Stable (par défaut)", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Si vous souhaitez masquer certains affichages dans le menu déroulant, vous pouvez les désactiver ici.", "SETTINGS_UPDATES_CHANNEL": "Canal de mise à jour", "SETTINGS_UPDATES_BRANCH_BETA": "Bêta", "SETTINGS_FEATURES_POWER_OFF": "Éteindre", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Appliquer la luminosité automatiquement", "SETTINGS_FEATURES_POWER_TITLE": "Signal d'état d'allumage", "SETTINGS_FEATURES_POWER_STANDBY": "Repos", "SETTINGS_FEATURES_ADD_VCP": "Code VCP", "SETTINGS_GENERAL_REPORT_TITLE": "Rapport général", "SETTINGS_FEATURES_POWER_COMPAT": "Le plus compatible", "SETTINGS_FEATURES_ADD": "Ajouter une fonction", "SETTINGS_FEATURES_ADD_EXISTS": "Cette fonctionnalité est déjà active.", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Forcé on", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Méthode de détection DDC/CI antérieure", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Utiliser l'ancienne méthode v1.15.5 de détection d'écrans DDC/CI.", "GENERIC_DELETE": "Supprimer", "GENERIC_DEFAULT": "Défaut", "GENERIC_OPTIONAL": "Optionnel", "SETTINGS_GENERAL_OVERLAY_TITLE": "Comportement par défaut de l'overlay", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Le plus compatible", "PANEL_LABEL_TURN_ON": "Mise en marche", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Ne pas appliquer automatiquement pour certains moniteurs", "SETTINGS_FEATURES_POWER_DESC": "Lors de l’envoi de la commande DDC/CI pour éteindre votre écran, la ou les valeurs suivantes seront envoyées.", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "Code VCP (ex. 0x12)", "SETTINGS_FEATURES_VCP_EXPECTED": "Valeurs attendues", "SETTINGS_TIME_SUN_TITLE": "Coordonnées pour la position du soleil", "SETTINGS_TIME_LAT": "Latitude", "SETTINGS_TIME_LONG": "Longitude", "SETTINGS_TIME_SUN_GET": "Récupérer les coordonnées", "SETTINGS_TIME_IDLE_FS_TITLE": "Les applications plein écran ne sont jamais inactives", "SETTINGS_TIME_IDLE_FS_DESC": "Les applications plein écran bloquent la détection d’inactivité. Ceci s’applique uniquement à la fenêtre active.", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Saisissez un nombre", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Tous les codes VCP signalés par cet écran", "SETTINGS_GENERAL_REPORT_DESC": "Enregistrer un fichier texte avec des données sur vos moniteurs et vos paramètres pour le débogage.", "SETTINGS_PROFILES_ADD": "Nouveau profil", "SETTINGS_PROFILES_NAME": "Nom du profil", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Valeur du défilement", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Les médias bloquent la détection d’inactivité", "SETTINGS_TIME_IDLE_MEDIA_DESC": "La détection d’inactivité sera désactivée lors de la lecture de médias. Cela inclut à la fois la vidéo et l’audio. Cela s’applique uniquement lorsque Windows signale une lecture de média.", "SETTINGS_HOTKEY_ACTION": "Action", "SETTINGS_HOTKEY_ACTION_SET": "Définir une valeur", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Définir la luminosité quand actif", "SETTINGS_PROFILES_SHOW_MENU": "Afficher dans le menu du clic droit de la zone de notification", "SETTINGS_PROFILES_TRIGGER_TITLE": "Paramètres de déclenchement par application", "SETTINGS_PROFILES_APP_PATH": "Chemin de l’application", "SETTINGS_PROFILES_APP_DESC": "Si vous souhaitez que ce profil s’active automatiquement lorsqu’une application spécifique est active, saisissez le chemin complet ou partiel de l’EXE ci-dessous.", "SETTINGS_HOTKEY_ACTION_OFFSET": "Ajuster une valeur", "SETTINGS_HOTKEY_ACTION_CYCLE": "Traverser une liste de valeurs", "SETTINGS_PROFILES_TITLE": "Profils", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Inverser le défilement", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Lors du défilement sur l’icône dans la zone de notification, la direction du défilement sera inversée.", "SETTINGS_HOTKEY_TARGET": "Cible de l’action", "SETTINGS_HOTKEY_VALUE": "Valeur", "SETTINGS_HOTKEY_VALUES": "Valeurs", "SETTINGS_HOTKEY_ADD_VALUE": "Ajouter une valeur", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Luminosité" } ================================================ FILE: src/localization/he.json ================================================ { "LANGUAGE": "עברית", "GENERIC_OK": "אישור", "GENERIC_CANCEL": "ביטול", "GENERIC_SAVE": "שמירה", "GENERIC_CLEAR": "ניקוי", "GENERIC_DELETE": "מחיקה", "GENERIC_OFF": "כיבוי", "GENERIC_ON": "הפעלה", "GENERIC_QUIT": "יציאה", "GENERIC_CLOSE": "סגירה", "GENERIC_SETTINGS": "הגדרות", "GENERIC_INSTALL": "התקנה", "GENERIC_DISMISS": "סירוב", "GENERIC_DEFAULT": "ברירת מחדל", "GENERIC_OPTIONAL": "אופציונלי", "GENERIC_DISPLAY_SINGLE": "מסך", "GENERIC_ALL_DISPLAYS": "כל המסכים", "GENERIC_REFRESH_DISPLAYS": "רענן מסכים", "GENERIC_MINIMUM": "מינימום", "GENERIC_MAXIMUM": "מקסימום", "GENERIC_NO_DISPLAYS": "לא זוהו מסכים. אנא חבר מסך למחשב.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "לא נמצא מסך תואם. אנא בדוק ש-\"DDC/CI\" מופעל עבור המסך שלך.", "GENERIC_NO_DISPLAYS_SHORT": "לא זוהה מסך נתמך.", "GENERIC_SECONDS": "שניות", "GENERIC_MINUTES": "דקות", "GENERIC_DDC_WARNING": "אפשרויות DDC/CI עלולות לגרום למסך להפסיק להגיב. השימוש הוא על אחריותך בלבד.", "GENERIC_SPEED_INSTANT": "מיידי", "GENERIC_SPEED_SLOW": "איטי", "GENERIC_SPEED_VERY_SLOW": "איטי מאוד", "GENERIC_SPEED_NORMAL": "רגיל", "GENERIC_SPEED_FAST": "מהיר", "GENERIC_SPEED_VERY_FAST": "ממש מהיר", "GENERIC_PAUSE_TOD": "השהיית תזמון הבהירות", "GENERIC_PAUSE_IDLE": "השהיית זיהוי חוסר פעילות", "PANEL_TITLE": "שינוי בהירות", "PANEL_UPDATE_AVAILABLE": "גרסה חדשה זמינה", "PANEL_BUTTON_LINK_LEVELS": "סנכרון בהירות בכל הצגים בו-זמנית", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "כיבוי מסכים", "PANEL_LABEL_BRIGHTNESS": "בהירות", "PANEL_LABEL_CONTRAST": "ניגודיות", "PANEL_LABEL_OFF_ON": "מצב צריכת חשמל", "PANEL_LABEL_COLOR_TEMPERATURE": "טמפרטורת צבע", "PANEL_LABEL_VOLUME": "ווליום", "PANEL_LABEL_TURN_OFF": "כבה", "PANEL_LABEL_TURN_ON": "הפעל", "INTRO_TITLE": "היי, Twinkle Tray!", "INTRO_INSTRUCTIONS": "סמל המגש של Twinkle Tray כנראה מוסתר, לכן עליך להעביר אותו למקום שבו תוכל לגשת אליו בקלות. ראה הוראות להלן.", "SETTINGS_TITLE": "הגדרות Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "כללי", "SETTINGS_SIDEBAR_MONITORS": "הגדרות המסך", "SETTINGS_SIDEBAR_FEATURES": "תכונות DDC/CI", "SETTINGS_SIDEBAR_TIME": "תזמון בהירות", "SETTINGS_SIDEBAR_HOTKEYS": "קיצורי דרך", "SETTINGS_SIDEBAR_UPDATES": "עדכונים", "SETTINGS_GENERAL_TITLE": "כללי", "SETTINGS_GENERAL_STARTUP": "הפעל בעת הפעלת המחשב", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "עדכון בהירות בעת הפעלת האפליקציה", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "שחזור רמת הבהירות האחרונה הידועה עבור כל צג בעת הפעלת Twinkle Tray.", "SETTINGS_GENERAL_THEME_TITLE": "ערכת נושא", "SETTINGS_GENERAL_THEME_SYSTEM": "הגדרות מערכת (ברירת מחדל)", "SETTINGS_GENERAL_THEME_DARK": "מצב כהה", "SETTINGS_GENERAL_THEME_LIGHT": "מצב בהיר", "SETTINGS_GENERAL_LANGUAGE_TITLE": "שפה", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "שפת מערכת (ברירת מחדל)", "SETTINGS_GENERAL_RESET_TITLE": "איפוס הגדרות", "SETTINGS_GENERAL_RESET_DESC": "לחץ על כפתור זה כדי לאפס את ההגדרות שלך.", "SETTINGS_GENERAL_RESET_BUTTON": "איפוס הגדרות", "SETTINGS_GENERAL_ACRYLIC_TITLE": "טשטוש אקרילי", "SETTINGS_GENERAL_ACRYLIC_DESC": "הפעלה או השבתה של אפקט טשטוש ברקע שקוף של Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "טשטוש Mica", "SETTINGS_GENERAL_MICA_DESC": "הפעלה או השבתה של אפקט הטשטוש ברקע של Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "ניתוח נתונים", "SETTINGS_GENERAL_ANALYTICS_DESC": "שלח נתוני שימוש אנונימיים כדי לעזור לשפר את Twinkle Tray. לא נשלח מידע אישי. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "למידע נוסף", "SETTINGS_GENERAL_SCROLL_TITLE": "קיצור דרך לגלילה על סמל שורת המשימות", "SETTINGS_GENERAL_SCROLL_DESC": "כיוון הבהירות של כל הצגים בבת אחת על ידי גלילה מעל סמל האפליקציה בשורת המשימות. פעולה זו אינה פועלת עם חלק משטחי העקיבה.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "סמל שורת המשימות", "SETTINGS_GENERAL_TROUBLESHOOTING": "פתרון בעיות", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "שיטות זיהוי צגים פעילות", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "אם Twinkle Tray אינו מגיב ללחיצה על הסמל או לא מזהה צגים, באפשרותך לנסות להשבית שיטות זיהוי מסוימות של צגים. הפעל מחדש את Twinkle Tray כדי שהשינויים ייכנסו לתוקף. {{1}}", "SETTINGS_GENERAL_OVERLAY_TITLE": "התנהגות חיווי הבהירות", "SETTINGS_GENERAL_OVERLAY_DESC": "קובע אם ואיך תופיע החלונית שמציגה את אחוז הבהירות על המסך בזמן שימוש בקיצור מקשים. לא אמור להיות צורך להתאים זאת.", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "ביטול החיווי", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "אם החלונית של Twinkle Tray מפריעה ליישומים במסך מלא, ניתן להשבית אותה כאן.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "תאימות רגילה", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "החלונית תוצג על פני רוב החלונות, אך לא תכפה את עצמה מעל אפליקציות המסומנות כ\"תמיד למעלה\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "חיווי כפוי", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "נסה תמיד להציג את חלונית החיווי מעל חלונות אחרים. אפשרות זו עלולה לגרום לבעיות באפליקציות ובמשחקים הפועלים במסך מלא, ואף עלולה להפעיל מנגנוני הגנה נגד רמאויות (Anti-cheat) בחלק מהמשחקים.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "שיטת זיהוי DDC/CI מדור קודם", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "השתמש בשיטה הישנה (גרסה 1.15.5) לזיהוי צגי DDC/CI.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "החלת בהירות אוטומטית", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "אם הצג שלך מגיב בצורה מוזרה לאחר כיבוי/הדלקה או ניתוק/חיבור חומרה, השבתת פעולה זו עשויה לעזור.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "ביטול החלה אוטומטית לצגים ספציפיים", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "אם הצג מגיב בצורה משונה לאחר כיבוי והדלקה או לאחר ניתוק וחיבור של חומרה, כיבוי אפשרות זו עשוי לעזור. זה כולל את תכונת זיהוי ההתנהלות במצב סרק.", "SETTINGS_GENERAL_REPORT_TITLE": "צור דוח", "SETTINGS_GENERAL_REPORT_DESC": "שמור קובץ טקסט עם מידע על המסכים וההגדרות שלך לצורך פתרון בעיות וניפוי שגיאות.", "SETTINGS_MONITORS_RATE_TITLE": "קצב עדכון הבהירות", "SETTINGS_MONITORS_RATE_DESC": "באיזו תדירות תעודכן הבהירות בצגים שלך בזמן שאתה מכוון את הערכים שלהם. אם הצגים מהבהבים, כדאי להגדיל את משך הזמן.", "SETTINGS_MONITORS_RATE_0": "מיידי", "SETTINGS_MONITORS_RATE_1": "מהיר (רבע שנייה)", "SETTINGS_MONITORS_RATE_2": "רגיל (חצי שנייה)", "SETTINGS_MONITORS_RATE_3": "איטי (שנייה שלמה)", "SETTINGS_MONITORS_RATE_4": "ממש איטי (שתי שניות)", "SETTINGS_MONITORS_RENAME_TITLE": "שינוי שם מסך", "SETTINGS_MONITORS_RENAME_DESC": "אם אתם מעדיפים שם שונה לכל צג (לדוגמה \"צג שמאלי\", \"צג אמצעי\"), תוכלו להזין אותו למטה. השארת השדה ריק תשחזר את השם המקורי.", "SETTINGS_MONITORS_ENTER_NAME": "הכנס שם", "SETTINGS_MONITORS_REORDER_TITLE": "שנה סדר הצגים", "SETTINGS_MONITORS_REORDER_DESC": "שנה את סדר הצגת הצגים במגש. לחץ וגרור כדי לבצע שינויים.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "נרמול בהירות", "SETTINGS_MONITORS_NORMALIZE_DESC": "למסכים יש לעיתים קרובות טווחי בהירות שונים. על ידי הגבלת הבהירות המינימלית/מקסימלית לכל תצוגה, רמות הבהירות בין הצגים יהיו עקביות הרבה יותר.", "SETTINGS_MONITORS_DETAILS_NAME": "שם", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "שם פנימי", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "שיטת תקשורת", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "בהירות נוכחית", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "בהירות מקסימלית", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "נרמול בהירות", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "הסתר תצוגה פנימית לא פעילה", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "כאשר מכסה המחשב נייד סגור או שהתצוגה הפנימית הושבתה ב-Windows, הסתר את מחוון הבהירות בחלונית.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "הסתר צגים", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "אם ברצונך להסתיר צגים מסוימים מהתפריט הנשלף, ניתן לכבות אותן כאן.", "SETTINGS_FEATURES_DESCRIPTION": "הפעל או השבת תכונות DDC/CI ספציפיות בלוח הבהירות. לפחות תכונה אחת חייבת להיות מופעלת כדי שהצג שלך יופיע בלוח הבהירות. לא כל הצגים תומכים בתכונות אלה, כגון צגי מחשב נייד/טאבלט.", "SETTINGS_FEATURES_UNSUPPORTED": "צג זה אינו תומך בתכונות DDC/CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "בדוק ערכים נוכחיים", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "קבל תמיד את הערכים העדכניים ביותר מהצג בעת פתיחת לוח הבהירות. הפעל אפשרות זו אם הבהירות (או קודי VCP אחרים כמו ניגודיות) משתנים לעתים קרובות מחוץ ל-Twinkle Tray.", "SETTINGS_FEATURES_POWER_TITLE": "אות מצב צריכת חשמל", "SETTINGS_FEATURES_POWER_DESC": "בעת שליחת פקודת DDC/CI לכיבוי הצג, יישלחו הערכים הבאים.", "SETTINGS_FEATURES_POWER_STANDBY": "המתנה", "SETTINGS_FEATURES_POWER_OFF": "כבה", "SETTINGS_FEATURES_POWER_COMPAT": "הכי מותאם", "SETTINGS_FEATURES_POWER_WARNING": "האפשרות \"המתנה\" נוטה יותר לאפשר הפעלה/כיבוי של הצג דרך Twinkle Tray. עם זאת, צגים רבים אינם מגיבים כראוי לשינוי מצב הפעלה. השימוש על אחריותך בלבד.", "SETTINGS_FEATURES_ADD": "הוסף תכונה", "SETTINGS_FEATURES_ADD_DESC": "הזן את קוד ה-VCP עבור התכונה שברצונך להוסיף לתצוגה שלך. שים לב ש-Twinkle Tray אינו מאמת אם הצג שלך אכן תומך בקוד VCP זה. השימוש על אחריותך בלבד.", "SETTINGS_FEATURES_ADD_VCP": "קוד VCP", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "קוד VCP (לדוגמה: 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "תכונה זו כבר פעיל.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "כל הקודים של הVPC שהמסך דיווח", "SETTINGS_FEATURES_VCP_LIST_DESC": "להלן רשימה של קודי VCP זמינים המדווחים על ידי תצוגה זו ל-Windows. Twinkle Tray אינו מאמת את הפונקציונליות או היציבות של קודי VCP אלה. השימוש בהם על אחריותך בלבד.", "SETTINGS_FEATURES_VCP_EXPECTED": "ערך צפוי", "SETTINGS_TIME_TITLE": "שינוי בהירות מתוזמן", "SETTINGS_TIME_DESC": "הגדר אוטומטית את הצגים שלך לרמת בהירות ספציפית בזמן הרצוי. כל הצגים יוגדרו לאותן רמות בהירות מתואמות.", "SETTINGS_TIME_ADD": "הוספת זמן", "SETTINGS_TIME_REMOVE": "הסרת זמן", "SETTINGS_TIME_INDIVIDUAL_TITLE": "הגדרת בהירות עבור צגים בודדים", "SETTINGS_TIME_INDIVIDUAL_DESC": "הגדר את הבהירות לכל צג במקום עבור כל הצגים בו זמנית.", "SETTINGS_TIME_TRANSITON_TITLE": "קצב שינוי הבהירות", "SETTINGS_TIME_TRANSITON_DESC": "באיזו מהירות צריכה הבהירות לעבור כאשר מופעלים התאמות שעת היום.", "SETTINGS_TIME_STARTUP_TITLE": "בדיקה בהפעלת התוכנה", "SETTINGS_TIME_STARTUP_DESC": "התאם את הבהירות לזמן הרלוונטי ביותר כאשר Twinkle Tray מופעל.", "SETTINGS_TIME_IDLE_TITLE": "זיהוי חוסר פעילות", "SETTINGS_TIME_IDLE_DESC": "כאשר לא זוהה קלט במשך פרק זמן מסוים, בהירות כל הצגים תופחת.", "SETTINGS_TIME_ANIMATE_TITLE": "אנימציה בין זמנים", "SETTINGS_TIME_ANIMATE_DESC": "ערכי בהירות יוצגו באנימציה בין האירוע הנוכחי לאירוע המתוזמן הבא. פעולה זו עשויה להגביר את ניצול המעבד. התאמות בהירות ידניות יימחקו במהירות בזמן שהפעולה פעילה.", "SETTINGS_TIME_SUN_TITLE": "קואורדינטות למיקום השמש", "SETTINGS_TIME_SUN_DESC": "כדי להשתמש ב\"מיקום השמש\" לצורך התאמות זמן, הזן את קווי הרוחב והאורך הנוכחיים שלך כדי שניתן יהיה לקבוע את הזמנים הנכונים.", "SETTINGS_TIME_LAT": "רוחב", "SETTINGS_TIME_LONG": "אורך", "SETTINGS_TIME_SUN_GET": "השג קורדינטות", "SETTINGS_TIME_IDLE_FS_TITLE": "אפליקציות במסך מלא חוסמות זיהוי", "SETTINGS_TIME_IDLE_FS_DESC": "אפליקציות במסך מלא ימנעו את הפחתת הבהירות. תקף רק כאשר החלון נמצא במיקוד.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "מדיה חוסמת זיהוי", "SETTINGS_TIME_IDLE_MEDIA_DESC": "זיהוי חוסר פעילות יושבת בזמן ניגון מדיה (וידאו או אודיו), כל עוד Windows מדווחת שהמדיה פעילה.", "SETTINGS_HOTKEYS_TITLE": "קיצורי מקשים", "SETTINGS_HOTKEYS_DESC": "הגדרת מקשי קיצור כדי להתאים את הבהירות בצג אחד או בכל הצגים.", "SETTINGS_HOTKEYS_ADD": "הוסף מקש קיצור", "SETTINGS_HOTKEYS_REMOVE": "הסר מקש קיצור", "SETTINGS_HOTKEYS_INCREASE": "הגברת הבהירות", "SETTINGS_HOTKEYS_DECREASE": "הפחתת הבהירות", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "לחץ על המקשים כאן", "SETTINGS_HOTKEYS_LEVEL_TITLE": "כוונון רמת הבהירות", "SETTINGS_HOTKEYS_LEVEL_DESC": "כמה יש לכוונן את הבהירות בעת שימוש במקשי קיצור.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "כמות גלילה", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "הפוך גלילה", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "בעת גלילה מעל סמל מגש המערכת, כיוון הגלילה יתהפך.", "SETTINGS_HOTKEYS_TOD_TITLE": "פעולת כיבוי צגים", "SETTINGS_HOTKEYS_TOD_DESC": "התאם אישית את האות הנשלח בעת שימוש במקש הקיצור או בסמל \"כיבוי צגים\". אות התוכנה יציג מסך שחור עד ש-Windows יזהה קלט (לדוגמה, עכבר או מקלדת). אות החומרה יכבה את החשמל לצגים.", "SETTINGS_HOTKEYS_TOD_NONE": "אין (הסתר סמל)", "SETTINGS_HOTKEYS_TOD_SOFT": "אות תוכנה (ברירת מחדל)", "SETTINGS_HOTKEYS_TOD_HARD": "אות חומרה* (DDC/CI בלבד)", "SETTINGS_HOTKEYS_TOD_BOTH": "אות חומרה* ותוכנה", "SETTINGS_HOTKEYS_TOD_NOTE": "*הערה: לא כל צגי DDC/CI תומכים בתכונה זו.", "SETTINGS_HOTKEYS_BREAK_TITLE": "מקשי קיצור מפרקים רמות מקושרות", "SETTINGS_HOTKEYS_BREAK_DESC": "בעת שימוש במקש קיצור עבור תצוגה בודדת בזמן ש\"רמות מקושרות\" פעילות, הוא יושבת.", "SETTINGS_HOTKEY_OFF_WARN": "פעולה זו תשתמש באפשרות שנבחרה תחת \"פעולת כיבוי צגים\". אם ברצונך לכבות צגים ספציפיים במקום זאת, השתמש בפעולת מקש הקיצור \"הגדר\" או \"מחזור\".", "SETTINGS_HOTKEY_TARGET": "יעד פעולה", "SETTINGS_HOTKEY_VALUE": "ערך", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "הכנס מספר", "SETTINGS_HOTKEY_VALUES": "ערכים", "SETTINGS_HOTKEY_ADD_VALUE": "הוספת ערך", "SETTINGS_HOTKEY_ACTION": "פעולה", "SETTINGS_HOTKEY_ACTION_SET": "קבע ערך", "SETTINGS_HOTKEY_ACTION_OFFSET": "שינוי ערך", "SETTINGS_HOTKEY_ACTION_CYCLE": "דפדוף רשימת ערכים", "SETTINGS_PROFILES_TITLE": "פרופילים", "SETTINGS_PROFILES_DESC": "כוונן אוטומטית את הבהירות או את התנהגות שכבת הקיצורים בהתאם לאפליקציה הממוקדת. ניתן גם להוסיף פרופילים לתפריט לחיצה ימנית במגש המערכת כדי לשנות במהירות את הבהירות לפרופילים מוגדרים מראש.", "SETTINGS_PROFILES_ADD": "פרופיל חדש", "SETTINGS_PROFILES_NAME": "שם פרופיל", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "קבע בהירות כשפעיל", "SETTINGS_PROFILES_SHOW_MENU": "הצגת תפרית לחצן יימני", "SETTINGS_PROFILES_TRIGGER_TITLE": "הגדרות טריגר לאפליקציה", "SETTINGS_PROFILES_APP_PATH": "נתיב האפליקציה", "SETTINGS_PROFILES_APP_DESC": "אם ברצונך שפרופיל זה יופעל אוטומטית כאשר אפליקציה ספציפית ממוקדת, הזן את הנתיב המלא או החלקי של קובץ ה-EXE למטה.", "SETTINGS_PROFILES_OVERLAY_TITLE": "סוג שכבת-על עקיפה", "SETTINGS_PROFILES_OVERLAY_DESC": "משנה את אופן הפעולה של שכבת המקשים החמים כאשר האפליקציה שצוינה נמצאת במוקד. תכונה זו אינה פועלת כאשר הפרופיל מופעל ידנית.", "SETTINGS_UPDATES_TITLE": "עדכונים", "SETTINGS_UPDATES_VERSION": "Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "בדיקת עדכונים אוטומטית", "SETTINGS_UPDATES_AUTOMATIC_DESC": "כאשר תהיה גרסה חדשה, היא תוצג בחלונית הבהירות.", "SETTINGS_UPDATES_MS_STORE": "כדי לבדוק אם יש גרסאות חדשות, בקר באפליקציית Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "גרסה חדשה של Twinkle Tray זמינה!", "SETTINGS_UPDATES_NONE_AVAILABLE": "מעודכן. הגרסה הנוכחית כוללת את השינויים הבאים:", "SETTINGS_UPDATES_DOWNLOADING": "מוריד עדכון…", "SETTINGS_UPDATES_DOWNLOAD": "הורד והתקן {{1}}", "SETTINGS_UPDATES_CHANNEL": "עדכון ערוץ", "SETTINGS_UPDATES_BRANCH_STABLE": "יציב (ברירת מחדל)", "SETTINGS_UPDATES_BRANCH_BETA": "גרסת ניסיון", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "בהירות SDR", "GENERIC_CALIBRATION_POINT": "נקודת כיול", "GENERIC_NOT_SUPPORTED": "לא נתמך", "GENERIC_SUPPORTED": "נתמך", "GENERIC_UNSUPPORTED": "לא זמין", "GENERIC_ACTIVE": "פעיל", "GENERIC_DETECTING_DISPLAYS": "מזהה מסכים…", "PANEL_LABEL_INPUTS": "קלט", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "סגנון ממשק המשתמש", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "השבתה במסך הנעילה", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "השבתת השינויים כשהמחשב נעול, כדי למנוע התנגשויות בין משתמשים שונים.", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "זיהוי עדכוני ערכת נושא", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "מזהה שינויים בצבעי המערכת, בטפט או בערכת הנושא של Windows כדי לעדכן את סמל המגש ואת אפקט ה-Mica. השבתת אפשרות זו עשויה לעזור אם אפליקציה צד-שלישי משנה את ערכת הנושא בתדירות גבוהה, דבר שגורם לניצול גבוה של המעבד (CPU).", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "זיהוי מצב צריכת חשמל של המסך", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "מזהה שינויים במצב החשמל של המסכים. ניטרול האפשרות עשוי לעזור אם מופיעות שגיאות בעת כיבוי והדלקה של המסכים או כשהם במצב המתנה (Idle). דורש הפעלה מחדש של האפליקציה כדי שהשינוי ייכנס לתוקף.", "SETTINGS_MONITORS_CALIBRATION_DESC": "ניתן להוסיף נקודות כיול נפרדות לכל צג כדי לפצות על הבדלים בעקומות הבהירות. \"ערך הקלט\" הוא רמת הבהירות שמופיעה במחוון, בעוד ש\"ערך הפלט\" הוא רמת הבהירות בפועל שמוחלת על הצג.", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "הגדרות צג HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "הפעלת מחווני בהירות SDR עבור צגים ספציפיים. כדי שזה יעבוד, יש לוודא ש-HDR מופעל בהגדרות Windows של אותם צגים.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "מחוון SDR מחליף את הראשי", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "שליטה בבהירות ה-SDR דרך מחוון הבהירות הראשי בזמן ש-HDR פעיל.", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "הצמד לרמת הבהירות", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "עצור לאחר רמת בהירות זו", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "אם הצג שלך משתמש בקוד VCP לא סטנדרטי עבור בהירות (כמו 0x13), או אם תרצה למפות מחדש את מחוון הבהירות לקוד אחר, תוכל להזין אותו כאן.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "השאר ריק עבור ברירת מחדל (0x10). מצא קודים נתמכים ברשימה למטה.", "SETTINGS_TIME_USE_SUN_POSITION": "השתמש במיקום השמש", "SETTINGS_HOTKEY_ADD_ACTION": "הוספת פעולה", "GENERIC_SLIDER_INDICATOR_TYPE": "סוג המחוון", "GENERIC_ICON": "סמל", "GENERIC_TEXT": "טקסט", "GENERIC_SLIDER_ICON": "סמל המחוון", "GENERIC_SLIDER_TEXT": "טקסט המחוון", "GENERIC_SLIDER_NAME": "הכנס שם עבור המחוון" } ================================================ FILE: src/localization/hi.json ================================================ { "LANGUAGE": "हिंदी", "GENERIC_OK": "ठीक है", "GENERIC_CANCEL": "रद्द करना", "GENERIC_SAVE": "सहेजें", "GENERIC_CLEAR": "स्पष्ट", "GENERIC_OFF": "बंद", "GENERIC_ON": "पर", "GENERIC_QUIT": "छोड़ना", "GENERIC_CLOSE": "बंद करे", "GENERIC_SETTINGS": "समायोजन", "GENERIC_INSTALL": "इंस्टॉल", "GENERIC_DISMISS": "खारिज", "GENERIC_DISPLAY_SINGLE": "प्रदर्शन", "GENERIC_ALL_DISPLAYS": "सभी प्रदर्शित करता है", "GENERIC_REFRESH_DISPLAYS": "रिफ्रेश डिस्प्ले", "GENERIC_MINIMUM": "मिनट", "GENERIC_MAXIMUM": "मैक्स", "GENERIC_NO_DISPLAYS": "कोई डिस्प्ले नहीं मिला। कृपया एक डिस्प्ले को अपने पीसी से कनेक्ट करें।", "GENERIC_NO_COMPATIBLE_DISPLAYS": "कोई संगत डिस्प्ले नहीं मिला। कृपया जांचें कि आपके डिस्प्ले के लिए \"डीडीसी/सीआई\" सक्षम है।", "GENERIC_NO_DISPLAYS_SHORT": "कोई संगत डिस्प्ले नहीं मिला।", "PANEL_TITLE": "चमक समायोजित करें", "PANEL_UPDATE_AVAILABLE": "नया संस्करण उपलब्ध है", "PANEL_BUTTON_LINK_LEVELS": "लिंक स्तर", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "डिस्प्ले बंद करें", "PANEL_LABEL_BRIGHTNESS": "चमक", "PANEL_LABEL_CONTRAST": "कंट्रास्ट", "PANEL_LABEL_OFF_ON": "पावर स्टेट", "PANEL_LABEL_COLOR_TEMPERATURE": "रंग तापमान", "PANEL_LABEL_VOLUME": "आयतन", "INTRO_TITLE": "हैलो, ट्विंकल ट्रे!", "INTRO_INSTRUCTIONS": "ट्विंकल ट्रे के लिए ट्रे आइकन शायद छिपा हुआ है, इसलिए आपको इसे किसी ऐसे स्थान पर ले जाना चाहिए जहां आप इसे आसानी से एक्सेस कर सकें। निर्देशों के लिए नीचे देखें।", "SETTINGS_TITLE": "ट्विंकल ट्रे सेटिंग्स", "SETTINGS_SIDEBAR_GENERAL": "आम", "SETTINGS_SIDEBAR_MONITORS": "मॉनिटर सेटिंग्स", "SETTINGS_SIDEBAR_FEATURES": "डीडीसी/सीआई विशेषताएं", "SETTINGS_SIDEBAR_TIME": "समय समायोजन", "SETTINGS_SIDEBAR_HOTKEYS": "हॉटकी और शॉर्टकट", "SETTINGS_SIDEBAR_UPDATES": "अपडेट", "SETTINGS_GENERAL_TITLE": "आम", "SETTINGS_GENERAL_STARTUP": "स्टार्टअप पर लॉन्च करें", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "स्टार्टअप पर चमक लागू करें", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "ट्विंकल ट्रे शुरू होने पर प्रत्येक डिस्प्ले के लिए अंतिम ज्ञात चमक को पुनर्स्थापित करें।", "SETTINGS_GENERAL_THEME_TITLE": "विषय", "SETTINGS_GENERAL_THEME_SYSTEM": "सिस्टम प्राथमिकताएं (डिफ़ॉल्ट)", "SETTINGS_GENERAL_THEME_DARK": "अंधेरा", "SETTINGS_GENERAL_THEME_LIGHT": "रोशनी", "SETTINGS_GENERAL_LANGUAGE_TITLE": "भाषा: हिन्दी", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "सिस्टम भाषा (डिफ़ॉल्ट)", "SETTINGS_GENERAL_RESET_TITLE": "सेटिंग्स को दुबारा करें", "SETTINGS_GENERAL_RESET_DESC": "अपना कॉन्फिग क्लियर करने के लिए इस बटन को हिट करें।", "SETTINGS_GENERAL_RESET_BUTTON": "सेटिंग्स को दुबारा करें", "SETTINGS_GENERAL_ACRYLIC_TITLE": "एक्रिलिक धुंधला", "SETTINGS_GENERAL_ACRYLIC_DESC": "ट्विंकल ट्रे में पारदर्शी पृष्ठभूमि के पीछे धुंधलापन सक्षम या अक्षम करें।", "SETTINGS_GENERAL_ANALYTICS_TITLE": "एनालिटिक्स", "SETTINGS_GENERAL_ANALYTICS_DESC": "ट्विंकल ट्रे को बेहतर बनाने में सहायता के लिए उपयोग डेटा भेजें। कोई व्यक्तिगत जानकारी नहीं भेजी जाती है। {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "और अधिक जानें", "SETTINGS_GENERAL_SCROLL_TITLE": "ट्रे आइकन स्क्रॉल शॉर्टकट", "SETTINGS_GENERAL_SCROLL_DESC": "सिस्टम ट्रे आइकन पर स्क्रॉल करके एक ही बार में सभी डिस्प्ले की चमक को समायोजित करें। यह कुछ ट्रैकपैड के साथ काम नहीं करता है।", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "ट्रे चिह्न", "SETTINGS_MONITORS_RATE_TITLE": "चमक अद्यतन दर", "SETTINGS_MONITORS_RATE_DESC": "जब आप उनके मान समायोजित कर रहे हों, तो आपके डिस्प्ले पर कितनी बार चमक अपडेट की जाएगी। यदि आपके डिस्प्ले टिमटिमा रहे हैं तो समय बढ़ाएँ।", "SETTINGS_MONITORS_RATE_0": "ऊटपटांग", "SETTINGS_MONITORS_RATE_1": "तेज (250 एमएस)", "SETTINGS_MONITORS_RATE_2": "सामान्य (500 एमएस)", "SETTINGS_MONITORS_RATE_3": "धीमा (1 सेकंड)", "SETTINGS_MONITORS_RATE_4": "बहुत धीमी (2 सेकंड)", "SETTINGS_MONITORS_RENAME_TITLE": "मॉनिटर्स का नाम बदलें", "SETTINGS_MONITORS_RENAME_DESC": "यदि आप प्रत्येक मॉनिटर के लिए एक अलग नाम पसंद करते हैं (उदाहरण के लिए \"लेफ्ट मॉनिटर\", \"मिडिल मॉनिटर\"), तो आप इसे नीचे दर्ज कर सकते हैं। फ़ील्ड को खाली छोड़ने से मूल नाम पुनर्स्थापित हो जाएगा।", "SETTINGS_MONITORS_ENTER_NAME": "नाम दर्ज", "SETTINGS_MONITORS_REORDER_TITLE": "मॉनिटर्स को फिर से व्यवस्थित करें", "SETTINGS_MONITORS_REORDER_DESC": "मॉनिटर के ट्रे में प्रदर्शित होने का क्रम बदलें। परिवर्तन करने के लिए क्लिक करें और खींचें।", "SETTINGS_MONITORS_NORMALIZE_TITLE": "चमक को सामान्य करें", "SETTINGS_MONITORS_NORMALIZE_DESC": "मॉनिटर्स में अक्सर अलग-अलग ब्राइटनेस रेंज होते हैं। प्रति डिस्प्ले न्यूनतम/अधिकतम चमक को सीमित करके, डिस्प्ले के बीच चमक का स्तर बहुत अधिक सुसंगत है। समान मॉनिटर समान सेटिंग्स का उपयोग करेंगे।", "SETTINGS_MONITORS_DETAILS_NAME": "नाम", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "आंतरिक नाम", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "संचार विधि", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "वर्तमान चमक", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "अधिकतम चमक", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "चमक सामान्यीकरण", "SETTINGS_FEATURES_DESCRIPTION": "ब्राइटनेस पैनल में विशिष्ट DDC/CI सुविधाओं को सक्षम या अक्षम करें। आपके मॉनिटर को ब्राइटनेस पैनल में दिखाने के लिए कम से कम एक फीचर सक्षम होना चाहिए। सभी डिस्प्ले इन सुविधाओं का समर्थन नहीं करते हैं, जैसे लैपटॉप/टैबलेट डिस्प्ले।", "SETTINGS_TIME_TITLE": "दिन का समय समायोजन", "SETTINGS_TIME_DESC": "अपने मॉनिटर को वांछित समय पर एक विशिष्ट चमक स्तर पर स्वचालित रूप से सेट करें। सभी मॉनिटर समान, सामान्यीकृत स्तरों पर सेट किए जाएंगे।", "SETTINGS_TIME_ADD": "एक समय जोड़ें", "SETTINGS_TIME_REMOVE": "समय निकालें", "SETTINGS_TIME_INDIVIDUAL_TITLE": "अलग-अलग डिस्प्ले के लिए ब्राइटनेस सेट करें", "SETTINGS_TIME_INDIVIDUAL_DESC": "एक बार में सभी डिस्प्ले के बजाय प्रति डिस्प्ले ब्राइटनेस कॉन्फ़िगर करें।", "SETTINGS_TIME_STARTUP_TITLE": "ऐप स्टार्टअप पर चेक करें", "SETTINGS_TIME_STARTUP_DESC": "ट्विंकल ट्रे शुरू होने पर सबसे प्रासंगिक समय से मेल खाने के लिए चमक को समायोजित करें।", "SETTINGS_HOTKEYS_TITLE": "हॉटकी", "SETTINGS_HOTKEYS_DESC": "एक या सभी डिस्प्ले की चमक को समायोजित करने के लिए हॉटकी को कॉन्फ़िगर करें।", "SETTINGS_HOTKEYS_ADD": "हॉटकी जोड़ें", "SETTINGS_HOTKEYS_REMOVE": "हॉटकी निकालें", "SETTINGS_HOTKEYS_INCREASE": "चमक बढ़ाएँ", "SETTINGS_HOTKEYS_DECREASE": "चमक कम करें", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "यहां कुंजियां दबाएं", "SETTINGS_HOTKEYS_LEVEL_TITLE": "चमक स्तर समायोजन", "SETTINGS_HOTKEYS_LEVEL_DESC": "हॉटकी का उपयोग करते समय कितनी चमक को समायोजित किया जाना चाहिए।", "SETTINGS_HOTKEYS_TOD_TITLE": "प्रदर्शन कार्रवाई बंद करें", "SETTINGS_HOTKEYS_TOD_DESC": "टर्न ऑफ डिस्प्ले हॉटकी या आइकन का उपयोग करते समय भेजे गए सिग्नल को अनुकूलित करें। सॉफ़्टवेयर सिग्नल एक काली स्क्रीन प्रदर्शित करेगा जब तक कि विंडोज़ द्वारा इनपुट (उदा. माउस या कीबोर्ड) का पता नहीं लगाया जाता। हार्डवेयर सिग्नल मॉनिटर को बिजली बंद कर देगा।", "SETTINGS_HOTKEYS_TOD_NONE": "कोई नहीं (आइकन छुपाएं)", "SETTINGS_HOTKEYS_TOD_SOFT": "सॉफ्टवेयर सिग्नल (डिफ़ॉल्ट)", "SETTINGS_HOTKEYS_TOD_HARD": "हार्डवेयर* सिग्नल (केवल DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "हार्डवेयर* और सॉफ्टवेयर सिग्नल", "SETTINGS_HOTKEYS_TOD_NOTE": "*नोट: सभी DDC/CI मॉनीटर इस सुविधा का समर्थन नहीं करते हैं।", "SETTINGS_HOTKEYS_BREAK_TITLE": "हॉटकी लिंक किए गए स्तरों को तोड़ती हैं", "SETTINGS_HOTKEYS_BREAK_DESC": "जब एकल डिस्प्ले के लिए हॉटकी का उपयोग किया जाता है और \"लिंक किए गए स्तर\" सक्रिय होते हैं, तो इसे निष्क्रिय कर दिया जाएगा।", "SETTINGS_UPDATES_TITLE": "अपडेट", "SETTINGS_UPDATES_VERSION": "आपके पास ट्विंकल ट्रे {{1}} है।", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "नए संस्करणों के लिए स्वचालित रूप से जांचें", "SETTINGS_UPDATES_AUTOMATIC_DESC": "जब कोई नया वर्जन आएगा तो उसे ब्राइटनेस पैनल में दिखाया जाएगा।", "SETTINGS_UPDATES_MS_STORE": "नए संस्करणों की जाँच करने के लिए, Microsoft Store ऐप पर जाएँ।", "SETTINGS_UPDATES_AVAILABLE": "ट्विंकल ट्रे का नया संस्करण उपलब्ध है!", "SETTINGS_UPDATES_NONE_AVAILABLE": "आधुनिक। वर्तमान संस्करण में निम्नलिखित परिवर्तन शामिल हैं:", "SETTINGS_UPDATES_DOWNLOADING": "अद्यतन स्थिति डाउनलोड हो रही है…", "SETTINGS_UPDATES_DOWNLOAD": "डाउनलोड और इंस्टॉल करें {{1}}", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "यदि ट्रे आइकन पर क्लिक करने या आपके डिस्प्ले का पता नहीं लगाने पर ट्विंकल ट्रे अनुत्तरदायी है, तो आप कुछ मॉनिटर डिटेक्शन विधियों को अक्षम करने का प्रयास कर सकते हैं। परिवर्तनों को प्रभावी करने के लिए ट्विंकल ट्रे को पुनरारंभ करें। {{1}}", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "निष्क्रिय आंतरिक प्रदर्शन छुपाएं", "PANEL_LABEL_TURN_OFF": "बिजली बंद", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "जब ढक्कन बंद हो या विंडोज़ में आंतरिक डिस्प्ले अक्षम हो, तो पैनल में चमक स्लाइडर छुपाएं।", "SETTINGS_TIME_IDLE_DESC": "जब कुछ समय के लिए कोई इनपुट नहीं मिला है, तो सभी डिस्प्ले की चमक कम हो जाएगी।", "GENERIC_SECONDS": "सेकंड", "GENERIC_MINUTES": "मिनट", "SETTINGS_GENERAL_MICA_TITLE": "मीका ब्लर", "SETTINGS_FEATURES_UNSUPPORTED": "यह मॉनिटर DDC/CI सुविधाओं का समर्थन नहीं करता है।", "SETTINGS_GENERAL_MICA_DESC": "ट्विंकल ट्रे में बैकग्राउंड के पीछे ब्लर को सक्षम या अक्षम करें।", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "वर्तमान चमक प्राप्त करें", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "ब्राइटनेस पेज खोलते समय हमेशा मॉनिटर से नवीनतम ब्राइटनेस लेवल प्राप्त करें। अगर ट्विंकल ट्रे के बाहर से ब्राइटनेस बार-बार बदलती है, तो इसे सक्षम करें (उदा। कोई अन्य एप्लिकेशन)।", "SETTINGS_TIME_IDLE_TITLE": "निष्क्रिय पहचान", "GENERIC_PAUSE_TOD": "समय समायोजन रोकें", "GENERIC_PAUSE_IDLE": "आइडल डिटेक्शन रोकें", "SETTINGS_GENERAL_TROUBLESHOOTING": "समस्या निवारण", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "मॉनिटर का पता लगाने के तरीकों को अक्षम करें", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "ओवरले अक्षम करें", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "यदि ट्विंकल ट्रे का हॉटकी ओवरले फुलस्क्रीन एप्लिकेशन में हस्तक्षेप कर रहा है, तो आप इसे यहां अक्षम कर सकते हैं।", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "प्रदर्शित छुपाएं", "SETTINGS_TIME_TRANSITON_TITLE": "चमक संक्रमण गति", "SETTINGS_TIME_TRANSITON_DESC": "दिन के समय के समायोजन सक्रिय होने पर चमक कितनी जल्दी बदलनी चाहिए।", "SETTINGS_TIME_ANIMATE_TITLE": "समय के बीच एनिमेट करें", "SETTINGS_TIME_ANIMATE_DESC": "चमक मान वर्तमान और अगले शेड्यूल किए गए ईवेंट के बीच एनिमेट किया जाएगा। CPU उपयोग बढ़ा सकता है। इसके सक्रिय रहने के दौरान मैन्युअल ब्राइटनेस एडजस्टमेंट जल्दी से ओवरराइट हो जाएंगे।", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "यदि आप फ़्लाईआउट से विशिष्ट प्रदर्शन छिपाना चाहते हैं, तो आप उन्हें यहाँ से टॉगल कर सकते हैं।", "GENERIC_SPEED_INSTANT": "तुरंत", "GENERIC_SPEED_SLOW": "धीमा", "GENERIC_SPEED_VERY_SLOW": "बहुत धीमी गति से", "GENERIC_SPEED_NORMAL": "सामान्य", "GENERIC_SPEED_FAST": "तेज़", "GENERIC_SPEED_VERY_FAST": "बहुत तेज़", "GENERIC_DDC_WARNING": "DDC/CI सुविधाएँ जैसे पावर स्थिति को नियंत्रित करना आपके मॉनिटर को अनुत्तरदायी बना सकता है। अपने जोखिम पार इस्तेमाल करें।", "SETTINGS_UPDATES_BRANCH_STABLE": "स्थिर (डिफ़ॉल्ट)", "SETTINGS_UPDATES_CHANNEL": "अपडेट चैनल", "SETTINGS_UPDATES_BRANCH_BETA": "बीटा" } ================================================ FILE: src/localization/hr.json ================================================ { "LANGUAGE": "Hrvatski", "GENERIC_OK": "U redu", "GENERIC_CANCEL": "Odustani", "GENERIC_SAVE": "Spremi", "GENERIC_CLEAR": "Izbriši", "GENERIC_OFF": "Isključeno", "GENERIC_ON": "Uključeno", "GENERIC_QUIT": "Zatvori program", "GENERIC_CLOSE": "Zatvori", "GENERIC_SETTINGS": "Postavke", "GENERIC_INSTALL": "Instaliraj", "GENERIC_DISMISS": "Zanemari", "GENERIC_DISPLAY_SINGLE": "Ekran", "GENERIC_ALL_DISPLAYS": "Svi ekrani", "GENERIC_MINIMUM": "Min.", "GENERIC_MAXIMUM": "Maks.", "GENERIC_NO_DISPLAYS": "Nije otkriven nijedan ekran. Poveži jedan ekran s računalom.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Nije otkriven nijedan kompatibilan ekran. Provjeri, je li „DDC/CI” aktivirano za tvoje ekrane.", "GENERIC_NO_DISPLAYS_SHORT": "Nije otkriven nijedan kompatibilan ekran.", "PANEL_TITLE": "Podesi svjetlinu", "PANEL_UPDATE_AVAILABLE": "Dostupna je nova verzija", "PANEL_BUTTON_LINK_LEVELS": "Razine veza", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Isključi ekrane", "INTRO_TITLE": "Bok, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Twinkle Tray ikona u programskoj traci je vjerojatno skrivena. Premjesti je na neko mjesto gdje joj lako možeš pristupiti. Pogledaj upute niže dolje.", "SETTINGS_TITLE": "Twinkle Tray postavke", "SETTINGS_SIDEBAR_GENERAL": "Opće", "SETTINGS_SIDEBAR_MONITORS": "Postavke monitora", "SETTINGS_SIDEBAR_TIME": "Podešavanja vremena", "SETTINGS_SIDEBAR_HOTKEYS": "Tipkovni prečaci", "SETTINGS_SIDEBAR_UPDATES": "Aktualiziranja", "SETTINGS_GENERAL_TITLE": "Opće", "SETTINGS_GENERAL_STARTUP": "Pokreni pri pokretanju", "SETTINGS_GENERAL_THEME_TITLE": "Tema", "SETTINGS_GENERAL_THEME_SYSTEM": "Postavke sustava (standardno)", "SETTINGS_GENERAL_THEME_DARK": "Tamna", "SETTINGS_GENERAL_THEME_LIGHT": "Svijetla", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Jezik", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Jezik sustava (standardno)", "SETTINGS_GENERAL_RESET_TITLE": "Resetiraj postavke", "SETTINGS_GENERAL_RESET_DESC": "Pritisni ovaj gumb brisanje konfiguracije.", "SETTINGS_GENERAL_RESET_BUTTON": "Resetiraj postavke", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analize", "SETTINGS_GENERAL_ANALYTICS_DESC": "Šalji podatke o upotrebi, kako bi se Twinkle Tray poboljšao. Ne šalju se osobni podaci. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Saznaj više", "SETTINGS_GENERAL_SCROLL_TITLE": "Prečac za klizanje na ikonu u programskoj traci", "SETTINGS_GENERAL_SCROLL_DESC": "Prilagodi svjetlinu svih ekrana istovremeno, klizanjem preko ikone u programskoj traci. Ne radi s nekim dodirnim pločama.", "SETTINGS_MONITORS_RATE_TITLE": "Brzina aktualiziranja svjetline", "SETTINGS_MONITORS_RATE_DESC": "Učestalost aktualiziranja svjetline ekrana dok podešavaš njihove vrijednosti. Povećaj vrijeme, ako ekrani trepere.", "SETTINGS_MONITORS_RATE_0": "Ludo", "SETTINGS_MONITORS_RATE_1": "Brzo (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normalno (500 ms)", "SETTINGS_MONITORS_RATE_3": "Sporo (1 sekunda)", "SETTINGS_MONITORS_RATE_4": "Jako sporo (2 sekunde)", "SETTINGS_MONITORS_RENAME_TITLE": "Preimenuj monitor", "SETTINGS_MONITORS_RENAME_DESC": "Ako želiš drugačije ime za svaki monitor (npr. „Lijevi monitor”, „Srednji monitor”), upiši ga dolje. Ako polje ostane prazno, vratit će se izvorno ime.", "SETTINGS_MONITORS_ENTER_NAME": "Upiši ime", "SETTINGS_MONITORS_REORDER_TITLE": "Prerasporedi monitore", "SETTINGS_MONITORS_REORDER_DESC": "Promijeni redoslijed prikaza monitora u programskoj traci. Za mijenjanje, pritisni i povuci ih.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normaliziraj svjetlinu", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitori često imaju različite raspone svjetline. Ograničavanjem min./maks. svjetline po ekranu, razina svjetline između ekrana znatno je dosljednija. Slični monitori koristit će iste postavke.", "SETTINGS_TIME_TITLE": "Podešavanja doba dana", "SETTINGS_TIME_DESC": "Automatski postavi određenu razinu svjetline na svojim monitorima u željeno vrijeme. Svi će se monitori postaviti na iste, normalizirane razine.", "SETTINGS_TIME_ADD": "Dodaj vrijeme", "SETTINGS_TIME_REMOVE": "Ukloni vrijeme", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Postavi svjetlinu za pojedinačne ekrane", "SETTINGS_TIME_INDIVIDUAL_DESC": "Postavi svjetlinu ekrana pojedinačno, umjesto za sve ekrane najednom.", "SETTINGS_TIME_STARTUP_TITLE": "Provjeri prilikom pokretanja programa", "SETTINGS_TIME_STARTUP_DESC": "Prilagodi svjetlinu da odgovara najrelevantnijem vremenu kad se Twinkle Tray pokrene.", "SETTINGS_HOTKEYS_TITLE": "Tipkovnički prečaci", "SETTINGS_HOTKEYS_DESC": "Konfiguriraj tipkovničke prečace za podešavanje svjetline jednog ili svih ekrana.", "SETTINGS_HOTKEYS_ADD": "Dodaj tipkovnički prečac", "SETTINGS_HOTKEYS_REMOVE": "Ukloni tipkovnički prečac", "SETTINGS_HOTKEYS_INCREASE": "Posvijetli", "SETTINGS_HOTKEYS_DECREASE": "Potamni", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Ovdje pritisni tipke", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Podešavanje razine svjetline", "SETTINGS_HOTKEYS_LEVEL_DESC": "Količina podešavanja svjetline kad se koriste tipkovnički prečaci.", "SETTINGS_UPDATES_TITLE": "Aktualiziranja", "SETTINGS_UPDATES_VERSION": "Imaš Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automatski traži nove verzije", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Kad postoji nova verzija, prikazat će se na ploči svjetline.", "SETTINGS_UPDATES_MS_STORE": "Potraži nove verzije u Microsoft Store programu.", "SETTINGS_UPDATES_AVAILABLE": "Postoji nova verzija za Twinkle Tray!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Aktualan. Trenutačna verzija uključuje sljedeće promjene:", "SETTINGS_UPDATES_DOWNLOADING": "Preuzimanje nadogradnje …", "SETTINGS_UPDATES_DOWNLOAD": "Preuzmi i instaliraj {{1}}", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Ikone u programskoj traci", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akrilno zamućenje", "SETTINGS_GENERAL_ACRYLIC_DESC": "Aktiviraj ili deaktiviraj zamućenost iza prozirne pozadine u Twinkle Tray.", "SETTINGS_MONITORS_FEATURES_DESCRIPTION": "Aktiviraj ili deaktiviraj određene DDC/CI funkcije na ploči svjetline. Da bi se monitor prikazao na ploči svjetline, mora biti uključena barem jedna funkcija. Ove funkcije ne podržavaju svi ekrani, kao što su ekrani prijenosnih računala/tableta.", "PANEL_LABEL_BRIGHTNESS": "Svjetlina", "PANEL_LABEL_OFF_ON": "Stanje napajanja", "SETTINGS_MONITORS_FEATURES_TITLE": "DDC/CI funkcije", "PANEL_LABEL_COLOR_TEMPERATURE": "Temperatura boje", "PANEL_LABEL_CONTRAST": "Kontrast", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalizacija svjetline", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maksimalna svjetlina", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Trenutačna svjetlina", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Način komunikacije", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Interno ime", "SETTINGS_MONITORS_DETAILS_NAME": "Ime", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Obnovi zadnju svjetlinu za svaki ekran prilikom pokretanja Twinkle Traya.", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Primijeni svjetlinu pri pokretanju", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI funkcije", "GENERIC_REFRESH_DISPLAYS": "Aktualiziraj ekrane", "SETTINGS_FEATURES_DESCRIPTION": "Aktiviraj ili deaktiviraj određene DDC/CI funkcije na ploči svjetline. Barem jedna funkcija mora biti aktivirana, da bi se tvoj monitor prikazao na ploči svjetline. Ove funkcije ne podržavaju svi ekrani, kao što su ekrani prijenosnih računala/tableta.", "PANEL_LABEL_VOLUME": "Glasnoća", "SETTINGS_HOTKEYS_BREAK_DESC": "Kad se koristi prečac za jedan ekran i kad je „povezane razine” aktivirano, deaktivirat će se.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Prečaci prekidaju povezane razine", "SETTINGS_HOTKEYS_TOD_NOTE": "* Napomena: Neki DDC/CI monitori ne podržavaju ovu funkciju.", "SETTINGS_HOTKEYS_TOD_BOTH": "Hardverski* i softverski signal", "SETTINGS_HOTKEYS_TOD_HARD": "Hardverski* signal (samo DDC/CI)", "SETTINGS_HOTKEYS_TOD_SOFT": "Softverski signal (standardno)", "SETTINGS_HOTKEYS_TOD_NONE": "Ništa (sakrij ikonu)", "SETTINGS_HOTKEYS_TOD_DESC": "Prilagodi signal koji se šalje prilikom upotrebe prečaca ili ikone za isključivanje ekrana. Softverski signal će prikazati crni ekran sve dok Windows ne otkrije unos (npr. mišem ili tipkovnicom). Hardverski signal će isključiti monitore.", "SETTINGS_HOTKEYS_TOD_TITLE": "Radnja isključivanja ekrana", "SETTINGS_FEATURES_UNSUPPORTED": "Ovaj monitor ne podržava DDC/CI funkcije.", "GENERIC_MINUTES": "minute", "GENERIC_SECONDS": "sekunde", "PANEL_LABEL_TURN_OFF": "Isključi", "SETTINGS_GENERAL_MICA_TITLE": "Mica zamućenje", "SETTINGS_GENERAL_MICA_DESC": "Aktiviraj ili deaktiviraj zamućenost iza pozadina u Twinkle Tray.", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Sakrij neaktivan interni prikaz", "SETTINGS_TIME_IDLE_TITLE": "Otkrivanje nekativnosti", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Preuzmi trenutačnu svjetlinu", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Kad je poklopac zatvoren ili kad je interni ekran deaktiviran u sustavu Windows, sakrij upravljač svjetline u ploči.", "SETTINGS_TIME_IDLE_DESC": "Kad u određenom vremenskom razdoblju nema unosa, smanjit će se svjetlina svih ekrana.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Prilikom otvaranja stranice svjetline uvijek preuzmi najnoviju razinu svjetline monitora. Aktiviraj ovu opciju ako se svjetlina često mijenja izvan programa Twinkle Tray (npr. od jednog drugog programa).", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Ako Twinkle Tray ne reagira na klik na ikonu trake ili ne otkriva vaše zaslone, možete pokušati onemogućiti određene metode detekcije monitora. Ponovno pokrenite Twinkle tray kako bi promjene stupile na snagu. {{1}}", "GENERIC_PAUSE_TOD": "Prilagodbe vremena pauze", "GENERIC_PAUSE_IDLE": "Pauziraj detekciju mirovanja", "SETTINGS_GENERAL_TROUBLESHOOTING": "Rješavanje problema", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Sakrij zaslone", "SETTINGS_TIME_TRANSITON_TITLE": "Brzina prijelaza svjetline", "SETTINGS_TIME_TRANSITON_DESC": "Koliko brzo bi svjetlina trebala prijeći kada se aktiviraju prilagodbe doba dana.", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Ako želite sakriti određene prikaze iz flyouta, možete ih isključiti ovdje.", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Onemogući metode otkrivanja monitora", "SETTINGS_TIME_ANIMATE_DESC": "Vrijednosti svjetline bit će animirane između trenutnog i sljedećeg planiranog događaja. Može povećati upotrebu CPU-a. Ručna podešavanja svjetline brzo će se prebrisati dok je ovo aktivno.", "GENERIC_SPEED_INSTANT": "Trenutak", "GENERIC_SPEED_SLOW": "Usporiti", "GENERIC_SPEED_VERY_SLOW": "Vrlo sporo", "GENERIC_SPEED_NORMAL": "Normalan", "GENERIC_SPEED_FAST": "Brzo", "GENERIC_SPEED_VERY_FAST": "Vrlo brzo", "GENERIC_DDC_WARNING": "DDC/CI značajke kao što je kontrola stanja napajanja mogu uzrokovati da vaš monitor ne reagira. Koristite na vlastitu odgovornost.", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Onemogući preklapanje", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabilno (zadano)", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Ako preklapanje tipki prečaca Twinkle Tray-a ometa aplikacije preko cijelog zaslona, možete ga onemogućiti ovdje.", "SETTINGS_TIME_ANIMATE_TITLE": "Animirajte između vremena", "SETTINGS_UPDATES_CHANNEL": "Ažurirajte kanal", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Isključi", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Svjetlina" } ================================================ FILE: src/localization/hu.json ================================================ { "LANGUAGE": "magyar", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Mégse", "GENERIC_SAVE": "Mentés", "GENERIC_CLEAR": "Törlés", "GENERIC_OFF": "Ki", "GENERIC_ON": "Be", "GENERIC_QUIT": "Kilépés", "GENERIC_CLOSE": "Bezárás", "GENERIC_SETTINGS": "Beállítások", "GENERIC_INSTALL": "Telepítés", "GENERIC_DISMISS": "Elvetés", "GENERIC_DISPLAY_SINGLE": "Kijelző", "GENERIC_ALL_DISPLAYS": "Minden kijelző", "GENERIC_REFRESH_DISPLAYS": "Kijelzők frissítése", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Max", "GENERIC_NO_DISPLAYS": "Nem észlelhető kijelző. Kérjük, csatlakoztasson egy kijelzőt a számítógéphez.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Nem találhatók kompatibilis kijelzők. Kérjük, ellenőrizze, hogy a \"DDC/CI\" engedélyezve van a kijelzőkön.", "GENERIC_NO_DISPLAYS_SHORT": "Nem észleltünk kompatibilis kijelzőt.", "PANEL_TITLE": "Fényerő beállítása", "PANEL_UPDATE_AVAILABLE": "Új verzió érhető el", "PANEL_BUTTON_LINK_LEVELS": "Szintek összekapcsolása", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Kijelzők kikapcsolása", "PANEL_LABEL_BRIGHTNESS": "Fényerő", "PANEL_LABEL_CONTRAST": "Kontraszt", "PANEL_LABEL_OFF_ON": "Energiaállapot", "PANEL_LABEL_COLOR_TEMPERATURE": "Színhőmérséklet", "PANEL_LABEL_VOLUME": "Hangerő", "INTRO_TITLE": "Helló, Twinkle Tray!", "INTRO_INSTRUCTIONS": "A Twinkle Tray tálcaikonja valószínűleg el van rejtve, ezért érdemes áthelyezni egy olyan helyre, ahol könnyen hozzáférhet. Utasítások lentebb.", "SETTINGS_TITLE": "Twinkle Tray beállítások", "SETTINGS_SIDEBAR_GENERAL": "Általános", "SETTINGS_SIDEBAR_MONITORS": "Képernyő beállítások", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI jellemzők", "SETTINGS_SIDEBAR_TIME": "Időbeállítások", "SETTINGS_SIDEBAR_HOTKEYS": "Gyorsgombok és parancsikonok", "SETTINGS_SIDEBAR_UPDATES": "Frissítések", "SETTINGS_GENERAL_TITLE": "Általános", "SETTINGS_GENERAL_STARTUP": "Futtatás rendszerindításkor", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Fényerő alkalmazása indításkor", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "A Twinkle Tray indításakor visszaállítja az utolsó ismert fényerőt az egyes kijelzők számára.", "SETTINGS_GENERAL_THEME_TITLE": "Téma", "SETTINGS_GENERAL_THEME_SYSTEM": "Rendszerbeállítások (alapértelmezett)", "SETTINGS_GENERAL_THEME_DARK": "Sötét", "SETTINGS_GENERAL_THEME_LIGHT": "Világos", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Nyelv", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Rendszer nyelve (alapértelmezett)", "SETTINGS_GENERAL_RESET_TITLE": "Beállítások alaphelyzetbe állítása", "SETTINGS_GENERAL_RESET_DESC": "A konfiguráció törléséhez nyomja meg ezt a gombot.", "SETTINGS_GENERAL_RESET_BUTTON": "Beállítások alaphelyzetbe állítása", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akril elmosódás", "SETTINGS_GENERAL_ACRYLIC_DESC": "Engedélyezze vagy tiltsa le a hátterek mögötti elmosódást a Twinkle Tray alkalmazásban.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Adatelemzés", "SETTINGS_GENERAL_ANALYTICS_DESC": "Küldjön használati adatokat a Twinkle Tray fejlesztéséhez. Személyes adatok nem kerülnek elküldésre. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Tudjon meg többet", "SETTINGS_GENERAL_SCROLL_TITLE": "Tálca ikon görgetés parancsikon", "SETTINGS_GENERAL_SCROLL_DESC": "Az összes kijelző fényerejét egyszerre állíthatja be a rendszer-tálca ikonja fölött görgetve. Ez nem működik egyes trackpadekkel.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Tálcaikon", "SETTINGS_MONITORS_RATE_TITLE": "Fényerő frissítési sebesség", "SETTINGS_MONITORS_RATE_DESC": "Milyen gyakran frissül a fényerő a kijelzőkön miközben beállítja az értékeiket. Növelje az időt, ha a kijelzői villognak.", "SETTINGS_MONITORS_RATE_0": "Agyament", "SETTINGS_MONITORS_RATE_1": "Gyors (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normál (500 ms)", "SETTINGS_MONITORS_RATE_3": "Lassú (1 másodperc)", "SETTINGS_MONITORS_RATE_4": "Nagyon lassú (2 másodperc)", "SETTINGS_MONITORS_RENAME_TITLE": "Monitorok átnevezése", "SETTINGS_MONITORS_RENAME_DESC": "Ha az egyes monitoroknak más nevet szeretne adni (pl. \"Bal monitor\", \"Középső monitor\"), akkor azt alább megadhatja. Ha üresen hagyja a mezőt, akkor visszaáll az eredeti név.", "SETTINGS_MONITORS_ENTER_NAME": "Név megadása", "SETTINGS_MONITORS_REORDER_TITLE": "Monitorok átrendezése", "SETTINGS_MONITORS_REORDER_DESC": "A monitorok megjelenítési sorrendjének módosítása a tálcán. Húzza a módosítások elvégzéséhez.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Fényerők egységesítése", "SETTINGS_MONITORS_NORMALIZE_DESC": "A monitorok gyakran különböző fényerősségtartományokkal rendelkeznek. A kijelzőnkénti min/max fényerő korlátozásával a kijelzők közötti fényerőszintek sokkal egységesebbek lesznek.", "SETTINGS_MONITORS_DETAILS_NAME": "Név", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Belső név", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Kommunikációs módszer", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Jelenlegi fényerő", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maximális fényerő", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Fényerő egységesítés", "SETTINGS_FEATURES_DESCRIPTION": "Egyes DDC/CI funkciók engedélyezése vagy letiltása a fényerőpanelen. Legalább egy funkciónak engedélyezve kell lennie ahhoz, hogy a monitor megjelenjen a fényerőpanelen. Nem minden kijelző támogatja ezeket a funkciókat, mint például a laptopok/tabletek kijelzői.", "SETTINGS_TIME_TITLE": "Napszak beállítások", "SETTINGS_TIME_DESC": "Automatikusan állítsa be a monitorokat egy adott fényerőszintre a kívánt időpontban. Minden monitor azonos, szabványosított szintre lesz beállítva.", "SETTINGS_TIME_ADD": "Időpont hozzáadása", "SETTINGS_TIME_REMOVE": "Időpont eltávolítása", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Fényerő beállítása az egyes kijelzőkhöz", "SETTINGS_TIME_INDIVIDUAL_DESC": "A fényerő beállítása kijelzőnként, nem pedig egyszerre az összes kijelzőn.", "SETTINGS_TIME_STARTUP_TITLE": "Ellenőrizze az alkalmazás futtatásakor", "SETTINGS_TIME_STARTUP_DESC": "Állítsa be a fényerőt az időpontokkal összhangban a Twinkle Tray indításakor.", "SETTINGS_HOTKEYS_TITLE": "Gyorsbillentyűk", "SETTINGS_HOTKEYS_DESC": "Konfigurálja a gyorsbillentyűket egy vagy az összes kijelző fényerejének beállításához.", "SETTINGS_HOTKEYS_ADD": "Gyorsbillentyű hozzáadása", "SETTINGS_HOTKEYS_REMOVE": "Gyorsbillentyű eltávolítása", "SETTINGS_HOTKEYS_INCREASE": "Fényerő növelése", "SETTINGS_HOTKEYS_DECREASE": "Fényerő csökkentése", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Itt nyomja meg a billentyűket", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Fényerőszint beállítása", "SETTINGS_HOTKEYS_LEVEL_DESC": "Mennyivel legyen a fényerő módosítva a gyorsbillentyűk használatakor.", "SETTINGS_UPDATES_TITLE": "Frissítések", "SETTINGS_UPDATES_VERSION": "A Twinkle Tray jellenlegi verziója: {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Új verziók automatikus ellenőrzése", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Ha új verzió elérhető, az a fényerőpanelen fog megjelenni.", "SETTINGS_UPDATES_MS_STORE": "Az új verziók kereséséhez látogasson el a Microsoft Store alkalmazásba.", "SETTINGS_UPDATES_AVAILABLE": "A Twinkle Tray új verziója érhető el!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Naprakész. Az aktuális verzió a következő változásokat tartalmazza:", "SETTINGS_UPDATES_DOWNLOADING": "Frissítés letöltése…", "SETTINGS_UPDATES_DOWNLOAD": "Letöltés és telepítés {{1}}", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Aktuális értékek ellenőrzése", "PANEL_LABEL_TURN_OFF": "Kikapcsolás", "GENERIC_MINUTES": "perc", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Inaktív kijelző elrejtése", "SETTINGS_HOTKEYS_TOD_TITLE": "Kijelzők kikapcsolásához társított művelet", "SETTINGS_TIME_IDLE_TITLE": "Tétlenség észlelés", "SETTINGS_HOTKEYS_TOD_SOFT": "Szoftveres jel (alapértelmezett)", "SETTINGS_HOTKEYS_TOD_HARD": "Hardveres* jel (csak DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Hardveres* és szoftveres jel", "SETTINGS_HOTKEYS_TOD_NOTE": "*Megjegyzés: Nem minden DDC/CI monitor támogatja ezt a funkciót.", "SETTINGS_HOTKEYS_BREAK_TITLE": "A gyorsbillentyűk megszakítják a kapcsolt szinteket", "SETTINGS_HOTKEYS_BREAK_DESC": "Ha egyetlen kijelzőhöz használ gyorsbillentyűt, és a „kapcsolt szintek” aktív, akkor az inaktívvá válik.", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Ha a fedél le van zárva, vagy a belső kijelző le van tiltva a Windows rendszerben, rejtse el a fényerő csúszkáját a panelen.", "SETTINGS_GENERAL_MICA_DESC": "A háttér elmosódás engedélyezése vagy letiltása a Twinkle Trayben.", "GENERIC_SECONDS": "mp", "SETTINGS_GENERAL_MICA_TITLE": "Kis elmosódás", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "A fényerő panel megnyitásakor mindig kapja meg a monitor legfrissebb értékeit. Engedélyezze ezt, ha a fényerő (vagy más VCP kódok, például a kontraszt) gyakran változik a Twinkle Tray-n kívülről.", "SETTINGS_FEATURES_UNSUPPORTED": "Ez a monitor nem támogatja a DDC/CI funkciókat.", "SETTINGS_TIME_IDLE_DESC": "Ha egy bizonyos ideig nem érzékel bevitelt, az összes kijelző fényereje csökken.", "SETTINGS_HOTKEYS_TOD_DESC": "Testreszabhatja a Kijelzők kikapcsolása gyorsbillentyű vagy ikon használatakor kiküldött jelet. A szoftveres jel fekete képernyőt jelenít meg, amíg a Windows nem érzékel bevitelt (pl. egérrel vagy billentyűzettel). A hardveres jel kikapcsolja a monitorokat.", "SETTINGS_HOTKEYS_TOD_NONE": "Semmi (ikon elrejtése)", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Ha a Twinkle Tray nem reagál a tálcaikonra kattintásra vagy nem érzékeli a kijelzőket, megpróbálhat letiltani bizonyos monitorészlelési módszereket. A módosítások érvénybe léptetéséhez indítsa újra a Twinkle Tray programot. {{1}}", "GENERIC_PAUSE_IDLE": "Tétlenség érzékelés szüneteltetése", "SETTINGS_GENERAL_TROUBLESHOOTING": "Hibaelhárítás", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Kijelzők elrejtése", "SETTINGS_TIME_TRANSITON_TITLE": "Fényerő átmenet sebessége", "SETTINGS_TIME_TRANSITON_DESC": "Milyen gyorsan váltson a fényerő, ha ehhez időpont van aktiválva.", "SETTINGS_TIME_ANIMATE_DESC": "A fényerő értékei animálva lesznek az aktuális és a következő ütemezett esemény között. Növelheti a CPU-használatot. A manuális fényerő-beállítások gyorsan felülíródnak, amíg ez aktív.", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Ha a Twinkle Tray gyorsbillentyű-fedvénye zavarja a teljes képernyős alkalmazásokat, itt letilthatja.", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Engedélyezett monitorészlelési módszerek", "GENERIC_SPEED_INSTANT": "Azonnal", "GENERIC_SPEED_SLOW": "Lassú", "GENERIC_SPEED_VERY_SLOW": "Nagyon lassú", "GENERIC_SPEED_NORMAL": "Normál", "GENERIC_DDC_WARNING": "A DDC/CI funkciók miatt a monitor lefagyhat. Használja saját felelősségére.", "GENERIC_SPEED_FAST": "Gyors", "GENERIC_SPEED_VERY_FAST": "Nagyon gyors", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Átfedés letiltása", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabil (alapértelmezett)", "GENERIC_PAUSE_TOD": "Időbeállítások szüneteltetése", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Ha el szeretne rejteni bizonyos kijelzőket a felugró menüből, itt kikapcsolhatja őket.", "SETTINGS_TIME_ANIMATE_TITLE": "Animálás időpontok között", "SETTINGS_UPDATES_CHANNEL": "Frissítési csatorna", "SETTINGS_UPDATES_BRANCH_BETA": "Béta", "SETTINGS_FEATURES_POWER_OFF": "Kikapcsolás", "GENERIC_OPTIONAL": "Opcionális", "PANEL_LABEL_TURN_ON": "Bekapcsolás", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Leginkább kompatibilis", "SETTINGS_GENERAL_OVERLAY_TITLE": "Alapértelmezett átfedési viselkedés", "SETTINGS_GENERAL_OVERLAY_DESC": "Mennyire erőteljesen próbáljon meg a fényerő gyorsbillentyű fedvénye más alkalmazások felett megjelenni. Ezt nem szükséges módosítania.", "GENERIC_DEFAULT": "Alapértelmezett", "GENERIC_DELETE": "Törlés", "SETTINGS_FEATURES_POWER_COMPAT": "Leginkább kompatibilis", "GENERIC_CALIBRATION_POINT": "Kalibrációs pont", "GENERIC_NOT_SUPPORTED": "Nem támogatott", "GENERIC_SUPPORTED": "Támogatott", "GENERIC_UNSUPPORTED": "Nem támogatott", "GENERIC_ACTIVE": "Aktív", "GENERIC_DETECTING_DISPLAYS": "Kijelzők észlelése…", "GENERIC_SLIDER_INDICATOR_TYPE": "Csúszkajelző típusa", "GENERIC_ICON": "Ikon", "GENERIC_TEXT": "Szöveg", "GENERIC_SLIDER_ICON": "Csúszka ikon", "GENERIC_SLIDER_TEXT": "Csúszka szöveg", "GENERIC_SLIDER_NAME": "Adja meg a csúszka nevét", "PANEL_LABEL_INPUTS": "Bemenetek", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Letiltás a záróképernyőn", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Ne férjen hozzá a monitorokhoz, amíg a felhasználói munkamenet zárolva van, hogy elkerülje az ütközéseket többfelhasználós környezetekben.", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Windows stílus", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "A fedvény a legtöbb ablak felett megjelenik, de nem pozícionálja magát a \"mindig legfelül\" beállítású alkalmazások fölé.", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Kényszerítve", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Mindig próbálja meg a fedvényt a többi ablak felett megjeleníteni. Ez problémákat okozhat a teljes képernyős játékoknál és más teljes képernyős alkalmazásoknál. Egyes játékokban aktiválhatja csalásgátló funkciót is.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Régi DDC/CI észlelési módszer", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Használja a régi, v1.15.5-ös módszert a DDC/CI kijelzők észlelésére.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Fényerő automatikus alkalmazása", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Ha a monitor furcsán reagál ki-/bekapcsolás vagy hardveres leválasztás/csatlakoztatás után, ennek a letiltása segíthet.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Automatikus alkalmazás mellőzése adott monitorokon", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Letiltja az ismert fényerő automatikus alkalmazását minden hardveres/tápellátási esemény után bizonyos monitoroknál. Ez magában foglalja a készenléti állapot észlelési funkciót is.", "SETTINGS_GENERAL_REPORT_TITLE": "Jelentés generálása", "SETTINGS_GENERAL_REPORT_DESC": "Mentsen el egy szövegfájlt, amely tartalmazza a monitorokkal és a hibakeresési beállításokkal kapcsolatos információkat.", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Témamódosítás észlelése", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Észleli a Windowsból származó háttérkép- és témaváltozásokat a tálcaikon és a csillámeffektus frissítéséhez. Ennek a letiltása segíthet, ha egy harmadik féltől származó alkalmazás gyakran változtatja a témát, növeli a CPU-használatot.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Monitor energiaállapot észlelése", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Észleli a monitorok energiaállapotának változásait. A letiltása segíthet, ha hibákat tapasztal a monitorok ki-/bekapcsolása vagy tétlensége során. A funkció érvénybe lépéséhez újraindítás szükséges.", "SETTINGS_MONITORS_CALIBRATION_DESC": "Minden monitorhoz egyedi kalibrációs pontok adhatók hozzá a fényerőgörbék közötti különbségek kompenzálására. A bemeneti érték a csúszkán jelzett fényerőszint, míg a kimeneti érték a monitorra alkalmazott tényleges fényerőszint.", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR kijelzőbeállítások", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Engedélyezze az SDR fényerő-csúszkákat bizonyos monitorokhoz. A monitorokon engedélyezni kell a HDR-t a Windowsban ahhoz, hogy ez működjön.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "Az SDR helyettesíti az elsődleges csúszkát", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Az SDR fényerejét a fő fényerő-csúszkával szabályozhatja, miközben a HDR aktív.", "SETTINGS_FEATURES_POWER_TITLE": "Energiaállapot jel", "SETTINGS_FEATURES_POWER_DESC": "DDC/CI parancs küldésekor a kijelző kikapcsolására a következő érték(ek) kerülnek elküldésre.", "SETTINGS_FEATURES_POWER_STANDBY": "Készenlét", "SETTINGS_FEATURES_POWER_WARNING": "A „Készenlét” opció nagyobb valószínűséggel teszi lehetővé a monitor be- és kikapcsolását a Twinkle Tray-ből. Sok monitor azonban nem reagál megfelelően az energiaállapot változtatására. Saját felelősségre használja.", "SETTINGS_FEATURES_ADD": "Funkció hozzáadása", "SETTINGS_FEATURES_ADD_DESC": "Adja meg annak a funkciónak a VCP-kódját, amelyet hozzá szeretna adni a kijelzőhöz. Vegye figyelembe, hogy a Twinkle Tray nem ellenőrzi, hogy a kijelzője valóban támogatja-e ezt a VCP kódot. Saját felelősségre használja.", "SETTINGS_FEATURES_ADD_VCP": "VCP kód", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP kód (pl. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Ez a funkció már aktív.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Ezen kijelző által jelentett összes VCP kód", "SETTINGS_FEATURES_VCP_LIST_DESC": "Az alábbiakban a kijelző által a Windowsnak jelentett elérhető VCP kódok listája látható. A Twinkle Tray nem ellenőrzi ezen VCP kódok működését vagy stabilitását. Saját felelősségre használja őket.", "SETTINGS_FEATURES_VCP_EXPECTED": "Várható értékek", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR fényerő", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "A fényerőhöz kapcsolva", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Álljon meg ezen fényerőszint után", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "Ha a monitor nem szabványos VCP kódot használ a fényerőhöz (mint például 0x13 vagy 0x6B), vagy ha a fényerő-csúszkát egy másik VCP-kódra szeretné átállítani, akkor írja be a lenti kódot.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "Alapértelmezés szerint hagyja üresen (0x10). A támogatott kódokat az alábbi listában találja.", "SETTINGS_TIME_SUN_TITLE": "Koordináták a napállás opcióhoz", "SETTINGS_TIME_SUN_DESC": "A \"Napállás\" időbeállítás használatához adja meg az aktuális szélességi és hosszúsági fokot, hogy a helyes időpont meghatározható legyen.", "SETTINGS_TIME_USE_SUN_POSITION": "Napállás használata", "SETTINGS_TIME_LAT": "Szélesség", "SETTINGS_TIME_LONG": "Hosszúság", "SETTINGS_TIME_SUN_GET": "Koordináták lekérése", "SETTINGS_TIME_IDLE_FS_TITLE": "A teljes képernyős alkalmazások blokkolják a tétlenség érzékelést", "SETTINGS_TIME_IDLE_FS_DESC": "Teljes képernyős alkalmazások blokkolják a tétlenség érzékelést. Ez csak fókuszban lévő ablakokra alkalmazható.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Média blokkolja a tétlenség érzékelést", "SETTINGS_TIME_IDLE_MEDIA_DESC": "A tétlenség érzékelés le lesz tiltva médialejátszás közben. Ez magában foglalja mind a videót, mind a hangot. Csak akkor érvényes, ha a Windows jelzi, hogy médialejátszás van folyamatban.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Görgetendő mennyiség", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Görgetés megfordítása", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "A tálcaikon felett görgetve a görgetési irány megfordul.", "SETTINGS_HOTKEY_OFF_WARN": "Ez a művelet a „Kijelzők kikapcsolása művelet” alatt kiválasztott beállítást fogja használni. Ha bizonyos kijelzőket szeretne kikapcsolni, használja ehelyett a \"Beállítás\" vagy \"Ciklus\" gyorsbillentyű-műveletet.", "SETTINGS_HOTKEY_TARGET": "Művelet cél", "SETTINGS_HOTKEY_VALUE": "Érték", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Adjon meg egy számot", "SETTINGS_HOTKEY_VALUES": "Értékek", "SETTINGS_HOTKEY_ADD_VALUE": "Érték megadása", "SETTINGS_HOTKEY_ADD_ACTION": "Művelet megadása", "SETTINGS_HOTKEY_ACTION": "Művelet", "SETTINGS_HOTKEY_ACTION_SET": "Érték beállítása", "SETTINGS_HOTKEY_ACTION_OFFSET": "Érték módosítása", "SETTINGS_HOTKEY_ACTION_CYCLE": "Értékek cikluslistája", "SETTINGS_PROFILES_TITLE": "Profilok", "SETTINGS_PROFILES_DESC": "Automatikusan beállítja a fényerőt vagy a parancsikonok átfedésének viselkedését a fókuszban lévő alkalmazástól függően. Profilokat is hozzáadhat a jobb gombbal elérhető menühöz a tálcán, hogy gyorsan módosítsa a fényerőt az előre definiált profilokra.", "SETTINGS_PROFILES_ADD": "Új profil", "SETTINGS_PROFILES_NAME": "Profil neve", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Fényerő beállítása, ha aktív", "SETTINGS_PROFILES_SHOW_MENU": "Megjelenítés a jobb gombos tálcamenüben", "SETTINGS_PROFILES_TRIGGER_TITLE": "Alkalmazás indító beállítások", "SETTINGS_PROFILES_APP_PATH": "Alkalmazásútvonal", "SETTINGS_PROFILES_APP_DESC": "Ha azt szeretné, hogy ez a profil automatikusan aktiválódjon, amikor egy adott alkalmazásra fókuszál, adja meg az EXE fájl teljes vagy részleges elérési útját alább.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Átfedés típus felülírása", "SETTINGS_PROFILES_OVERLAY_DESC": "Módosítja a gyorsbillentyű fedvény viselkedését, amikor a megadott alkalmazásra fókuszálnak. Ez a funkció nem működik, ha a profil manuálisan van aktiválva." } ================================================ FILE: src/localization/id.json ================================================ { "LANGUAGE": "Indonesia", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Batal", "GENERIC_SAVE": "Simpan", "GENERIC_CLEAR": "Bersihkan", "GENERIC_OFF": "Matikan", "GENERIC_ON": "Hidupkan", "GENERIC_QUIT": "Keluar", "GENERIC_CLOSE": "Tutup", "GENERIC_SETTINGS": "Pengaturan", "GENERIC_INSTALL": "Instal", "GENERIC_DISMISS": "Bubarkan", "GENERIC_DISPLAY_SINGLE": "Layar", "GENERIC_ALL_DISPLAYS": "Semua Layar", "GENERIC_REFRESH_DISPLAYS": "Segarkan layar", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Maks", "GENERIC_NO_DISPLAYS": "Tidak ada layar terdeteksi. Silahkan koneksikan layar dengan PC Anda.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Tidak ditemukan layar yang kompatibel. Silahkan periksa apakah \"DDC/CI\" diaktifkan untuk layar Anda.", "GENERIC_NO_DISPLAYS_SHORT": "Tidak ditemukan layar yang kompatibel.", "GENERIC_SECONDS": "detik", "GENERIC_MINUTES": "menit", "PANEL_TITLE": "Sesuaikan Kecerahan", "PANEL_UPDATE_AVAILABLE": "Versi terbaru tersedia", "PANEL_BUTTON_LINK_LEVELS": "Level link", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Matikan layar", "PANEL_LABEL_BRIGHTNESS": "Kecerahan", "PANEL_LABEL_CONTRAST": "Kontras", "PANEL_LABEL_OFF_ON": "Keadaan Daya", "PANEL_LABEL_COLOR_TEMPERATURE": "Temperatur Warna", "PANEL_LABEL_VOLUME": "Volume", "PANEL_LABEL_TURN_OFF": "Matikan", "INTRO_TITLE": "Halo, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Ikon tray untuk Twinkle Tray kemungkinan disembunyikan, sehingga Anda perlu memindahkannya ke suatu tempat yang mudah diakses. Ikuti petunjuk berikut.", "SETTINGS_TITLE": "Pengaturan Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Umum", "SETTINGS_SIDEBAR_MONITORS": "Pengaturan Monitor", "SETTINGS_SIDEBAR_FEATURES": "Fitur DDC/CI", "SETTINGS_SIDEBAR_TIME": "Penyesuaian Waktu", "SETTINGS_SIDEBAR_HOTKEYS": "Tombol Pintas", "SETTINGS_SIDEBAR_UPDATES": "Pembaruan", "SETTINGS_GENERAL_TITLE": "Umum", "SETTINGS_GENERAL_STARTUP": "Luncurkan saat startup", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Terapkan kecerahan pada startup", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Kembalikan kecerahan terakhir pada setiap layar ketika Twinkle Tray dimulai.", "SETTINGS_GENERAL_THEME_TITLE": "Tema", "SETTINGS_GENERAL_THEME_SYSTEM": "Preferensi sistem (default)", "SETTINGS_GENERAL_THEME_DARK": "Gelap", "SETTINGS_GENERAL_THEME_LIGHT": "Terang", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Bahasa", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Bahasa system (default)", "SETTINGS_GENERAL_RESET_TITLE": "Reset pengaturan", "SETTINGS_GENERAL_RESET_DESC": "Tekan tombol ini untuk membersihkan pengaturan Anda.", "SETTINGS_GENERAL_RESET_BUTTON": "Reset pengaturan", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akrilik Blur", "SETTINGS_GENERAL_ACRYLIC_DESC": "Mengaktifkan atau menonaktifkan blur di balik background transparan dalam Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Mika Blur", "SETTINGS_GENERAL_MICA_DESC": "Mengaktifkan atau menonaktifkan blur di balik background dalam Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analitik", "SETTINGS_GENERAL_ANALYTICS_DESC": "Kirim data penggunaan untuk membantu meningkatkan Twinkle Tray. Tidak ada info pribadi yang dikirim. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Pelajari lebih lanjut", "SETTINGS_GENERAL_SCROLL_TITLE": "Pintasan gulir ikon tray", "SETTINGS_GENERAL_SCROLL_DESC": "Sesuaikan kecerahan dari semua layar sekaligus dengan menggulir pada ikon tray sistem. Hal ini tidak bekerja pada beberapa trackpads.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Ikon tray", "SETTINGS_MONITORS_RATE_TITLE": "Tingkat pembaruan kecerahan", "SETTINGS_MONITORS_RATE_DESC": "Seberapa sering kecerahan akan diperbarui pada layar Anda saat Anda menyesuaikan nilainya. Tambah waktu jika layar Anda berkedip.", "SETTINGS_MONITORS_RATE_0": "Menggelikan", "SETTINGS_MONITORS_RATE_1": "Cepat (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Lambat (1 detik)", "SETTINGS_MONITORS_RATE_4": "Sangat Lambat (2 detik)", "SETTINGS_MONITORS_RENAME_TITLE": "Ubah Nama Monitor", "SETTINGS_MONITORS_RENAME_DESC": "Jika Anda lebih suka nama yang berbeda untuk setiap monitor (misalnya \"Monitor Kiri\", \"Monitor Tengah\"), Anda dapat memasukkannya di bawah ini. Membiarkannya kosong akan mengembalikan nama asli.", "SETTINGS_MONITORS_ENTER_NAME": "Masukkan nama", "SETTINGS_MONITORS_REORDER_TITLE": "Urutkan Ulang Monitor", "SETTINGS_MONITORS_REORDER_DESC": "Ubah urutan monitor yang ditampilkan di tray. Klik dan seret untuk membuat perubahan.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalisasi Kecerahan", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitor sering kali memiliki rentang kecerahan yang berbeda. Dengan membatasi kecerahan min/maks per layar, tingkat kecerahan antar layar jauh lebih konsisten. Monitor serupa akan menggunakan pengaturan yang sama.", "SETTINGS_MONITORS_DETAILS_NAME": "Nama", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Nama Internal", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Metode Komunikasi", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Kecerahaan Saat Ini", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Kecerahan Maks", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalisasi Kecerahan", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Menyembunyikan Tampilan Internal Tidak Aktif", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Saat layar tertutup atau layar internal telah dinonaktifkan di Windows, sembunyikan slider kecerahan di panel.", "SETTINGS_FEATURES_DESCRIPTION": "Mengaktifkan atau menonaktifkan fitur DDC/CI tertentu di panel kecerahan. Setidaknya satu fitur harus diaktifkan agar monitor Anda muncul di panel kecerahan. Tidak semua layar mendukung fitur ini, seperti layar laptop/tablet.", "SETTINGS_FEATURES_UNSUPPORTED": "Monitor ini tidak mendukung fitur DDC/CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Periksa Nilai Saat Ini", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Selalu dapatkan nilai terbaru dari monitor saat membuka panel kecerahan. Aktifkan ini jika kecerahan (atau kode VCP lainnya seperti kontras) sering berubah dari luar Twinkle Tray.", "SETTINGS_TIME_TITLE": "Penyesuaian Waktu Hari", "SETTINGS_TIME_DESC": "Secara otomatis mengatur monitor Anda ke tingkat kecerahan tertentu pada waktu yang diinginkan. Semua monitor akan diatur ke level yang sama dan dinormalisasi.", "SETTINGS_TIME_ADD": "Tambahkan waktu", "SETTINGS_TIME_REMOVE": "Hapus waktu", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Atur kecerahan untuk layar individu", "SETTINGS_TIME_INDIVIDUAL_DESC": "Konfigurasikan kecerahan per layar, bukan untuk semua layar sekaligus.", "SETTINGS_TIME_STARTUP_TITLE": "Periksa pada startup aplikasi", "SETTINGS_TIME_STARTUP_DESC": "Sesuaikan kecerahan agar sesuai dengan waktu yang paling relevan saat Twinkle Tray dimulai.", "SETTINGS_TIME_IDLE_TITLE": "Deteksi Idle", "SETTINGS_TIME_IDLE_DESC": "Apabila tidak ada input yang terdeteksi selama jangka waktu tertentu, kecerahan semua tampilan akan dikurangi.", "SETTINGS_HOTKEYS_TITLE": "Tombol Pintas", "SETTINGS_HOTKEYS_DESC": "Atur tombol pintas untuk menyesuaikan kecerahan dari satu atau semua layar.", "SETTINGS_HOTKEYS_ADD": "Tambahkan Tombol Pintasan", "SETTINGS_HOTKEYS_REMOVE": "Hapus tombol pintas", "SETTINGS_HOTKEYS_INCREASE": "Tingkatkan Kecerahan", "SETTINGS_HOTKEYS_DECREASE": "Kurangi Kecerahan", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Tekan tombol disini", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Penyesuaian tingkat kecerahan", "SETTINGS_HOTKEYS_LEVEL_DESC": "Berapa banyak kecerahan yang harus disesuaikan ketika menggunakan tombol pintas.", "SETTINGS_HOTKEYS_TOD_TITLE": "Matikan Layar aksi", "SETTINGS_HOTKEYS_TOD_DESC": "Sesuaikan sinyal yang dikirim saat menggunakan tombol atau ikon Matikan Layar. Sinyal perangkat lunak akan menampilkan layar hitam sampai input (mis. mouse atau keyboard) terdeteksi oleh Windows. Sinyal perangkat keras akan mematikan daya ke monitor.", "SETTINGS_HOTKEYS_TOD_NONE": "Tidak ada (sembunyikan ikon)", "SETTINGS_HOTKEYS_TOD_SOFT": "Sinyal perangkat lunak (default)", "SETTINGS_HOTKEYS_TOD_HARD": "Sinyal perangkat keras* (hanya DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Sinyal perangkat keras* dan perangkat lunak", "SETTINGS_HOTKEYS_TOD_NOTE": "*Catatan: Tidak semua monitor DDC/CI mendukung fitur ini.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Tombol pintas menghancurkan linked levels", "SETTINGS_HOTKEYS_BREAK_DESC": "Ketika menggunakan tombol pintas untuk layar tunggal dan \"linked levels\" aktif, maka akan dinonaktfikan.", "SETTINGS_UPDATES_TITLE": "Pembaruan", "SETTINGS_UPDATES_VERSION": "Anda memiliki Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Otomatis memeriksa versi terbaru", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Ketika terdapat versi baru, maka akan muncul pada panel kecerahan.", "SETTINGS_UPDATES_MS_STORE": "Untuk memeriksa versi baru, kunjungi aplikasi Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Versi terbaru dari Twinkle Tray tersedia!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Terkini. Versi saat ini mencakup perubahan berikut:", "SETTINGS_UPDATES_DOWNLOADING": "Mengunduh pembaruan…", "SETTINGS_UPDATES_DOWNLOAD": "Mengunduh & Instal {{1}}", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Jika Twinkle Tray tidak responsif ketika mengklik ikon tray atau tidak mendeteksi tampilan Anda, Anda bisa mencoba menonaktifkan metode deteksi monitor tertentu. Restart Twinkle Tray agar perubahan yang terjadi bisa diterapkan. {{1}}", "GENERIC_PAUSE_TOD": "Penyesuaian Waktu Jeda", "GENERIC_PAUSE_IDLE": "Jeda Deteksi Idle", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Metode deteksi monitor yang diaktifkan", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Nonaktifkan hamparan", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Jika overlay hotkey Twinkle Tray mengganggu aplikasi layar penuh, Anda bisa menonaktifkannya di sini.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Sembunyikan Tampilan", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Jika Anda ingin menyembunyikan tampilan tertentu dari flyout, Anda bisa menonaktifkannya di sini.", "SETTINGS_TIME_TRANSITON_DESC": "Seberapa cepat kecerahan harus bertransisi apabila penyesuaian waktu diaktifkan.", "SETTINGS_TIME_TRANSITON_TITLE": "Kecepatan transisi kecerahan", "SETTINGS_TIME_ANIMATE_TITLE": "Menghidupkan di antara waktu", "SETTINGS_TIME_ANIMATE_DESC": "Nilai kecerahan akan dianimasikan antara acara yang dijadwalkan saat ini dan berikutnya. Dapat meningkatkan penggunaan CPU. Penyesuaian kecerahan manual akan dengan cepat ditimpa saat ini aktif.", "SETTINGS_GENERAL_TROUBLESHOOTING": "Pemecahan Masalah", "GENERIC_DDC_WARNING": "Fitur DDC/CI seperti mengontrol status daya dapat menyebabkan monitor Anda menjadi tidak responsif. Gunakan dengan risiko Anda sendiri.", "GENERIC_SPEED_INSTANT": "Instan", "GENERIC_SPEED_SLOW": "Lambat", "GENERIC_SPEED_VERY_SLOW": "Sangat Lambat", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_SPEED_FAST": "Cepat", "GENERIC_SPEED_VERY_FAST": "Sangat cepat", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabil (default)", "SETTINGS_UPDATES_CHANNEL": "Perbarui saluran", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Matikan", "GENERIC_DELETE": "Hapus", "GENERIC_DEFAULT": "Bawaan", "GENERIC_OPTIONAL": "Opsional", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Metode deteksi DDC/CI lama", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Gunakan metode lama v1.15.5 untuk mendeteksi tampilan DDC/CI.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Terapkan kecerahan secara otomatis", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Lewati penerapan otomatis ke monitor tertentu", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Nonaktifkan penerapan kecerahan yang diketahui secara otomatis setelah semua kejadian perangkat keras/daya untuk monitor tertentu. Ini termasuk fitur deteksi siaga.", "SETTINGS_FEATURES_POWER_DESC": "Saat mengirim perintah DDC/CI untuk mematikan layar Anda, nilai berikut akan dikirim.", "SETTINGS_FEATURES_POWER_STANDBY": "Siaga", "SETTINGS_FEATURES_VCP_EXPECTED": "Nilai yang diharapkan", "SETTINGS_GENERAL_REPORT_TITLE": "Buat Laporan", "SETTINGS_GENERAL_REPORT_DESC": "Simpan berkas teks berisi informasi mengenai monitor dan pengaturan Anda untuk debugging.", "SETTINGS_FEATURES_POWER_COMPAT": "Paling kompatibel", "SETTINGS_FEATURES_POWER_WARNING": "Opsi \"Standby\" lebih memungkinkan untuk menghidupkan/mematikan monitor dari Twinkle Tray. Namun, banyak monitor tidak merespons dengan benar terhadap perubahan status daya. Gunakan dengan risiko Anda sendiri.", "SETTINGS_FEATURES_ADD": "Tambahkan Fitur", "SETTINGS_FEATURES_ADD_DESC": "Masukkan kode VCP untuk fitur yang ingin Anda tambahkan ke layar Anda. Harap perhatikan bahwa Twinkle Tray tidak memvalidasi apakah layar Anda benar-benar mendukung kode VCP ini. Gunakan dengan risiko Anda sendiri.", "SETTINGS_FEATURES_ADD_VCP": "Kode VCP", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "Kode VCP (Misalnya 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Fitur ini sudah aktif.", "SETTINGS_FEATURES_VCP_LIST_DESC": "Berikut ini adalah daftar kode VCP yang tersedia yang dilaporkan oleh layar ini ke Windows. Twinkle Tray tidak memvalidasi fungsionalitas atau stabilitas kode VCP ini. Gunakan kode-kode ini dengan risiko Anda sendiri.", "SETTINGS_TIME_SUN_TITLE": "Koordinat untuk posisi matahari", "SETTINGS_TIME_LAT": "Lintang", "SETTINGS_TIME_LONG": "Garis bujur", "SETTINGS_TIME_SUN_GET": "Dapatkan koordinat", "SETTINGS_TIME_IDLE_FS_TITLE": "Aplikasi layar penuh memblokir deteksi idle", "SETTINGS_TIME_IDLE_FS_DESC": "Aplikasi layar penuh memblokir deteksi saat tidak aktif. Ini hanya berlaku untuk jendela yang difokuskan.", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Balikkan gulir", "SETTINGS_HOTKEY_OFF_WARN": "Tindakan ini akan menggunakan opsi yang dipilih di bawah tindakan \"Matikan Layar\". Jika Anda ingin mematikan tampilan tertentu, gunakan Tindakan Tombol Pintasan \"Atur\" atau \"Siklus\".", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Masukkan angka", "SETTINGS_HOTKEY_VALUES": "Nilai-nilai", "SETTINGS_HOTKEY_ADD_VALUE": "Tambahkan Nilai", "SETTINGS_HOTKEY_ACTION": "Tindakan", "SETTINGS_HOTKEY_ACTION_SET": "Tetapkan nilai", "SETTINGS_HOTKEY_ACTION_OFFSET": "Sesuaikan nilai", "SETTINGS_PROFILES_TITLE": "Profil", "SETTINGS_PROFILES_DESC": "Sesuaikan kecerahan atau perilaku overlay pintasan secara otomatis tergantung pada aplikasi yang difokuskan. Anda juga dapat menambahkan profil ke menu klik kanan di baki sistem untuk mengubah kecerahan dengan cepat ke profil yang telah ditetapkan sebelumnya.", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Hamparan akan ditampilkan di sebagian besar jendela, tetapi tidak akan muncul di atas aplikasi yang ditandai sebagai \"selalu di atas\".", "SETTINGS_TIME_SUN_DESC": "Untuk menggunakan \"posisi matahari\" untuk penyesuaian waktu, masukkan lintang dan bujur Anda saat ini sehingga waktu yang tepat dapat ditentukan.", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Saat menggulir ikon baki sistem, arah gulir akan dibalik.", "SETTINGS_GENERAL_OVERLAY_DESC": "Seberapa kuat tampilan tombol pintas kecerahan akan mencoba ditampilkan di atas aplikasi lain. Anda seharusnya tidak perlu menyesuaikan ini.", "SETTINGS_HOTKEY_TARGET": "Target Tindakan", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Semua kode VCP dilaporkan oleh layar ini", "PANEL_LABEL_TURN_ON": "Nyalakan", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Paling kompatibel", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Jika monitor Anda merespons aneh setelah dimatikan/dihidupkan atau setelah melepas/menyambungkan perangkat keras, menonaktifkannya mungkin dapat membantu.", "SETTINGS_GENERAL_OVERLAY_TITLE": "Perilaku overlay bawaan", "SETTINGS_FEATURES_POWER_TITLE": "Sinyal Status Daya", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Selalu coba tampilkan overlay di atas jendela lain. Ini dapat menyebabkan masalah dengan game layar penuh eksklusif dan aplikasi layar penuh lainnya. Ini juga dapat memicu anti-cheat di beberapa game.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Media memblokir deteksi idle", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Deteksi siaga akan dinonaktifkan saat media apa pun sedang diputar. Ini termasuk video dan audio. Ini hanya berlaku saat Windows melaporkan bahwa media sedang diputar.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Jumlah untuk digulir", "SETTINGS_HOTKEY_VALUE": "Nilai", "SETTINGS_PROFILES_ADD": "Profil Baru", "SETTINGS_PROFILES_NAME": "Nama Profil", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Atur kecerahan saat aktif", "SETTINGS_PROFILES_SHOW_MENU": "Tampilkan di menu baki klik kanan", "SETTINGS_PROFILES_TRIGGER_TITLE": "Setelan pemicu aplikasi", "SETTINGS_PROFILES_APP_PATH": "Jalur aplikasi", "SETTINGS_PROFILES_APP_DESC": "Jika Anda ingin profil ini aktif secara otomatis saat aplikasi tertentu difokuskan, masukkan jalur lengkap atau sebagian EXE di bawah ini.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Ganti jenis overlay", "SETTINGS_PROFILES_OVERLAY_DESC": "Mengubah perilaku hotkey overlay saat aplikasi tertentu difokuskan. Fitur ini tidak berfungsi saat profil diaktifkan secara manual.", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Dipaksa menyala", "SETTINGS_HOTKEY_ACTION_CYCLE": "Siklus daftar nilai", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Kecerahan" } ================================================ FILE: src/localization/it.json ================================================ { "LANGUAGE": "Italiano", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Annulla", "GENERIC_SAVE": "Salva", "GENERIC_CLEAR": "Cancella", "GENERIC_OFF": "Spento", "GENERIC_ON": "Acceso", "GENERIC_QUIT": "Esci", "GENERIC_CLOSE": "Chiudi", "GENERIC_SETTINGS": "Impostazioni", "GENERIC_INSTALL": "Installa", "GENERIC_DISMISS": "Ignora", "GENERIC_DISPLAY_SINGLE": "Schermo", "GENERIC_ALL_DISPLAYS": "Tutti gli schermi", "GENERIC_MINIMUM": "Minimo", "GENERIC_MAXIMUM": "Massimo", "GENERIC_NO_DISPLAYS": "Nessuno schermo rilevato. Collega uno schermo al tuo PC.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Nessuno schermo compatibile rilevato. Controlla che il \"DDC/CI\" sia abilitato per i tuoi schermi.", "GENERIC_NO_DISPLAYS_SHORT": "Nessuno schermo compatibile rilevato.", "PANEL_TITLE": "Regola luminosità", "PANEL_UPDATE_AVAILABLE": "Nuova versione disponibile", "PANEL_BUTTON_LINK_LEVELS": "Collega livelli", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Spegni gli schermi", "INTRO_TITLE": "Benvenuto su Twinkle Tray!", "INTRO_INSTRUCTIONS": "L'icona di Twinkle Tray è probabilmente nascosta, quindi dovresti spostarla da qualche parte per accedervi facilmente. Guarda qui sotto per le istruzioni.", "SETTINGS_TITLE": "Impostazioni di Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Generale", "SETTINGS_SIDEBAR_MONITORS": "Impostazioni schermo", "SETTINGS_SIDEBAR_TIME": "Pianificazione giornaliera", "SETTINGS_SIDEBAR_HOTKEYS": "Scorciatoie da tastiera", "SETTINGS_SIDEBAR_UPDATES": "Aggiornamenti", "SETTINGS_GENERAL_TITLE": "Generale", "SETTINGS_GENERAL_STARTUP": "Apri all'avvio", "SETTINGS_GENERAL_THEME_TITLE": "Tema", "SETTINGS_GENERAL_THEME_SYSTEM": "Tema del sistema (predefinito)", "SETTINGS_GENERAL_THEME_DARK": "Scuro", "SETTINGS_GENERAL_THEME_LIGHT": "Chiaro", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Lingua", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Lingua del sistema (predefinito)", "SETTINGS_GENERAL_RESET_TITLE": "Ripristina impostazioni", "SETTINGS_GENERAL_RESET_DESC": "Premi questo pulsante per cancellare la tua configurazione.", "SETTINGS_GENERAL_RESET_BUTTON": "Ripristina impostazioni", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Statistiche", "SETTINGS_GENERAL_ANALYTICS_DESC": "Invia i dati di utilizzo per aiutare a migliorare Twinkle Tray. Non verrà inviata nessuna informazione personale. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Scopri di più", "SETTINGS_MONITORS_RATE_TITLE": "Velocità di aggiornamento della luminosità", "SETTINGS_MONITORS_RATE_DESC": "Quanto spesso viene aggiornata la luminosità degli schermi mentre la stai cambiando. Aumenta questo valore se i tuoi schermi sfarfallano.", "SETTINGS_MONITORS_RATE_0": "Immediato", "SETTINGS_MONITORS_RATE_1": "Veloce (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normale (500 ms)", "SETTINGS_MONITORS_RATE_3": "Lento (1 secondo)", "SETTINGS_MONITORS_RATE_4": "Molto lento (2 secondi)", "SETTINGS_MONITORS_RENAME_TITLE": "Rinomina schermi", "SETTINGS_MONITORS_RENAME_DESC": "Se preferisci assegnare un nome diverso a ciascuno schermo (es. \"Schermo a sinistra\", \"Schermo centrale\"), puoi inserirlo qui sotto. Lasciando il campo vuoto verrà ripristinato il nome originale.", "SETTINGS_MONITORS_ENTER_NAME": "Inserisci il nome", "SETTINGS_MONITORS_REORDER_TITLE": "Riordina gli schermi", "SETTINGS_MONITORS_REORDER_DESC": "Cambia l'ordine in cui vengono mostrati gli schermi. Premi e trascina per fare le modifiche.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalizza luminosità", "SETTINGS_MONITORS_NORMALIZE_DESC": "Spesso gli schermi hanno un intervallo di luminosità diverso. Limitando la luminosità minima e massima per ciascuno, il livello di luminosità tra diversi schermi sarà più consistente.", "SETTINGS_TIME_TITLE": "Pianificazione oraria", "SETTINGS_TIME_DESC": "Cambia automaticamente il livello di luminosità degli schermi ad un orario specifico. Tutti gli schermi verranno impostati allo stesso livello normalizzato.", "SETTINGS_TIME_ADD": "Aggiungi un orario", "SETTINGS_TIME_REMOVE": "Rimuovi l'orario", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Imposta la luminosità per ciascuno schermo", "SETTINGS_TIME_INDIVIDUAL_DESC": "Imposta la luminosità individualmente per ciascuno schermo invece che tutti insieme.", "SETTINGS_TIME_STARTUP_TITLE": "Controlla all'avvio dell'applicazione", "SETTINGS_TIME_STARTUP_DESC": "Cambia la luminosità in base all'orario più vicino all'avvio di Twinkle Tray.", "SETTINGS_HOTKEYS_TITLE": "Scorciatoie", "SETTINGS_HOTKEYS_DESC": "Configura le scorciatoie per cambiare la luminosità di uno o tutti gli schermi.", "SETTINGS_HOTKEYS_ADD": "Aggiungi scorciatoia", "SETTINGS_HOTKEYS_REMOVE": "Rimuovi tasti", "SETTINGS_HOTKEYS_INCREASE": "Aumenta luminosità", "SETTINGS_HOTKEYS_DECREASE": "Diminuisci luminosità", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Premi i tasti qui", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Regola livello di luminosità", "SETTINGS_HOTKEYS_LEVEL_DESC": "Di quanto verrà cambiata la luminosità usando le scorciatoie.", "SETTINGS_UPDATES_TITLE": "Aggiornamenti", "SETTINGS_UPDATES_VERSION": "Hai Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Controlla automaticamente se ci sono nuove versioni", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Quando sarà disponibile una nuova versione, verrà mostrata nel pannello della luminosità.", "SETTINGS_UPDATES_MS_STORE": "Per controllare se ci sono nuove versioni, visita il Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Nuova versione di Twinkle Tray disponibile!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Il software è aggiornato. La versione attuale include questi cambiamenti:", "SETTINGS_UPDATES_DOWNLOADING": "Download dell'aggiornamento…", "SETTINGS_UPDATES_DOWNLOAD": "Scarica e installa {{1}}", "PANEL_LABEL_OFF_ON": "Stato di alimentazione", "PANEL_LABEL_CONTRAST": "Contrasto", "PANEL_LABEL_BRIGHTNESS": "Luminosità", "PANEL_LABEL_COLOR_TEMPERATURE": "Temperatura colore", "SETTINGS_MONITORS_FEATURES_TITLE": "Funzionalità DDC/CI", "SETTINGS_GENERAL_SCROLL_DESC": "Regola simultaneamente la luminosità di tutti gli schermi scorrendo l'icona nella barra delle applicazioni. Non funziona con alcuni trackpad.", "SETTINGS_GENERAL_ACRYLIC_DESC": "Abilita o disabilita la sfocatura degli sfondi trasparenti su Twinkle Tray.", "SETTINGS_SIDEBAR_FEATURES": "Funzionalità DDC/CI", "SETTINGS_GENERAL_SCROLL_TITLE": "Scorri l'icona nella barra delle applicazioni", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Ripristina l'ultima luminosità nota per ogni schermo all'avvio di Twinkle Tray.", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Applica la luminosità all'avvio", "SETTINGS_FEATURES_DESCRIPTION": "Abilita o disabilita specifiche funzioni DDC/CI nel pannello della luminosità. Almeno una funzione deve essere abilitata affinché il monitor venga visualizzato nel pannello della luminosità. Non tutti gli schermi supportano queste funzionalità, come i display di laptop/tablet.", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalizzazione della luminosità", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Luminosità massima", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Luminosità attuale", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Metodo di comunicazione", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Nome interno", "SETTINGS_MONITORS_DETAILS_NAME": "Nome", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Icona della barra delle applicazioni", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Sfocatura acrilica", "PANEL_LABEL_VOLUME": "Volume", "GENERIC_REFRESH_DISPLAYS": "Aggiorna schermi", "SETTINGS_HOTKEYS_BREAK_TITLE": "Le scorciatoie disabilitano i livelli collegati", "SETTINGS_HOTKEYS_TOD_DESC": "Personalizza il segnale inviato quando si utilizza la scorciatoia o l'icona Spegni gli schermi. Il segnale del software visualizzerà uno schermo nero finché l'input (es. mouse o tastiera) non viene rilevato da Windows. Il segnale hardware disattiverà l'alimentazione dei monitor.", "SETTINGS_HOTKEYS_TOD_TITLE": "Azione Spegni gli schermi", "SETTINGS_HOTKEYS_BREAK_DESC": "Quando si utilizza una scorciatoia per solo uno schermo e \"livelli collegati\" è attivato, la funzione verrà disattivata.", "SETTINGS_HOTKEYS_TOD_NOTE": "*Nota: non tutti i monitor DDC/CI supportano questa funzione.", "SETTINGS_HOTKEYS_TOD_BOTH": "Segnale hardware* e software", "SETTINGS_HOTKEYS_TOD_HARD": "Segnale hardware* (solo DDC/CI)", "SETTINGS_HOTKEYS_TOD_SOFT": "Segnale software (predefinito)", "SETTINGS_HOTKEYS_TOD_NONE": "Nessuna (nascondi icona)", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Se Twinkle Tray non risponde quando si fa clic sull'icona della barra o non rileva i tuoi schermi, puoi provare a disabilitare alcuni metodi di rilevamento dei monitor. Riavvia Twinkle Tray affinché le modifiche abbiano effetto. {{1}}", "PANEL_LABEL_TURN_OFF": "Spegni", "GENERIC_MINUTES": "minuti", "SETTINGS_GENERAL_MICA_TITLE": "Sfocatura Mica", "GENERIC_SECONDS": "secondi", "SETTINGS_TIME_IDLE_TITLE": "Rilevamento inattività", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Controlla i valori attuali", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Ottiene sempre i valori più recenti dal monitor quando si apre il pannello della luminosità. Attivare questa opzione se la luminosità (o altri codici VCP come il contrasto) cambiano spesso fuori da Twinkle Tray.", "SETTINGS_TIME_IDLE_DESC": "Quando non viene rilevata alcuna attività per un determinato periodo di tempo, la luminosità di tutti gli schermi viene ridotta.", "SETTINGS_GENERAL_MICA_DESC": "Abilita o disabilita la sfumatura degli sfondi su Twinkle Tray.", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Nascondi schermo interno inattivo", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Quando il coperchio è chiuso o lo schermo interno è stato disabilitato da Windows, nascondi lo slider della luminosità nel pannello.", "SETTINGS_FEATURES_UNSUPPORTED": "Questo monitor non supporta le funzioni DDC/CI.", "GENERIC_PAUSE_TOD": "Metti in pausa pianificazione giornaliera", "GENERIC_PAUSE_IDLE": "Pausa rilevamento inattività", "SETTINGS_GENERAL_TROUBLESHOOTING": "Risoluzione dei problemi", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Metodi di rilevamento dei monitor abilitati", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Disattiva l'overlay", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Se l'overlay della scorciatoia di Twinkle Tray interferisce con le applicazioni a schermo intero, è possibile disattivarlo qui.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Nascondi schermi", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Se si desidera nascondere determinati schermi dal pannello, è possibile disattivarli qui.", "SETTINGS_TIME_TRANSITON_TITLE": "Velocità di transizione della luminosità", "SETTINGS_TIME_TRANSITON_DESC": "La velocità con cui la luminosità deve cambiare quando si attivano le pianificazioni orarie.", "SETTINGS_TIME_ANIMATE_TITLE": "Animazione tra gli orari", "SETTINGS_TIME_ANIMATE_DESC": "I valori di luminosità saranno animati tra l'evento attuale e il prossimo evento programmato. Può aumentare l'utilizzo della CPU. Le regolazioni manuali della luminosità saranno rapidamente sovrascritte quando questa funzione è attiva.", "GENERIC_SPEED_INSTANT": "Istantaneo", "GENERIC_SPEED_SLOW": "Lento", "GENERIC_SPEED_VERY_SLOW": "Molto lento", "GENERIC_SPEED_NORMAL": "Normale", "GENERIC_SPEED_FAST": "Veloce", "GENERIC_SPEED_VERY_FAST": "Molto veloce", "GENERIC_DDC_WARNING": "Le funzioni DDC/CI possono far bloccare il monitor. L'uso è a proprio rischio e pericolo.", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabile (predefinito)", "SETTINGS_UPDATES_CHANNEL": "Canale di aggiornamento", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Spegnimento", "GENERIC_DELETE": "Elimina", "GENERIC_DEFAULT": "Predefinito", "GENERIC_OPTIONAL": "Facoltativo", "PANEL_LABEL_TURN_ON": "Accendi", "SETTINGS_GENERAL_OVERLAY_TITLE": "Comportamento predefinito dell'overlay", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Modalità più compatibile", "SETTINGS_GENERAL_OVERLAY_DESC": "Il livello di forza con cui l'overlay della scorciatoia della luminosità proverà a comparire sulle altre applicazioni. Non dovresti aver bisogno di cambiare questa impostazione.", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "L'overlay comparirà sulla maggior parte delle finestre, ma non verrà forzato sulle applicazioni contrassegnate come \"sempre in primo piano\".", "SETTINGS_FEATURES_POWER_COMPAT": "Più compatibile", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Sempre in primo piano", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Applica automaticamente luminosità", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Metodo di rilevamento DDC/CI legacy", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Utilizza il vecchio metodo v1.15.5 per rilevare gli schermi DDC/CI.", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Se il monitor risponde in modo strano dopo lo spegnimento e/o la disconnessione/connessione dell'hardware, disabilitare questa funzione potrebbe aiutare.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Salta l'applicazione automatica a monitor specifici", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Disabilita l'applicazione automatica della luminosità nota dopo tutti gli eventi hardware o di accensione per monitor specifici. Questo include la funzione di rilevamento dell'inattività.", "SETTINGS_FEATURES_POWER_TITLE": "Segnale dello stato di alimentazione", "SETTINGS_GENERAL_REPORT_TITLE": "Genera report", "SETTINGS_GENERAL_REPORT_DESC": "Salva un file di testo con le informazioni sui monitor e le impostazioni per il debug.", "SETTINGS_FEATURES_POWER_STANDBY": "Sospensione", "SETTINGS_FEATURES_ADD": "Aggiungi funzione", "SETTINGS_FEATURES_ADD_VCP": "Codice VCP", "SETTINGS_FEATURES_ADD_EXISTS": "Questa funzione è già attiva.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Tutti i codici VCP segnalati dallo schermo", "SETTINGS_FEATURES_VCP_LIST_DESC": "Di seguito è riportato un elenco dei codici VCP disponibili segnalati da questo schermo a Windows. Twinkle Tray non convalida la funzionalità o la stabilità di questi codici VCP. Utilizzateli a vostro rischio e pericolo.", "SETTINGS_FEATURES_VCP_EXPECTED": "Valori attesi", "SETTINGS_FEATURES_POWER_DESC": "Quando si invia il comando DDC/CI per spegnere lo schermo, vengono inviati i seguenti valori.", "SETTINGS_FEATURES_ADD_DESC": "Inserisci il codice VCP per la funzione che desideri aggiungere al tuo schermo. Twinkle Tray non è in grado di verificare se lo schermo supporta effettivamente questo codice VCP. L'uso è a proprio rischio e pericolo.", "SETTINGS_TIME_SUN_TITLE": "Coordinate per la posizione del sole", "SETTINGS_TIME_SUN_DESC": "Per utilizzare la “posizione del sole” per la pianificazione giornaliera, inserire la latitudine e la longitudine correnti in modo da determinare gli orari corretti.", "SETTINGS_TIME_LAT": "Latitudine", "SETTINGS_TIME_LONG": "Longitudine", "SETTINGS_TIME_SUN_GET": "Ottieni coordinate", "SETTINGS_TIME_IDLE_FS_TITLE": "Le applicazioni a schermo intero bloccano il rilevamento inattività", "SETTINGS_TIME_IDLE_FS_DESC": "Le applicazioni a schermo intero bloccano il rilevamento dell'inattività. Questo vale solo per la finestra selezionata.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Quantità da scorrere", "SETTINGS_HOTKEY_VALUE": "Valore", "SETTINGS_HOTKEY_OFF_WARN": "Questa azione utilizzerà l'opzione selezionata per l'azione \"Spegni gli schermi\". Se invece si desidera spegnere schermi specifici, utilizzare la scorciatoia per l'azione \"Imposta\" o \"Scorri\".", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "I media bloccano il rilevamento inattività", "SETTINGS_PROFILES_APP_DESC": "Se si desidera che questo profilo si attivi automaticamente quando un'applicazione specifica è selezionata, inserire di seguito il percorso completo o parziale dell'EXE.", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Cerca sempre di far comparire l'overlay sopra le altre finestre. Questo può causare problemi con giochi esclusivi a schermo intero e altre applicazioni a schermo intero. Può anche attivare l'anti-cheat in alcuni giochi.", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Il rilevamento dell'inattività viene disattivato durante la riproduzione di qualsiasi media. Questo include sia contenuti video che audio. Questo vale solo quando Windows ne segnala la riproduzione.", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Inserisci un numero", "SETTINGS_HOTKEY_VALUES": "Valori", "SETTINGS_HOTKEY_ADD_VALUE": "Aggiungi valore", "SETTINGS_HOTKEY_ACTION": "Azione", "SETTINGS_HOTKEY_ACTION_SET": "Imposta valore", "SETTINGS_HOTKEY_ACTION_OFFSET": "Regola valore", "SETTINGS_HOTKEY_ACTION_CYCLE": "Scorri lista dei valori", "SETTINGS_PROFILES_TITLE": "Profili", "SETTINGS_PROFILES_DESC": "Regola automaticamente la luminosità o il comportamento dell'overlay delle scorciatoie in base all'applicazione selezionata. È inoltre possibile aggiungere profili al menù del tasto destro del mouse nella barra delle applicazioni per modificare rapidamente la luminosità in base a profili predefiniti.", "SETTINGS_PROFILES_ADD": "Nuovo profilo", "SETTINGS_PROFILES_NAME": "Nome profilo", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Imposta luminosità quando è attivo", "SETTINGS_PROFILES_SHOW_MENU": "Mostra nel menù contestuale della barra delle applicazioni", "SETTINGS_PROFILES_TRIGGER_TITLE": "Impostazioni di attivazione dell'app", "SETTINGS_PROFILES_APP_PATH": "Percorso app", "SETTINGS_PROFILES_OVERLAY_TITLE": "Imponi tipo di overlay", "SETTINGS_PROFILES_OVERLAY_DESC": "Modifica il comportamento dell'overlay delle scorciatoie quando l'applicazione specificata è selezionata. Questa funzione non funziona quando il profilo è attivato manualmente.", "SETTINGS_HOTKEY_TARGET": "Impostazione", "SETTINGS_FEATURES_POWER_WARNING": "È più probabile che l'opzione \"Sospensione\" consentirà di accendere e spegnere il monitor da Twinkle Tray. Tuttavia, molti monitor non rispondono correttamente al cambiamento di stato di alimentazione. Utilizzare a proprio rischio e pericolo.", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "Codice VCP (Es. 0x12)", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Luminosità SDR", "GENERIC_NOT_SUPPORTED": "Non supportato", "GENERIC_SUPPORTED": "Compatibile", "GENERIC_UNSUPPORTED": "Incompatibile", "GENERIC_ACTIVE": "Attivo", "GENERIC_DETECTING_DISPLAYS": "Rilevamento schermi…", "PANEL_LABEL_INPUTS": "Input", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Disabilita nel blocco schermo", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Non accedere ai monitor mentre la sessione utente è bloccata per evitare conflitti in ambienti multiutente.", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Stile interfaccia Windows", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Rilevamento modifica del tema", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Rileva modifiche al colore principale/sfondo/tema da Windows per aggiornare l'icona della barra delle applicazioni e l'effetto Mica. Disabilitare questa funzione potrebbe aiutare se un'applicazione di terze parti modifica spesso il tema, aumentando l'utilizzo della CPU.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Rilevamento dello stato di alimentazione del monitor", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Rileva modifiche allo stato di alimentazione dei monitor. Disabilitare questa funzione potrebbe aiutare se si verificano errori quando i monitor vengono spenti/accesi o sono inattivi. È necessario riavviare il sistema affinché le modifiche abbiano effetto.", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "Impostazioni schermi HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Abilita slider della luminosità SDR per monitor specifici. I monitor devono avere abilitato l'HDR su Windows per poter funzionare.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "L'SDR sostituisce lo slider primario", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Controlla la luminosità SDR dallo slider della luminosità principale quando l'HDR è attivo.", "SETTINGS_TIME_USE_SUN_POSITION": "Utilizza posizione del sole", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Inverti scrorrimento", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Inverti la direzione di scorrimento quando si scorre sull'icona nell'area delle notifiche.", "SETTINGS_HOTKEY_ADD_ACTION": "Aggiungi azione", "GENERIC_CALIBRATION_POINT": "Punto di calibrazione", "GENERIC_SLIDER_INDICATOR_TYPE": "Tipo indicatore slider", "GENERIC_ICON": "Icona", "GENERIC_TEXT": "Testo", "GENERIC_SLIDER_ICON": "Icona slider", "GENERIC_SLIDER_TEXT": "Testo slider", "GENERIC_SLIDER_NAME": "Inserisci un nome per lo slider", "SETTINGS_MONITORS_CALIBRATION_DESC": "Ogni schermo può avere dei punti di calibrazione specifici per compensare le differenze nella curva della luminosità. Il valore in ingresso è la luminosità indicata sullo slider, mentre il valore in uscita è l'effettiva luminosità applicata allo schermo.", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "Collegato alla luminosità", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "Lascia vuoto per il predefinito (0x10). Puoi trovare i codici supportati nella lista qui sotto.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "Se il tuo schermo usa un codice VCP non standard per la luminosità (come 0x13 o 0x6B), o se vuoi rimappare lo slider della luminosità a un altro codice VCP, puoi inserire quel codice qui sotto.", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Ferma dopo questo livello di luminosità" } ================================================ FILE: src/localization/ja.json ================================================ { "LANGUAGE": "日本語", "GENERIC_OK": "OK", "GENERIC_CANCEL": "キャンセル", "GENERIC_SAVE": "保存", "GENERIC_CLEAR": "消去", "GENERIC_OFF": "オフ", "GENERIC_ON": "オン", "GENERIC_QUIT": "終了", "GENERIC_CLOSE": "閉じる", "GENERIC_SETTINGS": "設定", "GENERIC_INSTALL": "インストール", "GENERIC_DISMISS": "非表示", "GENERIC_DISPLAY_SINGLE": "ディスプレイ", "GENERIC_ALL_DISPLAYS": "すべてのディスプレイ", "GENERIC_REFRESH_DISPLAYS": "ディスプレイを更新", "GENERIC_MINIMUM": "最小", "GENERIC_MAXIMUM": "最大", "GENERIC_NO_DISPLAYS": "ディスプレイを検出できません。パソコンにディスプレイを接続してください。", "GENERIC_NO_COMPATIBLE_DISPLAYS": "対応するディスプレイが見つかりません。お使いのディスプレイの DDC/CI 機能が有効か確認してください。", "GENERIC_NO_DISPLAYS_SHORT": "対応するディスプレイが検出されませんでした。", "GENERIC_SECONDS": "秒", "GENERIC_MINUTES": "分", "GENERIC_PAUSE_TOD": "時刻による調整を停止", "GENERIC_PAUSE_IDLE": "アイドル状態の検出を停止", "PANEL_TITLE": "明るさの調整", "PANEL_UPDATE_AVAILABLE": "最新版が利用できます", "PANEL_BUTTON_LINK_LEVELS": "すべて同時に設定", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "ディスプレイの電源を切る", "PANEL_LABEL_BRIGHTNESS": "明るさ", "PANEL_LABEL_CONTRAST": "コントラスト", "PANEL_LABEL_OFF_ON": "電源の状態", "PANEL_LABEL_COLOR_TEMPERATURE": "色温度", "PANEL_LABEL_VOLUME": "音量", "PANEL_LABEL_TURN_OFF": "電源を切る", "INTRO_TITLE": "ようこそ Twinkle Tray へ!", "INTRO_INSTRUCTIONS": "Twinkle Tray のアイコンはおそらく隠れています。利用しやすくするには以下の手順をご覧ください。", "SETTINGS_TITLE": "Twinkle Tray 設定", "SETTINGS_SIDEBAR_GENERAL": "一般", "SETTINGS_SIDEBAR_MONITORS": "ディスプレイの設定", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI 機能", "SETTINGS_SIDEBAR_TIME": "時間で調整", "SETTINGS_SIDEBAR_HOTKEYS": "ショートカットキーなど", "SETTINGS_SIDEBAR_UPDATES": "更新", "SETTINGS_GENERAL_TITLE": "一般", "SETTINGS_GENERAL_STARTUP": "起動時に実行", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "起動時に明るさを反映", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Twinkle Tray の起動時に、各ディスプレイの明るさへを最後の設定へと復元します。", "SETTINGS_GENERAL_THEME_TITLE": "テーマ", "SETTINGS_GENERAL_THEME_SYSTEM": "システムの設定 (既定)", "SETTINGS_GENERAL_THEME_DARK": "ダーク", "SETTINGS_GENERAL_THEME_LIGHT": "ライト", "SETTINGS_GENERAL_LANGUAGE_TITLE": "言語", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "システムの言語 (既定)", "SETTINGS_GENERAL_RESET_TITLE": "設定の初期化", "SETTINGS_GENERAL_RESET_DESC": "このボタンを押して設定を初期化します。", "SETTINGS_GENERAL_RESET_BUTTON": "設定の初期化", "SETTINGS_GENERAL_ACRYLIC_TITLE": "アクリル透かし", "SETTINGS_GENERAL_ACRYLIC_DESC": "Twinkle Tray の透過背景の透かし効果を切り替えます。", "SETTINGS_GENERAL_MICA_TITLE": "マイカ透かし", "SETTINGS_GENERAL_MICA_DESC": "Twinkle Tray の背景の透かし効果を切り替えます。", "SETTINGS_GENERAL_ANALYTICS_TITLE": "統計", "SETTINGS_GENERAL_ANALYTICS_DESC": "利用データを送信し Twinkle Tray の改良に協力します。個人情報は送信されません。{{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "詳細", "SETTINGS_GENERAL_SCROLL_TITLE": "トレイのアイコン上でスクロール", "SETTINGS_GENERAL_SCROLL_DESC": "トレイアイコン上でのスクロールで全ディスプレイの明るさを調整します。一部のタッチパッドでは動作しません。", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "トレイのアイコン", "SETTINGS_MONITORS_RATE_TITLE": "明るさの更新間隔", "SETTINGS_MONITORS_RATE_DESC": "明るさの値の調整時に、ディスプレイの明るさが更新される間隔です。画面がちらつく場合には増やしてください。", "SETTINGS_MONITORS_RATE_0": "非常に速い", "SETTINGS_MONITORS_RATE_1": "速い (250 ms)", "SETTINGS_MONITORS_RATE_2": "通常 (500 ms)", "SETTINGS_MONITORS_RATE_3": "遅い (1 秒)", "SETTINGS_MONITORS_RATE_4": "非常に遅い (2 秒)", "SETTINGS_MONITORS_RENAME_TITLE": "ディスプレイの名前の変更", "SETTINGS_MONITORS_RENAME_DESC": "それぞれのディスプレイを違う名前にします (例 「右のモニタ」「中央のモニタ」)。空にすると元の名前に戻ります。", "SETTINGS_MONITORS_ENTER_NAME": "名前を入力", "SETTINGS_MONITORS_REORDER_TITLE": "ディスプレイの順序", "SETTINGS_MONITORS_REORDER_DESC": "トレイにディスプレイが表示される順番を並び替え。変更するにはドラッグします。", "SETTINGS_MONITORS_NORMALIZE_TITLE": "明るさの標準化", "SETTINGS_MONITORS_NORMALIZE_DESC": "ディスプレイによって明るさの範囲が違うことがよくあります。ディスプレイごとに明るさの最小/最大値を制限することで、ディスプレイ同士の明るさの程度をより近いものにできます。似たようなディスプレイでは同じ設定にするといいでしょう。", "SETTINGS_MONITORS_DETAILS_NAME": "名前", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "内部名", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "通信方法", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "現在の明るさ", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "最大の明るさ", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "明るさの標準化", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "動作していない内蔵ディスプレイを非表示", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "カバーを閉じたり、Windowsで内蔵ディスプレイを無効にしている場合、パネル内のディスプレイの明るさ調整用スライダーを非表示にします。", "SETTINGS_FEATURES_DESCRIPTION": "明るさパネル内の個々の DDC/CI 機能を有効または無効にします。1つ以上の機能が有効であれば、ディスプレイが明るさパネルに表示されます。ノート/タブレットなど、すべてのディスプレイがこれらの機能に対応するわけではありません。", "SETTINGS_FEATURES_UNSUPPORTED": "このディスプレイは、DDC/CI 機能に対応していません。", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "現在の値を確認", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "明るさパネルを開いたら、ディスプレイから最新の値を取得します。Twinkle Tray の外部から頻繁に明るさ (やコントラストなどほかのVCPコード) が変更される場合にこの機能を有効にしてください。", "SETTINGS_TIME_TITLE": "時刻による調整", "SETTINGS_TIME_DESC": "希望の時刻に、ディスプレイを指定した明るさへと自動で設定します。すべてのディスプレイを同程度の明るさにします。", "SETTINGS_TIME_ADD": "時刻の追加", "SETTINGS_TIME_REMOVE": "時刻の削除", "SETTINGS_TIME_INDIVIDUAL_TITLE": "ディスプレイごとに明るさを設定", "SETTINGS_TIME_INDIVIDUAL_DESC": "すべてのディスプレイではなく、ディスプレイごとに明るさを設定します。", "SETTINGS_TIME_IDLE_TITLE": "アイドル状態の検出", "SETTINGS_TIME_IDLE_DESC": "一定時間の入力のない状態を検出すると、すべてのディスプレイの明るさを下げます。", "SETTINGS_TIME_STARTUP_TITLE": "起動時に確認", "SETTINGS_TIME_STARTUP_DESC": "Twinkle Tray の開始時に、一番近い時刻にあわせ明るさを調整します。", "SETTINGS_TIME_ANIMATE_TITLE": "時間での動的な変動", "SETTINGS_TIME_ANIMATE_DESC": "明るさの値は、現在と次回予定されたイベントとの間で動的になります。CPU使用率が増加するかもしれません。有効化した場合、手動での明るさ調整はすぐに上書きされます。", "SETTINGS_HOTKEYS_TITLE": "ショートカットキー", "SETTINGS_HOTKEYS_DESC": "個別またはすべてのディスプレイの明るさを調整するショートカットキー (ホットキー) を指定します。", "SETTINGS_HOTKEYS_ADD": "ショートカットキーの追加", "SETTINGS_HOTKEYS_REMOVE": "ショートカットキーの削除", "SETTINGS_HOTKEYS_INCREASE": "明るさを上げる", "SETTINGS_HOTKEYS_DECREASE": "明るさを下げる", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "ここでキーを入力", "SETTINGS_HOTKEYS_LEVEL_TITLE": "明るさ調整の程度", "SETTINGS_HOTKEYS_LEVEL_DESC": "ショートカットキー使用時にどのくらい明るさを調整するか。", "SETTINGS_HOTKEYS_TOD_TITLE": "ディスプレイの電源を切る際の動作", "SETTINGS_HOTKEYS_TOD_DESC": "「ディスプレイの電源を切る」のショートカットキーやアイコンを押した際に、送信される信号を選択できます。ソフトウェア信号では、Windows が入力 (マウス・キーボードなど) を検出するまでの間、黒い画面となります。ハードウェア信号は、ディスプレイの電源を切ります。", "SETTINGS_HOTKEYS_TOD_NONE": "なし (アイコンなし)", "SETTINGS_HOTKEYS_TOD_SOFT": "ソフトウェア信号 (標準)", "SETTINGS_HOTKEYS_TOD_HARD": "ハードウェア*信号 (DDC/CI でのみ)", "SETTINGS_HOTKEYS_TOD_BOTH": "ハードウェア*とソフトウェア信号", "SETTINGS_HOTKEYS_TOD_NOTE": "* 注: DDC/CI ディスプレイの一部はこの機能に対応しません。", "SETTINGS_HOTKEYS_BREAK_TITLE": "ショートカットキーでは同時設定しない", "SETTINGS_HOTKEYS_BREAK_DESC": "個別のディスプレイ用のショートカットキーを使用し、「すべて同時に設定」が有効の場合にこれを無効化します。", "SETTINGS_UPDATES_TITLE": "更新", "SETTINGS_UPDATES_VERSION": "Twinkle Tray {{1}} を利用中。", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "自動で最新版を確認", "SETTINGS_UPDATES_AUTOMATIC_DESC": "最新版があれば明るさパネルから通知します。", "SETTINGS_UPDATES_MS_STORE": "最新版の確認には Microsoft Store アプリにアクセスしてください。", "SETTINGS_UPDATES_AVAILABLE": "Twinkle Tray の最新版が利用できます!", "SETTINGS_UPDATES_NONE_AVAILABLE": "更新なし。以下は現在お使いのバージョンの更新履歴です。", "SETTINGS_UPDATES_DOWNLOADING": "更新をダウンロード中…", "SETTINGS_UPDATES_DOWNLOAD": "ダウンロード & インストール {{1}}", "SETTINGS_UPDATES_CHANNEL": "更新する種類", "SETTINGS_UPDATES_BRANCH_STABLE": "安定版 (既定)", "SETTINGS_UPDATES_BRANCH_BETA": "ベータ版", "SETTINGS_MONITORS_FEATURES_DESCRIPTION": "明るさパネル内の特定の DDC/CI 機能を有効または無効にします。明るさパネル内でモニターを設定可能にするには少なくとも1つを有効にする必要があります。ノート/タブレットなど、すべてのモニターでこうした機能に対応するわけではありません。", "SETTINGS_MONITORS_FEATURES_TITLE": "DDC/CI 機能", "GENERIC_DDC_WARNING": "電源状態の制御などの DDC/CI 機能により、ディスプレイが応答しなくなることがあります。ご自身の責任でご利用ください。", "GENERIC_SPEED_INSTANT": "瞬時", "GENERIC_SPEED_SLOW": "遅い", "GENERIC_SPEED_VERY_SLOW": "とても遅い", "GENERIC_SPEED_NORMAL": "通常", "GENERIC_SPEED_FAST": "速い", "GENERIC_SPEED_VERY_FAST": "とても速い", "SETTINGS_GENERAL_TROUBLESHOOTING": "トラブルシューティング", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "ディスプレイ検出方法の有効化", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "トレイアイコンをクリックしても反応しない、またはディスプレイが検出されない場合は、ディスプレイ検出方法のどれかを無効にしてみてください。変更を有効にするには、Twinkle Tray を再起動してください。{{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "オーバーレイを無効化", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Twinkle Tray のショートカットキーによるオーバーレイ表示が全画面表示のアプリと干渉する際は、ここで無効にできます。", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "ディスプレイを非表示", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "特定のディスプレイをメニューから非表示にしたければ、ここで無効にできます。", "SETTINGS_TIME_TRANSITON_TITLE": "明るさの遷移速度", "SETTINGS_TIME_TRANSITON_DESC": "時刻による調整が行われるときに、明るさを変化させる速さ。", "SETTINGS_FEATURES_POWER_OFF": "電源を切る", "GENERIC_DELETE": "削除", "PANEL_LABEL_TURN_ON": "電源オン", "SETTINGS_GENERAL_OVERLAY_TITLE": "オーバーレイの標準動作", "GENERIC_OPTIONAL": "オプション", "GENERIC_DEFAULT": "標準", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "以前の DDI/CI 検出方法", "SETTINGS_GENERAL_OVERLAY_DESC": "ショートカットキーによる明るさのオーバーレイを他のアプリに強制的に表示する方法。調整する必要はありません。", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "高い互換性", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "オーバーレイは、常にほかのウィンドウに適用されます。全画面専用のゲームや他の全画面アプリの問題になることがあります。ゲームによっては不正防止機構が発動します。", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "強制", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "ディスプレイの電源の入り切りや、ハードウェアの接続/切断後に、ディスプレイの反応がおかしい場合、無効にすると解決することもあります。", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "特定のディスプレイに自動適用しない", "SETTINGS_FEATURES_POWER_TITLE": "電源状態の信号", "SETTINGS_FEATURES_POWER_STANDBY": "スタンバイ", "SETTINGS_PROFILES_APP_PATH": "アプリのパス", "SETTINGS_GENERAL_REPORT_DESC": "デバッグ用にディスプレイや設定の情報をテキストファイルに保存します。", "SETTINGS_GENERAL_REPORT_TITLE": "バグ報告を生成", "SETTINGS_FEATURES_POWER_COMPAT": "高い互換性", "SETTINGS_TIME_SUN_TITLE": "太陽の位置の座標", "SETTINGS_TIME_LAT": "緯度", "SETTINGS_TIME_LONG": "経度", "SETTINGS_TIME_SUN_GET": "座標を取得", "SETTINGS_TIME_SUN_DESC": "「太陽の位置」を使って時刻に従い調整するには、現在の緯度と経度を入力し正確な時間になるようにします。", "SETTINGS_TIME_IDLE_FS_DESC": "全画面アプリでのアイドルの検出をしないようにします。焦点があたっているウィンドウにのみ適用されます。", "SETTINGS_TIME_IDLE_FS_TITLE": "全画面アプリをアイドル状態にしない", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "スクロールする量", "SETTINGS_FEATURES_ADD_VCP": "VCPコード", "SETTINGS_HOTKEY_ACTION": "操作", "SETTINGS_HOTKEY_TARGET": "操作の対象", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "数字を入力", "SETTINGS_HOTKEY_ADD_VALUE": "値を追加", "SETTINGS_HOTKEY_ACTION_SET": "値を設定", "SETTINGS_HOTKEY_ACTION_OFFSET": "値を調整", "SETTINGS_HOTKEY_ACTION_CYCLE": "値の一覧を循環", "SETTINGS_PROFILES_TITLE": "プロファイル", "SETTINGS_PROFILES_ADD": "新しいプロファイル", "SETTINGS_PROFILES_NAME": "プロファイル名", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "有効時に明るさを設定", "SETTINGS_PROFILES_SHOW_MENU": "トレイの右クリックメニュー内に表示", "SETTINGS_PROFILES_OVERLAY_TITLE": "オーバーレイの方法を上書き", "SETTINGS_PROFILES_OVERLAY_DESC": "指定したアプリに焦点が当たった時の、ショートカットキーによるオーバーレイの動作を変更。この機能は、手動でプロファイルを有効にした時には動作しません。", "SETTINGS_PROFILES_TRIGGER_TITLE": "アプリごとに発動", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "以前のv1.15.5の方法で DDC/CI ディスプレイを検出。", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "オーバーレイは、ほとんどのウィンドウ上に表示されるが、「常に手間に表示」のアプリには強制表示されません。", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "明るさの自動適用", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "特定のディスプレイで、すべてのハードウェア/電源イベント後の、最後の明るさを自動適用しない。アイドル検出機能も含みます。", "SETTINGS_FEATURES_POWER_DESC": "ディスプレイの電源を切る際に、DDC/CI コマンドで次の値を送信します。", "SETTINGS_FEATURES_POWER_WARNING": "「スタンバイ」を選べば、Twinkle Tray からディスプレイの電源オン/オフを切り替える可能性が高いです。しかし、多くのディスプレイは電源状態の変更に正しく反応しません。自己責任でご利用ください。", "SETTINGS_PROFILES_APP_DESC": "特定のアプリに焦点を当てた時にこのプロファイルを自動で有効にしたいなら、ここにその実行ファイル (exe) の完全なパスかパスの一部を入力してください。", "SETTINGS_HOTKEY_VALUE": "値", "SETTINGS_HOTKEY_VALUES": "値", "SETTINGS_HOTKEY_OFF_WARN": "これは「ディスプレイの電源を切る際の動作」の設定を使います。特定のディスプレイの電源を切るには、「設定」や「循環」の操作をご利用ください。", "SETTINGS_FEATURES_ADD": "機能追加", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP コード (例 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "この機能はすでに有効になっています。", "SETTINGS_FEATURES_VCP_LIST_TITLE": "このディスプレイが報告したすべてのVCPコード", "SETTINGS_FEATURES_ADD_DESC": "ディスプレイに追加したい機能に対応したVCPコードを入力してください。お使いのディスプレイが本当にそのVCPコードに対応するかは、TwinkleTrayからは分かりません。自己責任でご利用ください。", "SETTINGS_FEATURES_VCP_LIST_DESC": "このディスプレイが Windows に報告した、利用できるVCPコードの一覧です。Twinkle Tray は、このVCPコードの機能性や安定性を検証していません。自己責任でご利用ください。", "SETTINGS_FEATURES_VCP_EXPECTED": "期待する値", "SETTINGS_PROFILES_DESC": "焦点が当たっているアプリによって、明るさやショートカットキーによるオーバーレイの動作を自動的に調整します。また、システムトレイでの右クリックメニューにプロファイルを追加し、定義したプロファイルの明るさへ簡単に変更します。", "SETTINGS_TIME_IDLE_MEDIA_DESC": "メディアの再生中はアイドル状態を検出しません。これは動画と音楽の両方です。メディアの再生中だとWindowsが報告する際にのみ適用されます。", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "メディア再生時にアイドル検出しない", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "タスクトレイのアイコン上でスクロールする際のスクロール方向が逆になります。", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "スクロール方向を逆に", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "ユーザーのセッションがロックされている間はスクリーンにアクセスしない。複数ユーザーでの競合を回避します。", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "ロック画面では無効化", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR対応モニタの設定", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "特定のモニターでSDRの明るさスライダーを有効にします。動作には、WindowsでHDRを有効にする必要があります。", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "HDRが有効なら、メインの明るさスライダーからSDRの明るさを調整します。", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "メインのスライダーからSDRを調整", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDRの明るさ" } ================================================ FILE: src/localization/ko.json ================================================ { "LANGUAGE": "한국어", "GENERIC_OK": "확인", "GENERIC_CANCEL": "취소", "GENERIC_SAVE": "저장", "GENERIC_CLEAR": "지우기", "GENERIC_OFF": "끔", "GENERIC_ON": "켬", "GENERIC_QUIT": "종료", "GENERIC_CLOSE": "닫기", "GENERIC_SETTINGS": "설정", "GENERIC_INSTALL": "설치", "GENERIC_DISMISS": "해제", "GENERIC_DISPLAY_SINGLE": "디스플레이", "GENERIC_ALL_DISPLAYS": "모든 디스플레이", "GENERIC_REFRESH_DISPLAYS": "디스플레이 새로 고침", "GENERIC_MINIMUM": "최소값", "GENERIC_MAXIMUM": "최대값", "GENERIC_NO_DISPLAYS": "감지된 디스플레이가 없습니다. 디스플레이를 PC에 연결하세요.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "호환되는 디스플레이를 찾을 수 없습니다. 디스플레이에 \"DDC/CI\"가 활성화되어 있는지 확인하세요.", "GENERIC_NO_DISPLAYS_SHORT": "호환되는 디스플레이가 감지되지 않았습니다.", "GENERIC_SECONDS": "초", "GENERIC_MINUTES": "분", "GENERIC_DDC_WARNING": "DDC/CI 기능으로 인해 모니터가 응답하지 않을 수 있습니다. 위험을 감수하고 사용하세요.", "GENERIC_SPEED_INSTANT": "즉시", "GENERIC_SPEED_SLOW": "느림", "GENERIC_SPEED_VERY_SLOW": "매우 느림", "GENERIC_SPEED_NORMAL": "보통", "GENERIC_SPEED_FAST": "빠름", "GENERIC_SPEED_VERY_FAST": "매우 빠름", "GENERIC_PAUSE_TOD": "시간 조정 일시 중지", "GENERIC_PAUSE_IDLE": "유휴 탐지 일시 중지", "PANEL_TITLE": "밝기 조정", "PANEL_UPDATE_AVAILABLE": "새 버전 사용 가능", "PANEL_BUTTON_LINK_LEVELS": "연결 수준", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "디스플레이 끄기", "PANEL_LABEL_BRIGHTNESS": "밝기", "PANEL_LABEL_CONTRAST": "대비", "PANEL_LABEL_OFF_ON": "전원 상태", "PANEL_LABEL_COLOR_TEMPERATURE": "색 온도", "PANEL_LABEL_VOLUME": "볼륨", "PANEL_LABEL_TURN_OFF": "전원 끄기", "INTRO_TITLE": "안녕하세요, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Twinkle Tray의 트레이 아이콘이 숨겨져 있을 수 있으므로 쉽게 접근할 수 있는 곳으로 이동해야 합니다. 자세한 내용은 아래를 참조하세요.", "SETTINGS_TITLE": "Twinkle Tray 설정", "SETTINGS_SIDEBAR_GENERAL": "일반", "SETTINGS_SIDEBAR_MONITORS": "모니터 설정", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI 기능", "SETTINGS_SIDEBAR_TIME": "시간 조정", "SETTINGS_SIDEBAR_HOTKEYS": "단축키 및 바로 가기", "SETTINGS_SIDEBAR_UPDATES": "업데이트", "SETTINGS_GENERAL_TITLE": "일반", "SETTINGS_GENERAL_STARTUP": "시작 시 실행", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "시작 시 밝기 적용", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Twinkle Tray가 시작될 때 각 디스플레이의 마지막으로 알려진 밝기를 복원합니다.", "SETTINGS_GENERAL_THEME_TITLE": "테마", "SETTINGS_GENERAL_THEME_SYSTEM": "시스템 기본 설정 (기본값)", "SETTINGS_GENERAL_THEME_DARK": "어두운", "SETTINGS_GENERAL_THEME_LIGHT": "밝은", "SETTINGS_GENERAL_LANGUAGE_TITLE": "언어", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "시스템 언어 (기본값)", "SETTINGS_GENERAL_RESET_TITLE": "설정 초기화", "SETTINGS_GENERAL_RESET_DESC": "구성을 지우려면 이 버튼을 누르세요.", "SETTINGS_GENERAL_RESET_BUTTON": "설정 초기화", "SETTINGS_GENERAL_ACRYLIC_TITLE": "아크릴 흐림", "SETTINGS_GENERAL_ACRYLIC_DESC": "Twinkle Tray에서 투명한 배경 뒤의 흐림을 활성화하거나 비활성화합니다.", "SETTINGS_GENERAL_MICA_TITLE": "운모 흐림", "SETTINGS_GENERAL_MICA_DESC": "Twinkle Tray에서 배경 뒤의 흐림을 활성화하거나 비활성화합니다.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "분석 정보", "SETTINGS_GENERAL_ANALYTICS_DESC": "사용 데이터를 전송하여 Twinkle Tray를 개선합니다. 개인 정보가 전송되지 않습니다. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "더 알아보기", "SETTINGS_GENERAL_SCROLL_TITLE": "트레이 아이콘 스크롤 바로 가기", "SETTINGS_GENERAL_SCROLL_DESC": "시스템 트레이 아이콘 위로 스크롤하여 모든 디스플레이의 밝기를 한 번에 조정합니다. 일부 트랙패드에서는 작동하지 않습니다.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "트레이 아이콘", "SETTINGS_GENERAL_TROUBLESHOOTING": "문제 해결", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "활성화된 모니터 감지 방법", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "트레이 아이콘을 클릭할 때 Twinkle Tray가 응답하지 않거나 디스플레이를 감지하지 못하는 경우 특정 모니터 감지 방법을 비활성화할 수 있습니다. 변경 내용을 적용하려면 Twinkle Tray를 다시 시작하세요. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "오버레이 사용 안 함", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Twinkle Tray의 단축키 오버레이가 전체 화면 응용 프로그램과 간섭하는 경우 여기에서 비활성화할 수 있습니다.", "SETTINGS_MONITORS_RATE_TITLE": "밝기 업데이트 빈도", "SETTINGS_MONITORS_RATE_DESC": "값을 조정할 때 디스플레이의 밝기가 업데이트되는 빈도입니다. 디스플레이가 깜박이는 경우 시간을 늘립니다.", "SETTINGS_MONITORS_RATE_0": "아주 빠름", "SETTINGS_MONITORS_RATE_1": "빠름 (250 ms)", "SETTINGS_MONITORS_RATE_2": "보통 (500 ms)", "SETTINGS_MONITORS_RATE_3": "느림 (1초)", "SETTINGS_MONITORS_RATE_4": "매우 느림 (2초)", "SETTINGS_MONITORS_RENAME_TITLE": "모니터 이름 바꾸기", "SETTINGS_MONITORS_RENAME_DESC": "각 모니터에 대해 다른 이름 (예: \"왼쪽 모니터\", \"중간 모니터\")을 원하는 경우 아래에 해당 이름을 입력할 수 있습니다. 필드를 비워 두면 원래 이름이 복원됩니다.", "SETTINGS_MONITORS_ENTER_NAME": "이름 입력", "SETTINGS_MONITORS_REORDER_TITLE": "모니터 순서 변경", "SETTINGS_MONITORS_REORDER_DESC": "트레이에 모니터가 표시되는 순서를 변경합니다. 변경하려면 클릭해서 끌어서 놓습니다.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "밝기 정규화", "SETTINGS_MONITORS_NORMALIZE_DESC": "모니터는 종종 밝기 범위가 다릅니다. 디스플레이당 최소/최대 밝기를 제한함으로써 디스플레이 간 밝기 수준이 훨씬 더 일관성 있게 유지됩니다.", "SETTINGS_MONITORS_DETAILS_NAME": "이름", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "내부 이름", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "통신 방법", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "현재 밝기", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "최대 밝기", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "밝기 정규화", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "비활성 내부 디스플레이 숨기기", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Windows에서 덮개가 닫히거나 내부 디스플레이가 비활성화된 경우 패널에서 밝기 슬라이더를 숨깁니다.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "디스플레이 숨기기", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "특정 디스플레이를 플라이아웃에서 숨기려면 여기서 끌 수 있습니다.", "SETTINGS_FEATURES_DESCRIPTION": "밝기 패널에서 특정 DDC/CI 기능을 활성화하거나 비활성화합니다. 모니터가 밝기 패널에 나타나려면 하나 이상의 기능이 활성화되어 있어야 합니다. 랩탑/태블릿 디스플레이와 같은 일부 디스플레이는 이러한 기능을 지원하지 않습니다.", "SETTINGS_FEATURES_UNSUPPORTED": "이 모니터는 DDC/CI 기능을 지원하지 않습니다.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "현재 값 확인", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "밝기 패널을 열 때 항상 모니터에서 최신 값을 가져옵니다. 밝기 (또는 명암비와 같은 기타 VCP 코드)가 Twinkle Tray 외부에서 자주 변경되는 경우 이 기능을 활성화합니다.", "SETTINGS_TIME_TITLE": "시간 조정", "SETTINGS_TIME_DESC": "원하는 시간에 모니터를 특정 밝기 수준으로 자동 설정합니다. 모든 모니터가 동일한 정규화된 수준으로 설정됩니다.", "SETTINGS_TIME_ADD": "시간 추가", "SETTINGS_TIME_REMOVE": "시간 제거", "SETTINGS_TIME_INDIVIDUAL_TITLE": "개별 디스플레이의 밝기 설정", "SETTINGS_TIME_INDIVIDUAL_DESC": "한 번에 모든 디스플레이 대신 디스플레이당 밝기를 구성합니다.", "SETTINGS_TIME_TRANSITON_TITLE": "밝기 전환 속도", "SETTINGS_TIME_TRANSITON_DESC": "시간 조정이 활성화될 때 밝기가 얼마나 빨리 전환되어야 하는지 설정합니다.", "SETTINGS_TIME_STARTUP_TITLE": "앱 시작 시 확인", "SETTINGS_TIME_STARTUP_DESC": "Twinkle Tray가 시작될 때 가장 관련성이 높은 시간에 맞게 밝기를 조정합니다.", "SETTINGS_TIME_IDLE_TITLE": "유휴 감지", "SETTINGS_TIME_IDLE_DESC": "일정 시간 동안 아무런 입력도 감지되지 않으면 모든 디스플레이의 밝기가 감소합니다.", "SETTINGS_TIME_ANIMATE_TITLE": "애니메이션 간격 시간", "SETTINGS_TIME_ANIMATE_DESC": "밝기 값은 현재 예약된 이벤트와 다음 예약된 이벤트 사이에 애니메이션됩니다. CPU 사용량이 증가할 수 있습니다. 수동 밝기 조정은 활성 상태에서 빠르게 덮어씁니다.", "SETTINGS_HOTKEYS_TITLE": "단축키", "SETTINGS_HOTKEYS_DESC": "하나 또는 모든 디스플레이의 밝기를 조정하도록 단축키를 구성합니다.", "SETTINGS_HOTKEYS_ADD": "단축키 추가", "SETTINGS_HOTKEYS_REMOVE": "단축키 제거", "SETTINGS_HOTKEYS_INCREASE": "밝기 증가", "SETTINGS_HOTKEYS_DECREASE": "밝기 감소", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "여기서 키 누르기", "SETTINGS_HOTKEYS_LEVEL_TITLE": "밝기 수준 조정", "SETTINGS_HOTKEYS_LEVEL_DESC": "단축키를 사용할 때 조정해야 하는 밝기입니다.", "SETTINGS_HOTKEYS_TOD_TITLE": "디스플레이 끄기 작업", "SETTINGS_HOTKEYS_TOD_DESC": "디스플레이 끄기 단축키 또는 아이콘을 사용할 때 전송되는 신호를 사용자 지정합니다. Windows에서 입력 (예: 마우스 또는 키보드)이 감지될 때까지 소프트웨어 신호에 검은색 화면이 표시됩니다. 하드웨어 신호가 모니터의 전원을 끕니다.", "SETTINGS_HOTKEYS_TOD_NONE": "없음 (아이콘 숨기기)", "SETTINGS_HOTKEYS_TOD_SOFT": "소프트웨어 신호 (기본값)", "SETTINGS_HOTKEYS_TOD_HARD": "하드웨어* 신호 (DDC/CI만 해당)", "SETTINGS_HOTKEYS_TOD_BOTH": "하드웨어* 및 소프트웨어 신호", "SETTINGS_HOTKEYS_TOD_NOTE": "*참고: 일부 DDC/CI 모니터는 이 기능을 지원하지 않습니다.", "SETTINGS_HOTKEYS_BREAK_TITLE": "단축키가 연결된 수준 끊기", "SETTINGS_HOTKEYS_BREAK_DESC": "단일 디스플레이에 바로 가기 키를 사용하고 \"연결된 수준\"이 활성화되면 비활성화됩니다.", "SETTINGS_UPDATES_TITLE": "업데이트", "SETTINGS_UPDATES_VERSION": "Twinkle Tray {{1}}을(를) 사용 중입니다.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "자동으로 새 버전 확인", "SETTINGS_UPDATES_AUTOMATIC_DESC": "새 버전이 있으면 밝기 패널에 표시됩니다.", "SETTINGS_UPDATES_MS_STORE": "새 버전을 확인하려면 Microsoft Store 앱을 방문하세요.", "SETTINGS_UPDATES_AVAILABLE": "새로운 버전의 Twinkle Tray를 사용할 수 있습니다!", "SETTINGS_UPDATES_NONE_AVAILABLE": "최신 버전입니다. 현재 버전에는 다음과 같은 변경 사항이 포함되어 있습니다:", "SETTINGS_UPDATES_DOWNLOADING": "업데이트를 다운로드하는 중…", "SETTINGS_UPDATES_DOWNLOAD": "{{1}} 다운로드 및 설치", "SETTINGS_UPDATES_CHANNEL": "채널 업데이트", "SETTINGS_UPDATES_BRANCH_STABLE": "안정 (기본값)", "SETTINGS_UPDATES_BRANCH_BETA": "베타", "SETTINGS_FEATURES_POWER_OFF": "전원 끄기", "GENERIC_DELETE": "삭제", "GENERIC_DEFAULT": "기본값", "GENERIC_OPTIONAL": "선택사항", "PANEL_LABEL_TURN_ON": "전원 켜기", "SETTINGS_GENERAL_OVERLAY_TITLE": "기본 오버레이 동작", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "가장 호환성이 높음", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "오버레이는 대부분의 창에 표시되지만 \"항상 맨 위에\" 표시된 앱 위에는 강제로 표시되지 않습니다.", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "강제 적용", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "항상 다른 창 위에 오버레이를 표시하려고 합니다. 이로 인해 독점 전체 화면 게임 및 기타 전체 화면 앱에 문제가 발생할 수 있습니다. 또한 일부 게임에서는 부정행위 방지 기능을 트리거할 수도 있습니다.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "기존 DDC/CI 감지 방법", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "이전 v1.15.5 방식의 DDC/CI 디스플레이 감지 방법을 사용합니다.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "자동 적용 밝기", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "특정 모니터에 자동 적용 건너뛰기", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "특정 모니터의 모든 하드웨어/전원 이벤트 후 알려진 밝기 자동 적용을 비활성화합니다. 여기에는 유휴 감지 기능이 포함됩니다.", "SETTINGS_HOTKEY_VALUE": "값", "SETTINGS_GENERAL_REPORT_TITLE": "보고서 생성", "SETTINGS_FEATURES_POWER_TITLE": "전원 상태 신호", "SETTINGS_FEATURES_POWER_STANDBY": "대기", "SETTINGS_FEATURES_POWER_COMPAT": "가장 호환성이 높음", "SETTINGS_FEATURES_ADD": "기능 추가", "SETTINGS_FEATURES_ADD_DESC": "디스플레이에 추가하려는 기능의 VCP 코드를 입력합니다. Twinkle Tray는 디스플레이가 실제로 이 VCP 코드를 지원하는지 확인하지 않습니다. 위험을 감수하고 사용하세요.", "SETTINGS_FEATURES_ADD_VCP": "VCP 코드", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP 코드 (Ex. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "이 기능은 이미 활성화되어 있습니다.", "SETTINGS_FEATURES_VCP_EXPECTED": "기대값", "SETTINGS_TIME_SUN_GET": "좌표 가져오기", "SETTINGS_TIME_IDLE_FS_DESC": "전체 화면 앱은 유휴 감지를 차단합니다. 이는 포커스 창에만 적용됩니다.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "스크롤할 양", "SETTINGS_HOTKEY_TARGET": "동작 대상", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "숫자 입력", "SETTINGS_HOTKEY_VALUES": "값", "SETTINGS_HOTKEY_ADD_VALUE": "값 추가", "SETTINGS_HOTKEY_ACTION": "동작", "SETTINGS_HOTKEY_ACTION_SET": "값 설정", "SETTINGS_HOTKEY_ACTION_OFFSET": "값 조정", "SETTINGS_HOTKEY_ACTION_CYCLE": "값 주기 목록", "SETTINGS_PROFILES_TITLE": "프로필", "SETTINGS_PROFILES_ADD": "새 프로필", "SETTINGS_PROFILES_NAME": "프로필 이름", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "활성 상태일 때 밝기 설정", "SETTINGS_PROFILES_SHOW_MENU": "마우스 오른쪽 버튼 트레이 메뉴에 표시", "SETTINGS_PROFILES_TRIGGER_TITLE": "앱 트리거 설정", "SETTINGS_PROFILES_APP_PATH": "앱 경로", "SETTINGS_PROFILES_OVERLAY_TITLE": "오버레이 유형 재정의", "SETTINGS_TIME_IDLE_FS_TITLE": "전체 화면 앱은 유휴 상태 감지 차단", "SETTINGS_GENERAL_OVERLAY_DESC": "밝기 단축키 오버레이가 다른 앱에 얼마나 강력하게 표시되는지. 이를 조정할 필요는 없습니다.", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "모니터를 껐다/켜거나 하드웨어를 분리/연결한 후 모니터가 이상하게 반응한다면, 이 기능을 비활성화하면 도움이 될 수 있습니다.", "SETTINGS_TIME_LONG": "경도", "SETTINGS_FEATURES_POWER_DESC": "디스플레이를 끄라는 DDC/CI 명령을 전송하면 다음 값이 전송됩니다.", "SETTINGS_FEATURES_POWER_WARNING": "\"대기\" 옵션을 사용하면 Twinkle 트레이에서 모니터를 켜거나 끌 수 있습니다. 그러나 많은 모니터가 전원 상태 변경에 올바르게 반응하지 않습니다. 위험을 감수하고 사용하세요.", "SETTINGS_GENERAL_REPORT_DESC": "디버깅할 모니터 및 설정에 대한 정보가 포함된 텍스트 파일을 저장합니다.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "이 디스플레이에서 보고된 모든 VCP 코드", "SETTINGS_FEATURES_VCP_LIST_DESC": "다음은 이 디스플레이가 Windows에 보고한 사용 가능한 VCP 코드 목록입니다. Twinkle Tray는 이러한 VCP 코드의 기능이나 안정성을 검증하지 않습니다. 위험을 감수하고 사용하세요.", "SETTINGS_TIME_SUN_TITLE": "태양 위치 좌표", "SETTINGS_TIME_LAT": "위도", "SETTINGS_TIME_SUN_DESC": "시간 조정에 \"태양 위치\"를 사용하려면 현재 위도와 경도를 입력하여 올바른 시간을 확인할 수 있습니다.", "SETTINGS_HOTKEY_OFF_WARN": "이 작업은 \"디스플레이 끄기 작업\"에서 선택한 옵션을 사용합니다. 대신 특정 디스플레이를 끄려면 \"설정\" 또는 \"주기\" 단축키 작업을 대신 사용합니다.", "SETTINGS_PROFILES_DESC": "초점을 맞춘 앱에 따라 밝기 또는 바로 가기 오버레이 동작을 자동으로 조정합니다. 또한 시스템 트레이의 마우스 오른쪽 버튼 메뉴에 프로필을 추가하여 밝기를 미리 정의된 프로필로 빠르게 변경할 수도 있습니다.", "SETTINGS_PROFILES_OVERLAY_DESC": "지정한 앱이 포커스를 맞출 때 단축키 오버레이의 동작을 변경합니다. 프로필을 수동으로 활성화하면 이 기능이 작동하지 않습니다.", "SETTINGS_PROFILES_APP_DESC": "특정 앱에 포커스가 맞춰졌을 때 이 프로필이 자동으로 활성화되도록 하려면 아래에 EXE의 전체 또는 부분 경로를 입력하세요.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "미디어 차단 유휴 감지", "SETTINGS_TIME_IDLE_MEDIA_DESC": "미디어가 재생되는 동안 유휴 감지가 비활성화됩니다. 여기에는 비디오와 오디오가 모두 포함됩니다. 이는 Windows에서 미디어가 재생 중이라고 보고할 때만 적용됩니다.", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "시스템 트레이 아이콘을 스크롤할 때 스크롤 방향이 반대로 바뀝니다.", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "스크롤 반전", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "잠금 화면에서 사용 안 함", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "다중 사용자 환경에서 충돌을 방지하기 위해 사용자 세션이 잠겨 있는 동안 모니터에 접근하지 않습니다.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR 디스플레이 설정", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "특정 모니터에서 SDR 밝기 슬라이더를 활성화합니다. 이것을 사용하기 위해서는 Windows에서 모니터의 HDR이 활성화되어 있어야 합니다.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR이 기본 슬라이더를 대체", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "HDR이 활성화되어 있는 동안 기본 밝기 슬라이더에서 SDR 밝기를 제어합니다.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR 밝기", "GENERIC_CALIBRATION_POINT": "보정 지점", "GENERIC_NOT_SUPPORTED": "지원되지 않음", "GENERIC_SUPPORTED": "지원됨", "GENERIC_UNSUPPORTED": "지원되지 않음", "GENERIC_ACTIVE": "활동", "GENERIC_DETECTING_DISPLAYS": "디스플레이 감지 중…", "GENERIC_SLIDER_INDICATOR_TYPE": "슬라이더 표시기 유형", "GENERIC_ICON": "아이콘", "GENERIC_TEXT": "텍스트", "GENERIC_SLIDER_ICON": "슬라이더 아이콘", "GENERIC_SLIDER_TEXT": "슬라이더 텍스트", "GENERIC_SLIDER_NAME": "슬라이더 이름 입력", "PANEL_LABEL_INPUTS": "입력", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Windows UI 스타일", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "테마 업데이트 감지", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Windows에서 액센트/배경 화면/테마 변경을 감지하여 트레이 아이콘과 미카 효과를 업데이트합니다. 타사 앱이 테마를 자주 변경하여 CPU 사용량이 증가하는 경우 이 기능을 비활성화하면 도움이 될 수 있습니다.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "전원 상태 감지 모니터링", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "모니터의 전원 상태 변경을 감지합니다. 모니터가 꺼지거나 유휴 상태일 때 오류가 발생하는 경우 이 기능을 비활성화하면 도움이 될 수 있습니다. 이 기능을 적용하려면 재시작이 필요합니다.", "SETTINGS_MONITORS_CALIBRATION_DESC": "각 모니터에는 밝기 곡선의 차이를 보정하기 위해 개별 보정 지점을 추가할 수 있습니다. 입력 값은 슬라이더에 표시된 밝기 수준이고 출력 값은 모니터에 적용된 실제 밝기 수준입니다.", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "밝기와 관련됨", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "이 밝기 수준 이후에는 중지", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "모니터가 밝기를 위해 비표준 VCP 코드 (예: 0x13 또는 0x6B)를 사용하거나 밝기 슬라이더를 다른 VCP 코드로 다시 매핑하려면 아래에 해당 코드를 입력할 수 있습니다.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "기본값 (0x10)은 비워 둡니다. 아래 목록에서 지원되는 코드를 찾습니다.", "SETTINGS_TIME_USE_SUN_POSITION": "태양 위치 사용", "SETTINGS_HOTKEY_ADD_ACTION": "작업 추가" } ================================================ FILE: src/localization/lt.json ================================================ { "LANGUAGE": "Lietuvių", "GENERIC_OK": "Gerai", "GENERIC_CANCEL": "Atšaukti", "GENERIC_SAVE": "Išsaugoti", "GENERIC_CLEAR": "Išvalyti", "GENERIC_OFF": "Išjungta/-s", "GENERIC_ON": "Įjungta/-s", "GENERIC_QUIT": "Išeiti", "GENERIC_CLOSE": "Uždaryti", "GENERIC_SETTINGS": "Nustatymai", "GENERIC_INSTALL": "Įdiegti", "GENERIC_DISMISS": "Atmesti", "GENERIC_DISPLAY_SINGLE": "Ekranas", "GENERIC_ALL_DISPLAYS": "Visi ekranai", "GENERIC_REFRESH_DISPLAYS": "Atšviežinti ekranus", "GENERIC_MINIMUM": "Min.", "GENERIC_MAXIMUM": "Maks.", "GENERIC_NO_DISPLAYS": "Nėra aptiktų ekranų. Prašome prijungti ekraną prie savo asmeninio kompiuterio.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Nėra palaikomų ekranų. Prašome patikrinti, kad „DDC/CI“ yra įgalintas Jūsų ekranams/-ui.", "GENERIC_NO_DISPLAYS_SHORT": "Nebuvo galima aptikti palaikomų ekranų.", "GENERIC_SECONDS": "sekundės (-džių/-ė)", "GENERIC_MINUTES": "minutės (-čių/-ė)", "GENERIC_DDC_WARNING": "„DDC/CI“ funkcijos gali sukelti problemų Jūsų monitoriui/vaizduokliui (pvz: neatsakyti). Naudokite savo nuožiūra.", "GENERIC_SPEED_INSTANT": "Iškart/-o", "GENERIC_SPEED_SLOW": "Lėtas/-ai", "GENERIC_SPEED_VERY_SLOW": "Labai lėtas/-ai", "GENERIC_SPEED_NORMAL": "Normaliai", "GENERIC_SPEED_FAST": "Greitas/-ai", "GENERIC_SPEED_VERY_FAST": "Labai greitas/-ai", "GENERIC_PAUSE_TOD": "Sustabdyti laiko reguliavimą", "GENERIC_PAUSE_IDLE": "Sustabdyti neaktyvumo aptikimą", "PANEL_TITLE": "Reguliuoti skaistį", "PANEL_UPDATE_AVAILABLE": "Nauja versija pasiekiama", "PANEL_BUTTON_LINK_LEVELS": "Sujungti lygius", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Išjungti ekranus", "PANEL_LABEL_BRIGHTNESS": "Skai̇̃stis", "PANEL_LABEL_CONTRAST": "Kontrastas/-ingumas", "PANEL_LABEL_OFF_ON": "Maitinimo būsena", "PANEL_LABEL_COLOR_TEMPERATURE": "Spalvos temperatūra", "PANEL_LABEL_VOLUME": "Garsumas", "PANEL_LABEL_TURN_OFF": "Išjungti maitinimą", "INTRO_TITLE": "Sveiki, „Twinkle Tray“!", "INTRO_INSTRUCTIONS": "Sistemos srities piktograma skirta „Twinkle Tray“ greičiausiai yra paslėpta, todėl Jums derėtų ją perkelti į pasiekiamesnę vietą. Peržiūrėkite gidą apačioje.", "SETTINGS_TITLE": "„Twinkle Tray“ nustatymai", "SETTINGS_SIDEBAR_GENERAL": "Bendra/-i/-ai/-s", "SETTINGS_SIDEBAR_MONITORS": "Monitoriaus/Vaizduoklio nustatymai", "SETTINGS_SIDEBAR_FEATURES": "„DDC/CI“ funkcijos", "SETTINGS_SIDEBAR_TIME": "Laiko koregavimai", "SETTINGS_SIDEBAR_HOTKEYS": "Spartieji klavišai & Nuorodos", "SETTINGS_SIDEBAR_UPDATES": "Atnaujinimai", "SETTINGS_GENERAL_TITLE": "Bendra/-i/-ai/-s", "SETTINGS_GENERAL_STARTUP": "Paleisti pajungimo metu", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Pritaikyti skaistį paleidimo metu", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Atkurti paskutinę skaisčio konfigūraciją kiekvienam ekranui, kai „Twinkle Tray“ pasileidžia.", "SETTINGS_GENERAL_THEME_TITLE": "Apipavidalinimas", "SETTINGS_GENERAL_THEME_SYSTEM": "Sistemos pageidavimas (numatytai)", "SETTINGS_GENERAL_THEME_DARK": "Tamsus", "SETTINGS_GENERAL_THEME_LIGHT": "Šviesus", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Kalba", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Sistemos kalba (numatytai)", "SETTINGS_GENERAL_RESET_TITLE": "Atstatyti nustatymus", "SETTINGS_GENERAL_RESET_DESC": "Spauskite šį mygtuką, norint išvalyti konfigūraciją.", "SETTINGS_GENERAL_RESET_BUTTON": "Atstatyti nustatymus", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akrilinis liejimas", "SETTINGS_GENERAL_ACRYLIC_DESC": "Įjungti arba išjungti liejimąsi prieš permatomąjį foną per „Twinkle Tray“.", "SETTINGS_GENERAL_MICA_TITLE": "„Mica“ liejimas", "SETTINGS_GENERAL_MICA_DESC": "Įjungti arba išjungti liejimąsi prieš foną per „Twinkle Tray“.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analitika", "SETTINGS_GENERAL_ANALYTICS_DESC": "Siųsti naudojimo duomenis, siekiant patobulinti „Twinkle Tray“. Jokios asmeninės informacijos nesiunčiame/-a. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Sužinoti daugiau", "SETTINGS_GENERAL_SCROLL_TITLE": "Sistemos srities piktogramos slinkties nuoroda", "SETTINGS_GENERAL_SCROLL_DESC": "Reguliuoti visų skaisčių ryškumą vienu metu, slinkiant virš sistemos srities piktogramos. Šis neveikia su kai kuriomis lietimo jutikliais.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Sistemos srities piktograma", "SETTINGS_GENERAL_TROUBLESHOOTING": "Trikdžių derinimas", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Įjungti monitoriaus/vaizduoklio aptikimo metodai", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Jeigu „Twinkle Tray“ neatsako kai spaudžiate ant sistemos srities piktogramos arba neaptinka Jūsų ekranų, tada Jūs galite bandyti išjungti vienus ar kitus monitoriaus/vaizduoklio aptikimo metodus. Paleiskite iš naujo „Twinkle Tray“, kad pakeitimai būtų pritaikyti. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Išjungti perdangą", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Jeigu „Twinkle Tray“ sparčiojo klavišo perdangos trukdžiai su pilno ekrano programomis, tada Jūs galite išjungti jį štai čia.", "SETTINGS_MONITORS_RATE_TITLE": "Skaisčio atnaujinimo dažnis", "SETTINGS_MONITORS_RATE_DESC": "Kaip dažnai skai̇̃stis bus atnaujintas Jūsų ekranams, tuo metu kai Jūs keičiate jo reikšmes. Padidinkite laiką, jeigu Jūsų ekranai mirksi/-ėją.", "SETTINGS_MONITORS_RATE_0": "Absurdiškas", "SETTINGS_MONITORS_RATE_1": "Greitas/-ai (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normaliai (500 ms)", "SETTINGS_MONITORS_RATE_3": "Lėtas/-ai (1-a sekundė)", "SETTINGS_MONITORS_RATE_4": "Labai lėtas/-ai (2-i sekundės)", "SETTINGS_MONITORS_RENAME_TITLE": "Pervadinti monitorius/vaizduoklius", "SETTINGS_MONITORS_RENAME_DESC": "Jei Jums patogiau turėti atskirą pavadinimą kiekvienam monitoriui/vaizduokliui (pvz: „Kairysis monitorius“, „Didysis/Ryškesnis/Brangesnis ekranas“ ir t.t.), tada Jūs galite įvestį jį apačioje; skirtame lauke. Nieko neįvedus į lauką, atkurs/naudos jo originalų pavadinimą.", "SETTINGS_MONITORS_ENTER_NAME": "Įvesti/-kite pavadinimą/-us", "SETTINGS_MONITORS_REORDER_TITLE": "Perrikiuoti monitorius/vaizduoklius", "SETTINGS_MONITORS_REORDER_DESC": "Pakeisti tvarką, pagal kurią monitoriai/vaizduokliai yra rodomi užduočių juostoje. Spauskite ir tempkite norint pakeisti.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalizuoti skaistį", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitoriai/Vaizduokliai dažnai turi skirtingą skaisčio diapazoną. Ribojant minimalų ir maksimalų skaistį kiekvienam ekranui, jų skaisčio lygiai tarp ekranų bus nuoseklesni.", "SETTINGS_MONITORS_DETAILS_NAME": "Pavadinimas", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Vidinis pavadinimas", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Komunikacijos metodas", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Dabartinis skai̇̃stis", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maksimalus skai̇̃stis", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Skaisčio normalizavimas", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Slėpti neaktyvųjį vidinį ekraną", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Kai nešiojamojo kompiuterio ekranas nuleistas ar vidinis ekranas yra išjungtas per „Windows“, tada slėpti skaisčio slinktį/reguliavimą skydelyje (panelėje).", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Slėpti ekranus", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Jei Jūs norėtumėte slėpti specifinius ekranus nuo išskleidžiamojo meniu, tai Jūs galite perjungti (išjungti) jas čia.", "SETTINGS_FEATURES_DESCRIPTION": "Įgalinkite arba išjunkite specifines „DDC/CI“ funkcijas skaisčio skydelyje (panelėje). Nors viena funkcija turi būti įgalinta Jūsų monitoriui/vaizduokliui, kad jis atsirastų skaisčio skydelyje (panelėje). Ne visi ekranai palaiko šias funkcijas, tai įskaito nešiojamųjų kompiuterių/plančečių ekranus.", "SETTINGS_FEATURES_UNSUPPORTED": "Šis monitorius/vaizduoklis nepalaiko „DDC/CI“ funkcijas.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Patikrinti dabartines reikšmes", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Visada gauti paskiausią skaisčio lygį ar tam tikras reikšmes iš monitoriaus/vaizduoklio, kai atidaromas skaisčio skydelis. Įgalinkite šį, jeigu skai̇̃stis dažnai keičiasi (ar kitų „VCP“ kodų kaip kontrastas) iš kitų šaltinių negu „Twinkle Tray“ (pvz: kita programa).", "SETTINGS_TIME_TITLE": "Dienos laiko reguliavimas", "SETTINGS_TIME_DESC": "Automatiškai nustatyti Jūsų monitorius/vaizduoklius į nustatytą skaisčio lygį norimu laiku. Visi monitoriai/vaizduokliai bus nustatyti į tą patį, normalizuota lygį.", "SETTINGS_TIME_ADD": "Pridėti laiką", "SETTINGS_TIME_REMOVE": "Pašalinti laiką", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Nustatyti skaistį atskiriems ekranams", "SETTINGS_TIME_INDIVIDUAL_DESC": "Konfigūruoti skaistį atskiriems ekranams, vietoj visiems ekranams vienu metu.", "SETTINGS_TIME_TRANSITON_TITLE": "Skaisčio virsmo greitis", "SETTINGS_TIME_TRANSITON_DESC": "Kaip greitai tūrėtų skai̇̃stis virsmuoti, kai dienos laiko reguliavimas yra įgaliotas.", "SETTINGS_TIME_STARTUP_TITLE": "Tikrinti programos paleidimo metu", "SETTINGS_TIME_STARTUP_DESC": "Reguliuoti skaistį, kad sutaptų su tinkamiausiu laiku, kai „Twinkle Tray“ pasileidžia.", "SETTINGS_TIME_IDLE_TITLE": "Neaktyvumo aptikimas", "SETTINGS_TIME_IDLE_DESC": "Kai nėra aptiktas aktyvumas tam tikram laiko periodui, tada visų ekranų skai̇̃stis bus sumažintas.", "SETTINGS_TIME_ANIMATE_TITLE": "Animuoti tarp laikų", "SETTINGS_TIME_ANIMATE_DESC": "Skaisčio lygiai bus animuoti tarp dabartinio ir numatyto įvykio. Gali padidinti „CPU“ vartojimą. Rankinis skaisčio reguliavimas bus greitas perrašytas, kai šis yra aktyvus.", "SETTINGS_HOTKEYS_TITLE": "Spartieji klavišai", "SETTINGS_HOTKEYS_DESC": "Konfigūruoti sparčiuosius klavišus, norint reguliuoti vieno ar visų ekranų skaistį.", "SETTINGS_HOTKEYS_ADD": "Pridėti spartųjį klavišą", "SETTINGS_HOTKEYS_REMOVE": "Pašalinti spartųjį klavišą", "SETTINGS_HOTKEYS_INCREASE": "Padidinti skaistį", "SETTINGS_HOTKEYS_DECREASE": "Sumažinti skaistį", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Spauskite mygtukus čia", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Skaisčio lygio reguliavimas", "SETTINGS_HOTKEYS_LEVEL_DESC": "Kiek tūrėtų skai̇̃stis kisti, kai naudojami spartieji klavišai.", "SETTINGS_HOTKEYS_TOD_TITLE": "„Išjungti ekranų maitinimą“ veiksmas", "SETTINGS_HOTKEYS_TOD_DESC": "Redaguoti signalą, kuris siunčiamas naudojant „Išjungti maitinimą ekranams“ spartujį klavišą ar piktogramą. Programinis signalas bus rodomas juodu ekranu, iki tol, kol bus įvestis (pvz: pelė, klaviatūra ar liečiamumas) „Windows“. Aparatinis signalus išjungs maitinimą monitoriams/vaizduokliams.", "SETTINGS_HOTKEYS_TOD_NONE": "Joks (slėpti piktogramą)", "SETTINGS_HOTKEYS_TOD_SOFT": "Programinis signalas (numatytas)", "SETTINGS_HOTKEYS_TOD_HARD": "Aparatinis* signalas (tik „DDC/CI“)", "SETTINGS_HOTKEYS_TOD_BOTH": "Aparatinis* ir programinis signalas", "SETTINGS_HOTKEYS_TOD_NOTE": "*Pastaba: Ne visi „DDC/CI“ monitoriai/vaizduokliai palaiko šią funkciją. Į lietuvių k. išvertė Džiugas Jan.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Sparčiųjų klavišų trukimas sujungtiems lygiams", "SETTINGS_HOTKEYS_BREAK_DESC": "Kai naudojamas spartusis klavišas vienam ekranui ir „Sujungti lygiai“ yra aktyvūs, tada jis bus išjungtas.", "SETTINGS_UPDATES_TITLE": "Atnaujinimai", "SETTINGS_UPDATES_VERSION": "Jūs turite „Twinkle Tray {{1}}“.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automatiškai tikrinti ar yra naujų versijų", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Kai yra nauja versija, tada ji bus rodoma per skaisčio skydelį.", "SETTINGS_UPDATES_MS_STORE": "Norint patikrinti dėl naujos versijos, peržiūrėkite per „Microsoft Store“.", "SETTINGS_UPDATES_AVAILABLE": "Nauja „Twinkle Tray“ versija pasiekiama!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Naujausias. Dabartinė versija įtraukia šiuos pakeitimus:", "SETTINGS_UPDATES_DOWNLOADING": "Atsisiunčiami atnaujinimai…", "SETTINGS_UPDATES_DOWNLOAD": "Atsisiųsti & Įdiegti {{1}}", "SETTINGS_UPDATES_CHANNEL": "Atnaujinimo kanalas", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabilus (numatytas)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Išjungti maitinimą", "GENERIC_DELETE": "Ištrinti", "GENERIC_DEFAULT": "Numatyta/-s", "GENERIC_OPTIONAL": "Pasirinktina/-s/-i", "PANEL_LABEL_TURN_ON": "Įjungti maitinimą", "SETTINGS_GENERAL_OVERLAY_TITLE": "Numatyta apvalkalo veiksena", "SETTINGS_GENERAL_OVERLAY_DESC": "Ant kiek priverstinai skaisčio spartusis klavišas; jo apvalkalas bandys rodyti virš kitų programų/-ėlių. Jūs neturėtumėte keisti šios parinkties.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Daugiausiai palaikoma/-s", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Šis apvalkalas rodysis virš daugumos iškylančių langų, tačiau neverž ant viršaus tų, kurie pažymėti – „visada ant viršaus“.", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Priverstinai įjungta/-s", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Pasenusio „DDC/CI“ aptikimo būdas", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Naudoti senąjį „v1.15.5“ „DDC/CI“ ekranų aptikimo būdą.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Automatiškai pritaikyti skaistį", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Praleisti automatinį pritaikymą nurodytams monitoriams/vaizduokliams", "SETTINGS_GENERAL_REPORT_TITLE": "Sukurti at(a)skaita", "SETTINGS_GENERAL_REPORT_DESC": "Išsaugoti teksto failą su informacija apie Jūsų monitorius/vaizduoklius ir nustatymus; derinimo tikslams.", "SETTINGS_FEATURES_POWER_TITLE": "Elektros būsenos signalas", "SETTINGS_FEATURES_POWER_DESC": "Kai siunčiama „DDC/CI“ komanda, kad išjungtų Jūsų ekraną, ši/-os nurodyta/-os reikšmė/-s bus nusiųsta/-os.", "SETTINGS_FEATURES_POWER_COMPAT": "Daugiausiai palaikoma/-s", "SETTINGS_FEATURES_ADD": "Pridėti funkciją", "SETTINGS_FEATURES_ADD_VCP": "„VCP“ kodas", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "„VCP“ kodas (pvz.: „0x12“)", "SETTINGS_FEATURES_ADD_EXISTS": "Ši funkcija jau yra aktyvi.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Visi „VCP“ kodai, kurie yra pranešti šio ekrano", "SETTINGS_FEATURES_VCP_EXPECTED": "Numatytos reikšmės", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Jeigu Jūsų monitorius/vaizduoklis keistai reaguoja ar veikia po jo išjungimo ar prisijungimo/atsijungimo, tada išjungus šį, gali Jums padėti.", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Išjungti/Išgalinti automatinį pritaikymą žinomiems skaisčiams po to, kai visi įrangos/elektros įvykiai įvykstam tam tikram (-iems) monitoriui/vaizduokliui (-iam). Šis įskaito ir miego aptikimo funkcijas.", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Visada bandyti rodyti apvalkalą virš kitų langų. Šis nustatymas gali sukelti problemų su programomis ar žaidimais, kurie specialiai perima viso ekrano veikseną. Tai pat, gali sukelti tam tikrą anti-sukčiavimo žaidimuose reagavimą.", "SETTINGS_FEATURES_POWER_STANDBY": "Budėsena", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Kiekis slinkti", "SETTINGS_TIME_IDLE_FS_DESC": "Pilno ekrano programos/-ėlės blokuoja budinčios būklės aptikimą. Šis veikia tik ant fokusuotų langų.", "SETTINGS_TIME_LAT": "Platuma", "SETTINGS_FEATURES_POWER_WARNING": "Parinktis – „Budėsena“ yra labiau linkusi, kad leistu monitoriaus/vaizduoklio įjungimą/išjungimą naudojant „Twinkle Tray“. Tačiau, daugelis monitorių/vaizduoklių neatsako į šį elektros būsenos pakitimą. Naudokite savo nuožiūra.", "SETTINGS_FEATURES_ADD_DESC": "Įveskite „VCP“ kodą funkcijai, kurią Jūs norėtumėte pridėti savo ekranui. Atkreipkite dėmesį, kad „Twinkle Tray“ nepatikrina ar Jūsų ekranai iš tikrųjų palaiko šį „VCP“ kodą. Naudokite savo nuožiūra.", "SETTINGS_TIME_LONG": "Ilguma", "SETTINGS_TIME_SUN_GET": "Gauti koordinates", "SETTINGS_TIME_IDLE_FS_TITLE": "Pilno ekrano programos/-ėlės blokuoja budėjančiosios būsenos aptikimą", "SETTINGS_TIME_SUN_TITLE": "Koordinatės saulės pozicijai", "SETTINGS_TIME_SUN_DESC": "Kad naudotumėte „saulės poziciją“ laiko koregavimams, prašome įvesti savo dabartinę ilgumą ir platumą, kad teisingi laikai būtų nustatyti.", "SETTINGS_FEATURES_VCP_LIST_DESC": "Toliau esantis sąrašas galimų „VCP“ kodų, kuriuos praneša šis ekranas „Windows'ams“. „Twinkle Tray“ netikrina šių „VCP“ kodų funkcionalumą ar stabilumą. Naudokite juos savo nuožiūra.", "SETTINGS_HOTKEY_TARGET": "Veiksmo taikomasis", "SETTINGS_HOTKEY_VALUE": "Reikšmė", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Įveskite skaičių", "SETTINGS_HOTKEY_VALUES": "Reikšmės", "SETTINGS_HOTKEY_ADD_VALUE": "Pridėti reikšmę", "SETTINGS_HOTKEY_ACTION": "Veiksmas", "SETTINGS_HOTKEY_ACTION_SET": "Nustatyti reikšmę", "SETTINGS_HOTKEY_ACTION_OFFSET": "Derinti reikšmę", "SETTINGS_HOTKEY_ACTION_CYCLE": "Pereiti pro reikšmių sąrašą", "SETTINGS_PROFILES_TITLE": "Profiliai", "SETTINGS_PROFILES_ADD": "Naujas profilis", "SETTINGS_PROFILES_NAME": "Profilio pavadinimas/vardas", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Nustatyti skaistį, kai aktyvus/-i", "SETTINGS_PROFILES_SHOW_MENU": "Rodyti dešinės pelės paspaudimo meniu, sistemos juostelėje", "SETTINGS_PROFILES_TRIGGER_TITLE": "Programos/-ėlės sukėlimo veiksenos nustatymai", "SETTINGS_PROFILES_APP_PATH": "Programos/-ėlės kelias", "SETTINGS_PROFILES_APP_DESC": "Jeigu Jūs norite, kad šis profilis automatiškai aktyvuotųsi, kai nurodyta programa/-ėlė yra fokusuota, tada prašome įvesti pilną ar daliną „*.exe“ failo kelią apačioje.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Perrašyti apvalkalo tipą", "SETTINGS_HOTKEY_OFF_WARN": "Šis veiksmas naudos parinktį, parinkta po – „Išjungti ekranų maitinimą“ veiksmu. Jei Jūs pageidaujate išjungti nurodytą/-us ekraną/-us, tada naudokite – „Nustatyti“ ar „Ciklo“ spartųjį veiksmą.", "SETTINGS_PROFILES_DESC": "Automatiškai derinti skaistį ar nuorodos uždangos veikimą, priklausomai nuo fokusuotos programos/-ėlės. Jūs tai pat galite pridėti profilius prie dešinio paspaudimo meniu, sistemos juostelėje, norint greitai pakeisti skaistį į jau nustatytus profilius.", "SETTINGS_PROFILES_OVERLAY_DESC": "Pakeičia apvalkalo trumpinio elgseną, kai nurodyta programos/-ėlė fokusuota. Ši funkcija neveikia, kai profilis yra aktyvuotas rankiniu būdu.", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Neaktyvumo aptikimas bus išjungtas/išgalintas kol leidžiama medija. Šis įskaito vaizdą ir garsą. Šis prisitaiko tik tada, kai „Windows“ praneša apie jos veikimą.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Medijos veikimas blokuoja neaktyvumo aptikimą", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Apgręžti slinkimą", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Kai slinkama virš sistemos srities piktogramos, slinkimo kryptis bus apversta/priešinga nuo pradžios.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Išjungti/Išgalinti veikiant užrakinimo ekrane", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Nepasiekti monitorių/vaizduoklių, kol naudotojo/vartotojo seansas yra užrakintas. Kai turite kelis veikiančius naudotojus/vartotojus su savo atskirais veikimais ir aplinkomis; tai daroma siekiant išvengti konfliktų.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "Ekrano „HDR“ nustatymai", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Įjungti/Įgalinti „SDR“ skaisčio šliaužiklius/slinktukus nurodytams monitoriams/vaizduokliams. Šie monitoriai/vaizduokliai turi turėti „HDR“ parametrą įjungtą/įgalintą per „Windows“, kad šis veiktų.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "„SDR“ pakeičia pagrindinį šliaužiklį/slinktuką", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Valdykite „SDR“ skaistį iš pagrindinio skaisčio šliaužiklio/slinktuko, kol „HDR“ yra veikiantis.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "„SDR“ skaistis", "GENERIC_NOT_SUPPORTED": "Nepalaikoma/-s", "GENERIC_SUPPORTED": "Palaikoma/-s", "GENERIC_ACTIVE": "Aktyvus/-i", "PANEL_LABEL_INPUTS": "Įvestys", "SETTINGS_MONITORS_DETAILS_HDR": "„HDR“", "GENERIC_UNSUPPORTED": "Nepalaikoma/-s", "GENERIC_DETECTING_DISPLAYS": "Aptinkami ekranai…", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "„Windows“ grafinės sąsajos stilius", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Apipavidalinimo naujinimo aptikimas", "SETTINGS_HOTKEY_ADD_ACTION": "Pridėti veiksmą", "GENERIC_ICON": "Mygtukas", "GENERIC_TEXT": "&Tekstas", "GENERIC_CALIBRATION_POINT": "Kalibravimo/-cijos taškas", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Aptinka darbalaukio fono/apipavidalinimo/personalizavimo spalvų pakeitimus iš „Windows“, kad būtų atnaujinta sisteminės juostelės piktograma ir „Mica“ efektas. Išjungus/Išgalinus šį parametrą gali padėti, jei trečios šalies programa aktyviai ir/ar dažnai keitinėja apipavidalinimą, taip didinant „CPU“ vartojimą/naudojimą.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Monitoriaus/Ekrano/Vaizduoklio maitinimo būsenos aptikimas", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Aptinka pokyčius į ekranų/monitorių/vaizduoklių maitinimo būsenas. Išjungus/Išgalinus, gali padėti, jeigu Jūs patiriate įvairias klaidas ar nesąmoningą veikimą, kai jie yra įjungiami ar išjungiami (įskaitant neveiksnūs). Reikalauja paleidimo iš naujo, kad būtų įjungta/įgalinta (-s).", "SETTINGS_MONITORS_CALIBRATION_DESC": "Kiek vienas ekranas/monitorius/vaizduoklis gali turėti savo atskirą/individualų kalibravimo/-cijos tašką ar taškus, kurie gali būti pridėti, siekiant išlyginti skaisčio skirtumus tarp vietų, slenkstyje. Įvesties reikšmė yra tas skaisčio lygis, kuris nurodytas šliaužiklyje/slinktuke. Kitos išvesties reikšmės nurodo tikrąjį skaisčio lygį, kurį pritaiko.", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "Susietas prie skaisčio", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Sustoti po šio skaisčio lygio", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "Jeigu Jūsų ekranas/monitorius/vaizduoklis naudoja nestandartinį „VCP“ kodą skaisčiui (tokius kaip – „0x13“ arba „0x6B“) arba, jeigu Jūs norite pakeisti/perkreipti skaisčio sliaužiklį/slinktuką prie kitokio „VCP“ kodo, tada Jūs galite jį įvesti čia apačioje.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "Palikite tuščia, numatytojo kodo naudojimui („0x10“). Raskite palaikomus kodus sąraše, kuris randasi apačioje.", "SETTINGS_TIME_USE_SUN_POSITION": "Telktis saulės padėtimi", "GENERIC_SLIDER_INDICATOR_TYPE": "Šliaužiklio/Slinktuko skaitiklio tipas", "GENERIC_SLIDER_ICON": "Šliaužiklio/Slinktuko piktograma", "GENERIC_SLIDER_TEXT": "Šliaužiklio/Slinktuko tekstas", "GENERIC_SLIDER_NAME": "Įveskite šliaužiklio/slinktuko pavadinimą" } ================================================ FILE: src/localization/nb.json ================================================ { "LANGUAGE": "Norwegian Bokmål", "GENERIC_OK": "Ok", "GENERIC_CANCEL": "Avbryt", "GENERIC_SAVE": "Lagre", "GENERIC_CLEAR": "Tøm", "GENERIC_OFF": "Av", "GENERIC_ON": "På", "GENERIC_QUIT": "Avslutt", "GENERIC_CLOSE": "Lukk", "GENERIC_SETTINGS": "Innstillinger", "GENERIC_INSTALL": "Installer", "GENERIC_DISMISS": "Forkast", "GENERIC_DISPLAY_SINGLE": "Skjerm", "GENERIC_ALL_DISPLAYS": "Alle skjermer", "GENERIC_MINIMUM": "Min.", "GENERIC_MAXIMUM": "Maks.", "GENERIC_NO_DISPLAYS": "Ingen skjermer tilkoblet. Koble en skjerm til datamaskinen din.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Fant ingen kompatible skjermer. Sjekk at \"DCC/CI\" er påslått på skjermene dine.", "GENERIC_NO_DISPLAYS_SHORT": "Fant ingen kompatible skjermer.", "PANEL_TITLE": "Juster lysstyrke", "PANEL_UPDATE_AVAILABLE": "En oppdatering er tilgjengelig", "PANEL_BUTTON_LINK_LEVELS": "Lenkenivå", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Skru av skjermer", "INTRO_TITLE": "Velkommen til Twinkle Tray!", "INTRO_INSTRUCTIONS": "Systemstatus-ikonet for Twinkle Tray er muligens skjult, derfor anbefales det at du flytter det til et mer tilgjengelig sted. Se nedenfor for instruksjoner.", "SETTINGS_TITLE": "Twinkle Tray-innstillinger", "SETTINGS_SIDEBAR_GENERAL": "Generelt", "SETTINGS_SIDEBAR_MONITORS": "Skjerminnstillinger", "SETTINGS_SIDEBAR_TIME": "Tidsjusteringer", "SETTINGS_SIDEBAR_HOTKEYS": "Hurtigtaster & Snarveier", "SETTINGS_SIDEBAR_UPDATES": "Oppdateringer", "SETTINGS_GENERAL_TITLE": "Generelt", "SETTINGS_GENERAL_STARTUP": "Start ved oppstart", "SETTINGS_GENERAL_THEME_TITLE": "Programdrakt", "SETTINGS_GENERAL_THEME_SYSTEM": "Systeminnstillinger", "SETTINGS_GENERAL_THEME_DARK": "Mørk", "SETTINGS_GENERAL_THEME_LIGHT": "Lys", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Språk", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Systemspråk (forvalg)", "SETTINGS_GENERAL_RESET_TITLE": "Tilbakestill innstillinger", "SETTINGS_GENERAL_RESET_DESC": "Hvis du av noen grunn skulle ønske å fjerne innstillingene dine, trykk på denne knappen.", "SETTINGS_GENERAL_RESET_BUTTON": "Tilbakestill innstillinger", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Skru på analyseverktøy", "SETTINGS_GENERAL_ANALYTICS_DESC": "Send bruksdata for å forbedre Twinkle Tray. Ingen personvernsinfo blir sendt. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Lær mer", "SETTINGS_MONITORS_RATE_TITLE": "Lysstyrkeoppdateringsintervall", "SETTINGS_MONITORS_RATE_DESC": "Hvor ofte lysstyrken skal oppdateres på skjermene dine når du justerer nivåene deres. Øk denne hvis skjermene flimrer.", "SETTINGS_MONITORS_RATE_0": "Latterlig", "SETTINGS_MONITORS_RATE_1": "Rask (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Treg (ett sekund)", "SETTINGS_MONITORS_RATE_4": "Veldig treg (to senkunder)", "SETTINGS_MONITORS_RENAME_TITLE": "Gi skjermer nye navn", "SETTINGS_MONITORS_RENAME_DESC": "Hvis du foretrekker et annet navn for hver monitor (f.eks. \"Venstre skjerm\", \"Skjermen i midten\"), kan du skrive dem ned nedenfor. Å la navnet stå tomt gjenoppretter originalnavnet.", "SETTINGS_MONITORS_ENTER_NAME": "Skriv inn navn", "SETTINGS_MONITORS_REORDER_TITLE": "Endre skjermrekkefølge", "SETTINGS_MONITORS_REORDER_DESC": "Endre rekkefølgen for visning av skjermer i systemkurven. Klikk og dra for å gjøre endringer.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normaliser lysstyrke", "SETTINGS_MONITORS_NORMALIZE_DESC": "Skjermer har ofte forskjellige sysstyrkerekkevidder. Ved å begrense minimal/maksimal lysstyrke per skjerm, blir lysstyrkenivåene mellom hver av dem likere. Lignende skjermer vil bruke samme innstillinger.", "SETTINGS_TIME_TITLE": "Tidsjusteringer", "SETTINGS_TIME_DESC": "Sett skjermene dine til et angitt lysstyrkenivå på ønsket tidspunkt. Alle skjermene vil bli satt til det samme, normaliserte nivået.", "SETTINGS_TIME_ADD": "Legg til tidspunkt", "SETTINGS_TIME_REMOVE": "Fjern tidspunkt", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Sett lysstyrke for enkeltskjermer", "SETTINGS_TIME_INDIVIDUAL_DESC": "Istedenfor å endre lysstyre på alle skjermene samtidig, gjør det på en av gangen.", "SETTINGS_TIME_STARTUP_TITLE": "Sjekk ved programoppstart", "SETTINGS_TIME_STARTUP_DESC": "Jamfør lysstyrken for å passe mest relevante tid når Twinkle Tray startes.", "SETTINGS_HOTKEYS_TITLE": "Hurtigtaster", "SETTINGS_HOTKEYS_DESC": "Sett opp hurtigtaster for å justere lysstyrken for én eller alle skjermene.", "SETTINGS_HOTKEYS_ADD": "Legg til hurtigtast", "SETTINGS_HOTKEYS_REMOVE": "Fjern hurtigtast", "SETTINGS_HOTKEYS_INCREASE": "Øk lysstyrke", "SETTINGS_HOTKEYS_DECREASE": "Senk lysstyrke", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Trykk taster her", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Lysstyrkenivåjustering", "SETTINGS_HOTKEYS_LEVEL_DESC": "Hvor mye lysstyrken skal justeres ved bruk av hurtigtaster.", "SETTINGS_UPDATES_TITLE": "Oppdateringer", "SETTINGS_UPDATES_VERSION": "Du bruker Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automatisk se etter nye versjoner", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Når det er en ny versjon tilgjengelig, vil du bli varslet om det i lysstyrkepanelet.", "SETTINGS_UPDATES_MS_STORE": "For å se etter oppdateringer, besøk Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "En ny versjon av Twinkle Tray er tilgjengelig!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Du er oppdatert. Denne versjonen av Twinkle Tray har følgende endringer:", "SETTINGS_UPDATES_DOWNLOADING": "Laster ned oppdatering…", "SETTINGS_UPDATES_DOWNLOAD": "Last ned og installer {{1}}", "SETTINGS_MONITORS_FEATURES_DESCRIPTION": "Skru på eller av spesifikke DDC/CI-funksjoner i lysstyrkepanelet. Minst én må være påslått for at skjermen din skal vises i lysstyrkepanelet. Ikke alle skjermer støtter disse funksjonene, som f.eks. bærbar/nettbrett-skjermer.", "SETTINGS_MONITORS_FEATURES_TITLE": "DDC/CI-funksjoner", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Systemkurvsikon", "SETTINGS_GENERAL_SCROLL_DESC": "Juster lysstyrken for alle skjermer samtidig ved å rulle over systemkurvsikonet. Dette fungerer ikke med noen pekeflater.", "SETTINGS_GENERAL_SCROLL_TITLE": "Rullesnarvei for skuffikon", "SETTINGS_GENERAL_ACRYLIC_DESC": "Skru på eller av uskarphet bak gjennomsiktige bakgrunner i Twinkle Tray.", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akryluskarpt", "PANEL_LABEL_COLOR_TEMPERATURE": "Fargetemperatur", "PANEL_LABEL_OFF_ON": "Status", "PANEL_LABEL_CONTRAST": "Kontrast", "PANEL_LABEL_BRIGHTNESS": "Lysstyrke", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI-funksjoner", "GENERIC_REFRESH_DISPLAYS": "Oppdater skjermer", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Internt Navn", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normaliser lysstyrke", "SETTINGS_FEATURES_DESCRIPTION": "Aktiver eller deaktiver de spesifikke DDC/CI valgene i lysstyrkepanelet. Det kreves mins ett valg for å kunne vise skjermen din i lysstyrkepanelet. Ikke alle skjermer støtter disse valgene, for eksempel laptopskjermer eller nettbrett.", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Sett lysstyrke ved oppstart", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Gjenopprett forrige lysstyrke for hvert av displayene når Twinkle Tray starter.", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Nåværende lystyrke", "PANEL_LABEL_VOLUME": "Volum", "SETTINGS_HOTKEYS_TOD_HARD": "Maskinvare-signal* (bare DDC/CI)", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Hent nåværende lysstyre fra skjermen når du åpner lysstyrke-menyen. Du kan aktivere dette om lysstyrken ofte endrer seg utenfor Twinkle Tray. (eksempelvis en annen applikasjon).", "SETTINGS_HOTKEYS_BREAK_DESC": "Når du bruker en hurtigtast for ett display og \"sammenkoblede nivåer\" er aktivert, vil dette bli deaktivert.", "SETTINGS_HOTKEYS_TOD_BOTH": "Maskinvare* og applikasjons-signal", "SETTINGS_HOTKEYS_TOD_DESC": "Endre signalet som sendes ut når du bruker \"Slå av skjermene\"-hurtgitasten. Applikasjons-signalet vil vise en svart skjerm frem til aktivitet blir oppdaget ved mus/tastatur i Windows. Maskinvare-signalet vil slå skjermene helt av.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Hent nåværende lysstyrke", "PANEL_LABEL_TURN_OFF": "Slå av", "GENERIC_MINUTES": "minutter", "GENERIC_SECONDS": "sekunder", "SETTINGS_TIME_IDLE_DESC": "Når det ikke er oppdaget noe aktivitet etter en viss periode, vil lysstyrken på skjermene redusere seg.", "SETTINGS_HOTKEYS_TOD_NOTE": "*Merknad: Ikke alle DDC/CI skjermer støtter denne implementasjonen.", "SETTINGS_MONITORS_DETAILS_NAME": "Navn", "SETTINGS_HOTKEYS_TOD_TITLE": "Handling når skjermer slår seg av", "SETTINGS_HOTKEYS_BREAK_TITLE": "Hurtigtaster separerer sammenkoblede nivåer", "SETTINGS_GENERAL_MICA_DESC": "Skru på eller av uskarphet bak gjennomsiktige bakgrunner i Twinkle Tray.", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Kommunikasjonsmetode", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maksimal lysstyrke", "SETTINGS_FEATURES_UNSUPPORTED": "Denne skjermen støtter ikke noen DDC/CI valg.", "SETTINGS_HOTKEYS_TOD_NONE": "Ingen (skjul ikonet)", "SETTINGS_HOTKEYS_TOD_SOFT": "Applikasjons-signal (Standard)", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Skjul deaktivert innebygd skjerm", "SETTINGS_GENERAL_MICA_TITLE": "Uskarphet", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Når skjermen er lukket eller den innebygde skjermen er slått av i Windows, skjul lysstyrkenivået fra panelet.", "SETTINGS_TIME_IDLE_TITLE": "Oppdag når enheten ikke er i bruk", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Hvis Twinkle Tray ikke reagerer når du klikker på skuffikonet eller ikke oppdager skjermene dine, kan du prøve å deaktivere visse monitordeteksjonsmetoder. Start Twinkle Tray på nytt for at endringene skal tre i kraft. {{1}}", "GENERIC_PAUSE_TOD": "Pause Tidsjusteringer", "GENERIC_PAUSE_IDLE": "Sett inaktivregistrering på pause", "SETTINGS_GENERAL_TROUBLESHOOTING": "Feilsøking", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Deaktiver monitordeteksjonsmetoder", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Deaktiver overlegg", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Hvis hurtigtastoverlegget til Twinkle Tray forstyrrer fullskjermsapplikasjoner, kan du deaktivere det her.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Skjul skjermer", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Hvis du ønsker å skjule spesifikke skjermer fra flyouten, kan du slå dem av her.", "SETTINGS_TIME_ANIMATE_TITLE": "Animer mellom tider", "SETTINGS_TIME_ANIMATE_DESC": "Lysstyrkeverdier vil bli animert mellom gjeldende og neste planlagte hendelse. Kan øke CPU-bruken. Manuelle lysstyrkejusteringer vil raskt bli overskrevet mens dette er aktivt.", "GENERIC_SPEED_INSTANT": "Umiddelbar", "GENERIC_SPEED_SLOW": "Langsom", "GENERIC_SPEED_VERY_SLOW": "Veldig treg", "GENERIC_DDC_WARNING": "DDC/CI-funksjoner som å kontrollere strømtilstanden kan føre til at skjermen ikke reagerer. Bruk på eget ansvar.", "GENERIC_SPEED_VERY_FAST": "Veldig fort", "GENERIC_SPEED_NORMAL": "Vanlig", "GENERIC_SPEED_FAST": "Rask", "SETTINGS_TIME_TRANSITON_DESC": "Hvor raskt lysstyrken skal skifte når klokkeslettjusteringer er aktivert.", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabil (standard)", "SETTINGS_TIME_TRANSITON_TITLE": "Overgangshastighet for lysstyrke", "SETTINGS_UPDATES_CHANNEL": "Oppdater kanalen", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Slå av", "GENERIC_DELETE": "Slett", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Lysstyrke" } ================================================ FILE: src/localization/nl.json ================================================ { "LANGUAGE": "Nederlands", "GENERIC_OK": "Oké", "GENERIC_CANCEL": "Annuleren", "GENERIC_SAVE": "Opslaan", "GENERIC_CLEAR": "Wissen", "GENERIC_DELETE": "Verwijderen", "GENERIC_OFF": "Uit", "GENERIC_ON": "Aan", "GENERIC_QUIT": "Afsluiten", "GENERIC_CLOSE": "Sluiten", "GENERIC_SETTINGS": "Instellingen", "GENERIC_INSTALL": "Installeren", "GENERIC_DISMISS": "Verwerpen", "GENERIC_DEFAULT": "Standaard", "GENERIC_OPTIONAL": "Optioneel", "GENERIC_DISPLAY_SINGLE": "Beeldscherm", "GENERIC_ALL_DISPLAYS": "Alle beeldschermen", "GENERIC_REFRESH_DISPLAYS": "Ververs beeldschermen", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Max", "GENERIC_NO_DISPLAYS": "Geen beeldschermen aangetroffen. Sluit een beeldscherm aan op uw computer.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Geen compatibele beeldschermen aangetroffen. Controleer of ‘DDC/CI’ is ingeschakeld op uw beeldschermen.", "GENERIC_NO_DISPLAYS_SHORT": "Geen compatibele beeldschermen aangetroffen.", "GENERIC_SECONDS": "Seconden", "GENERIC_MINUTES": "Minuten", "GENERIC_DDC_WARNING": "DDC/CI functies zoals het beheren van de stroomtoestand kunnen ervoor zorgen dat uw beeldscherm niet meer reageert. Gebruik op eigen risico..", "GENERIC_SPEED_INSTANT": "Onmiddellijk", "GENERIC_SPEED_SLOW": "Langzaam", "GENERIC_SPEED_VERY_SLOW": "Zeer Langzaam", "GENERIC_SPEED_NORMAL": "Normaal", "GENERIC_SPEED_FAST": "Snel", "GENERIC_SPEED_VERY_FAST": "Zeer snel", "GENERIC_PAUSE_TOD": "Aanpassingen van de pauzetijd", "GENERIC_PAUSE_IDLE": "Pauze inactieve detectie", "PANEL_TITLE": "Helderheid aanpassen", "PANEL_UPDATE_AVAILABLE": "Nieuwe versie beschikbaar", "PANEL_BUTTON_LINK_LEVELS": "Helderheidsniveaus koppelen", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Schakel de beeldschermen uit", "PANEL_LABEL_BRIGHTNESS": "Helderheid", "PANEL_LABEL_CONTRAST": "Contrast", "PANEL_LABEL_OFF_ON": "Energiestatus", "PANEL_LABEL_COLOR_TEMPERATURE": "Kleurtemperatuur", "PANEL_LABEL_VOLUME": "Volume", "PANEL_LABEL_TURN_OFF": "Uitschakelen", "PANEL_LABEL_TURN_ON": "Inschaklen", "INTRO_TITLE": "Hallo, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Het taakbalk-pictogram van Twinkle Tray is waarschijnlijk verborgen, dus dient u het te verplaatsen naar een locatie waar u er gemakkelijk bij kunt. Zie de instructies hieronder.", "SETTINGS_TITLE": "Twinkle Tray instellingen", "SETTINGS_SIDEBAR_GENERAL": "Algemeen", "SETTINGS_SIDEBAR_MONITORS": "Beeldscherminstellingen", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI Functies", "SETTINGS_SIDEBAR_TIME": "Tijdsaanpassingen", "SETTINGS_SIDEBAR_HOTKEYS": "Sneltoetsen & snelkoppelingen", "SETTINGS_SIDEBAR_UPDATES": "Updates", "SETTINGS_GENERAL_TITLE": "Algemeen", "SETTINGS_GENERAL_STARTUP": "Automatisch opstarten", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Helderheidsniveaus toepassen na opstarten", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Herstel de vorige helderheidsniveaus van ieder beeldschermen na het starten van Twinke Tray.", "SETTINGS_GENERAL_THEME_TITLE": "Thema", "SETTINGS_GENERAL_THEME_SYSTEM": "Systeemthema (standaard)", "SETTINGS_GENERAL_THEME_DARK": "Donker", "SETTINGS_GENERAL_THEME_LIGHT": "Licht", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Taal", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Systeem taal (standaard)", "SETTINGS_GENERAL_RESET_TITLE": "Herstel instellingen", "SETTINGS_GENERAL_RESET_DESC": "Druk op deze knop om uw instellingen te wissen.", "SETTINGS_GENERAL_RESET_BUTTON": "Instellingen terugzetten", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Acrylvervaging", "SETTINGS_GENERAL_ACRYLIC_DESC": "Schakel de vervaging achter doorzichtige achtergronden in Twinkle Tray in of uit.", "SETTINGS_GENERAL_MICA_TITLE": "Micavervaging", "SETTINGS_GENERAL_MICA_DESC": "Schakel de vervaging achter achtergronden in Twinkle Tray in of uit.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Gegevensverzameling", "SETTINGS_GENERAL_ANALYTICS_DESC": "Verstuur gebruiksgegevens om Twinkle Tray te helpen verbeteren. Er wordt geen persoonlijke informatie verzonden. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Meer informatie", "SETTINGS_GENERAL_SCROLL_TITLE": "Taakbalksnelkoppeling-scrollsneltoets", "SETTINGS_GENERAL_SCROLL_DESC": "Pas de helderheid van alle beeldschermen aan door over het systeemvakpictogram te scrollen. Dit werkt niet op sommige trackpads.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Taakbalkpictogram", "SETTINGS_GENERAL_TROUBLESHOOTING": "SETTINGS_GENERAL_TROUBLESHOOTING", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Monitor detectiemethoden uitschakelen", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Als Twinkle Tray niet reageert wanneer u op het pictogram in de lade klikt of als uw beeldschermen niet worden gedetecteerd, kunt u proberen bepaalde methoden voor beeldschermdetectie uit te schakelen. Start Twinkle Tray opnieuw op voordat de wijzigingen van kracht worden. {{1}}", "SETTINGS_GENERAL_OVERLAY_TITLE": "Standaard overlay gedrag", "SETTINGS_GENERAL_OVERLAY_DESC": "Hoe sterk de helderheids-hotkey-overlay zal proberen weer te geven boven andere apps. U hoeft dit niet aan te passen.", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Overlay uitschakelen", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Als de sneltoets-overlay van Twinkle Tray interfereert met toepassingen op volledig scherm, kunt u die hier uitschakelen.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Meest compatibel", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "De overlay wordt weergegeven worden boven de meeste vensters, maar zal zich niet boven apps forceren die gemarkeerd zijn als \"altijd op de voorgrond\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Gerforceerd aan", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Probeer altijd de overlay bovenop andere vensters weer te geven. Dit kan problemen veroorzaken met exclusieve fullscreen games en andere fullscreen apps. Het kan ook anti-cheat in sommige games activeren.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Legacy DDC/CI detectiemethode", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Gebruik de oude v1.15.5 methode van detecteren DDC/CI beeldschermen.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Helderheid Automatisch toepassen", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Als uw beeldsherm vreemd reageert na het uitschakelen van het loskoppelen/aansluiten van hardware, kan het uitschakelen hiervan helpen.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Automatisch toepassen overslaan voor specifieke monitoren", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Automatisch toepassen van helderheid uitschakelen na alle hardware-/stroomevenementen voor specifieke beeldschermen. Dit omvat de inactieve detectiefunctie.", "SETTINGS_GENERAL_REPORT_TITLE": "Genereer Rapport", "SETTINGS_GENERAL_REPORT_DESC": "Sla een tekstbestand op met informatie over uw beeldschermen en instellingen voor foutopsporing.", "SETTINGS_MONITORS_RATE_TITLE": "Helderheidsveranderingssnelheid", "SETTINGS_MONITORS_RATE_DESC": "Hoe vaak de helderheid op uw beeldschermen wordt bijgewerkt als u de waarden ervan aanpast. Verhoog de tijd als uw beeldschermen flikkeren.", "SETTINGS_MONITORS_RATE_0": "Belachelijk", "SETTINGS_MONITORS_RATE_1": "Snel (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normaal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Langzaam (1 second)", "SETTINGS_MONITORS_RATE_4": "Zeer langzaam (2 seconds)", "SETTINGS_MONITORS_RENAME_TITLE": "Beeldschermnaam wijzigen", "SETTINGS_MONITORS_RENAME_DESC": "Als u de voorkeur geeft aan een andere naam voor elk beeldscherm (bijv. \"Beeldscherm links\", \"Middelste beeldscherm\"), dan kunt u die hieronder invoeren. Als u het veld leeg laat, wordt de oorspronkelijke naam hersteld.", "SETTINGS_MONITORS_ENTER_NAME": "Voer een naam in", "SETTINGS_MONITORS_REORDER_TITLE": "Beeldschermvolgorde veranderen", "SETTINGS_MONITORS_REORDER_DESC": "Wijzig de volgorde waarin de beeldschermen in de taakbalk worden getoond. Klik en sleep om wijzigingen aan te brengen.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Helderheid normaliseren", "SETTINGS_MONITORS_NORMALIZE_DESC": "Beeldschermen hebben vaak verschillende helderheidsbereiken. Door de min.-/max.-helderheid per beeldscherm te beperken, zijn de helderheidsniveaus tussen de schermen veel gelijkmatiger. Vergelijkbare beeldschermen gebruiken dezelfde instellingen.", "SETTINGS_MONITORS_DETAILS_NAME": "Naam", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Interne Naam", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Communicatiemethode", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Huidig helderheidsniveau", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Max. helderheidsniveau", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Helderheid normaliseren", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Inactief ingebouwd scherm verbergen", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Als de deksel gesloten is of het ingebouwde beeldscherm is uitgeschakeld in Windows, dan wordt de helderheidsbalk op de taakbalk verborgen.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Beeldschermen verbergen", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Als u specifieke displays uit het vervolgmenu wilt verbergen, kunt u ze hier uitschakelen.", "SETTINGS_FEATURES_DESCRIPTION": "Schakel specifieke DDC/CI-functies in of uit op het helderheidspaneel. U dient minimaal één functie in te schakelen om het beeldscherm op het paneel te tonen. Niet alle beeldschermen ondersteunen deze functies, zoals laptop- en tabletschermen.", "SETTINGS_FEATURES_UNSUPPORTED": "Dit beeldscherm heeft geen ondersteuning voor DDC-/CI-functies.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Huidig helderheidsniveau opvragen", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Vraag altijd het huidige helderheidsniveau op bij het beeldscherm na het openen van de pagina. Schakel in als de helderheid regelmatig wordt aangepast door een ander programma dan Twinke Tray.", "SETTINGS_FEATURES_POWER_TITLE": "Stroomtoestandssignaal", "SETTINGS_FEATURES_POWER_DESC": "Bij het verzenden van het DDC/CI-commando om uw display uit te schakelen, worden de volgende waarde(n) verzonden.", "SETTINGS_FEATURES_POWER_STANDBY": "Standby", "SETTINGS_FEATURES_POWER_OFF": "Uitschakelen", "SETTINGS_FEATURES_POWER_COMPAT": "Meest compatibel", "SETTINGS_FEATURES_POWER_WARNING": "De \"Standby\" optie maakt het waarschijnlijker om het beeldscherm in of uit te schakelen via Twinkle Tray. Echter, veel beeldschermen reageren niet correct op het wijzigen van de stroomtoestand. Gebruik op eigen risico.", "SETTINGS_FEATURES_ADD": "Functie toevoegen", "SETTINGS_FEATURES_ADD_DESC": "Voer de VCP-code in voor de functie die u aan uw beeldscherm wilt toevoegen. Houd er rekening mee dat Twinkle Tray niet controleert of uw beeldscherm deze VCP-code daadwerkelijk ondersteunt. Gebruik op eigen risico.", "SETTINGS_FEATURES_ADD_VCP": "VCP Code", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP code (Ex. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Deze functie is al actief.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Alle VCP codes gerapporteerd door dit beeldscherm", "SETTINGS_FEATURES_VCP_LIST_DESC": "Het volgende is een lijst met beschikbare VCP-codes die door dit beeldscherm aan Windows zijn gerapporteerd. Twinkle Tray valideert deze functionaliteit of stabiliteit van deze VCP-codes niet. Gebruik ze op eigen risico.", "SETTINGS_FEATURES_VCP_EXPECTED": "Verwachte waarden", "SETTINGS_TIME_TITLE": "Tijdstip van de dag aanpassen", "SETTINGS_TIME_DESC": "Stel uw beeldschermen automatisch in op een bepaald helderheidsniveau op een gewenst tijdstip. Alle beeldschermen worden op dezelfde, genormaliseerde niveaus ingesteld.", "SETTINGS_TIME_ADD": "Tijdstip toevoegen", "SETTINGS_TIME_REMOVE": "Tijdstip verwijderen", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Afzonderlijke helderheid instellen voor beeldschermen", "SETTINGS_TIME_INDIVIDUAL_DESC": "Stel de helderheid per beeldscherm in plaats van voor alle beeldschermen tegelijk.", "SETTINGS_TIME_TRANSITON_TITLE": "Helderheidsovergangssnelheid", "SETTINGS_TIME_TRANSITON_DESC": "Hoe snel de helderheid moet overgaan wanneer de tijdaanpassingen worden geactiveerd.", "SETTINGS_TIME_STARTUP_TITLE": "Controleren na opstarten", "SETTINGS_TIME_STARTUP_DESC": "Pas de helderheid aan zodat deze overeenkomt met het meest relevante tijdstip als Twinkle Tray start.", "SETTINGS_TIME_IDLE_TITLE": "Inactieve staat detecteren", "SETTINGS_TIME_IDLE_DESC": "Verlaag de helderheid van alle schermen als er gedurende een bepaalde periode geen invoer is waargenomen.", "SETTINGS_TIME_ANIMATE_TITLE": "Animatie tussen tijden", "SETTINGS_TIME_ANIMATE_DESC": "De helderheidswaarden worden geanimeerd tussen de huidige en de volgende geplande gebeurtenis. Kan het CPU-gebruik verhogen. Handmatige helderheidsaanpassingen worden snel overschreven als dit actief is.", "SETTINGS_TIME_SUN_TITLE": "Coördinaten voor de zonpositie", "SETTINGS_TIME_SUN_DESC": "Om de \"zonpositie\" te gebruiken voor tijdsaanpassingen, voer uw huidige breedtegraad en lengtegraad in zodat de juiste tijden kunnen worden bepaald.", "SETTINGS_TIME_LAT": "Breedtegraad", "SETTINGS_TIME_LONG": "Lengtegraad", "SETTINGS_TIME_SUN_GET": "Coördinaten ophalen", "SETTINGS_TIME_IDLE_FS_TITLE": "Volledige scherm-apps zijn nooit inactief", "SETTINGS_TIME_IDLE_FS_DESC": "Volledige scherm-apps blokkeren inactieve detectie. Dit geldt alleen voor het gefocuste venster.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Media blokkeert inactieve detectie", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Inactieve detectie wordt uitgeschakeld terwijl er media wordt afgespeeld. Dit geldt voor video en audio. Dit geldt alleen wanneer Windows meldt dat er media wordt afgespeeld.", "SETTINGS_HOTKEYS_TITLE": "Sneltoetsen", "SETTINGS_HOTKEYS_DESC": "Stel sneltoetsen in om de helderheid van één of alle beeldschermen aan te passen.", "SETTINGS_HOTKEYS_ADD": "Sneltoets toevoegen", "SETTINGS_HOTKEYS_REMOVE": "Sneltoets verwijderen", "SETTINGS_HOTKEYS_INCREASE": "Helderheid verhogen", "SETTINGS_HOTKEYS_DECREASE": "Helderheid verlagen", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Druk hier op toetsen", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Helderheidsniveau aanpassen", "SETTINGS_HOTKEYS_LEVEL_DESC": "Hoeveel de helderheid moet worden aangepast bij het gebruik van sneltoetsen.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Scrollhoeveelheid", "SETTINGS_HOTKEYS_TOD_TITLE": "Beeldschermen uitschakelen", "SETTINGS_HOTKEYS_TOD_DESC": "Pas het signaal aan dat wordt verstuurd bij gebruik van de sneltoets/het pictogram ‘Beeldschermen uitschakelen’. Het softwarematige signaal toont een zwart scherm totdat er invoer wordt vastgesteld (bijv. muis of toetsenbord) - het hardwarematige signaal schakelt de beeldschermen volledig uit.", "SETTINGS_HOTKEYS_TOD_NONE": "Geen (pictogram verbergen)", "SETTINGS_HOTKEYS_TOD_SOFT": "Softwarematig signaal (standaard)", "SETTINGS_HOTKEYS_TOD_HARD": "Hardwarematig* signaal (alleen DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Hardware-* en softwarematig signaal", "SETTINGS_HOTKEYS_TOD_NOTE": "*Let op: niet alle DDC/CI-beeldschermen ondersteunen deze functie.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Sneltoetsen onderbreken gekoppelde niveaus", "SETTINGS_HOTKEYS_BREAK_DESC": "Als u op een sneltoets drukt en ‘gekoppelde niveaus’ is ingeschakeld, dan wordt de functie uitgeschakeld.", "SETTINGS_HOTKEY_OFF_WARN": "Deze actie zal de optie gebruiken die is geselecteerd onder \"Beeldschermen uitschakelen\". Als u specifieke schermen wilt uitschakelen, gebruik dan in plaats daarvan de \"Set\" of \"Cycle\" sneltoetsactie.", "SETTINGS_HOTKEY_TARGET": "Actiedoel", "SETTINGS_HOTKEY_VALUE": "Waarde", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Enter een nummer", "SETTINGS_HOTKEY_VALUES": "Waarden", "SETTINGS_HOTKEY_ADD_VALUE": "Waarde toevoegen", "SETTINGS_HOTKEY_ACTION": "Actie", "SETTINGS_HOTKEY_ACTION_SET": "Zet waarde", "SETTINGS_HOTKEY_ACTION_OFFSET": "waarde aanpassen", "SETTINGS_HOTKEY_ACTION_CYCLE": "Lijst met waarden doorlopen", "SETTINGS_PROFILES_TITLE": "Profielen", "SETTINGS_PROFILES_DESC": "Pas de helderheid of het gedrag van het snelkoppelingsoverlay automatisch aan, afhankelijk van de gefocuste app. U kunt ook profielen toevoegen aan het rechtermuisklikmenu in het systeemvak om snel de helderheid te wijzigen naar vooraf gedefinieerde profielen.", "SETTINGS_PROFILES_ADD": "Nieuw profiel", "SETTINGS_PROFILES_NAME": "Profiel Naam", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Helderheid instellen wanneer actief", "SETTINGS_PROFILES_SHOW_MENU": "Weergeven in het rechtermuisklikmenu in het systeemvak", "SETTINGS_PROFILES_TRIGGER_TITLE": "App-triggerinstellingen", "SETTINGS_PROFILES_APP_PATH": "Applicatie pad", "SETTINGS_PROFILES_APP_DESC": "Als u wilt dat dit profiel automatisch wordt geactiveerd wanneer een specifieke app is gefocust, voert u het volledige of gedeeltelijke pad van het EXE-bestand hieronder in.", "SETTINGS_PROFILES_OVERLAY_TITLE": "overlaytype overschrijven", "SETTINGS_PROFILES_OVERLAY_DESC": "Verandert het gedrag van de sneltoets-overlay wanneer de gespecificeerde app is gefocust. Deze functie werkt niet wanneer het profiel handmatig is geactiveerd.", "SETTINGS_UPDATES_TITLE": "Updates", "SETTINGS_UPDATES_VERSION": "U beschikt over Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automatisch controleren op nieuwe versies", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Als er een nieuwe versie beschikbaar is, wordt deze getoond op het helderheidspaneel.", "SETTINGS_UPDATES_MS_STORE": "Open de Microsoft Store-app om te controleren op nieuwe versies.", "SETTINGS_UPDATES_AVAILABLE": "Er is een nieuwe versie van Twinkle Tray beschikbaar!", "SETTINGS_UPDATES_NONE_AVAILABLE": "U beschikt over de nieuwste versie. De huidige versie bevat de volgende wijzigingen:", "SETTINGS_UPDATES_DOWNLOADING": "Bezig met downloaden van update…", "SETTINGS_UPDATES_DOWNLOAD": "Downloaden en installeren {{1}}", "SETTINGS_UPDATES_CHANNEL": "Update kanaal", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabiel (standaard)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Helderheid" } ================================================ FILE: src/localization/pl.json ================================================ { "LANGUAGE": "Polski", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Anuluj", "GENERIC_SAVE": "Zapisz", "GENERIC_CLEAR": "Wyczyść", "GENERIC_OFF": "Wyłącz", "GENERIC_ON": "Włącz", "GENERIC_QUIT": "Zakończ", "GENERIC_CLOSE": "Zamknij", "GENERIC_SETTINGS": "Ustawienia", "GENERIC_INSTALL": "Zainstaluj", "GENERIC_DISMISS": "Odrzuć", "GENERIC_DISPLAY_SINGLE": "Wyświetlacz", "GENERIC_ALL_DISPLAYS": "Wszystkie wyświetlacze", "GENERIC_REFRESH_DISPLAYS": "Odśwież wyświetlacze", "GENERIC_MINIMUM": "Min.", "GENERIC_MAXIMUM": "Maks.", "GENERIC_NO_DISPLAYS": "Nie wykryto wyświetlaczy. Proszę podłączyć wyświetlacz do komputera.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Nie znaleziono kompatybilnych wyświetlaczy. Sprawdź, czy funkcja \"DDC/CI\" jest włączona dla Twoich wyświetlaczy.", "GENERIC_NO_DISPLAYS_SHORT": "Nie wykryto zgodnych wyświetlaczy.", "GENERIC_NOT_SUPPORTED": "Nieobsługiwane", "GENERIC_SUPPORTED": "Obsługiwane", "GENERIC_UNSUPPORTED": "Nieobsługiwane", "GENERIC_ACTIVE": "Aktywne", "GENERIC_SLIDER_INDICATOR_TYPE": "Typ suwaka", "GENERIC_ICON": "Ikona", "GENERIC_TEXT": "Tekst", "GENERIC_SLIDER_ICON": "Ikona suwaka", "GENERIC_SLIDER_TEXT": "Tekst suwaka", "GENERIC_SLIDER_NAME": "Wpisz nazwę suwaka", "PANEL_TITLE": "Regulacja jasności", "PANEL_UPDATE_AVAILABLE": "Dostępna jest nowa wersja", "PANEL_BUTTON_LINK_LEVELS": "Poziomy połączeń", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Wyłączanie wyświetlaczy", "PANEL_LABEL_BRIGHTNESS": "Jasność", "PANEL_LABEL_CONTRAST": "Kontrast", "PANEL_LABEL_OFF_ON": "Stan zasilania", "PANEL_LABEL_COLOR_TEMPERATURE": "Temperatura barwowa", "PANEL_LABEL_VOLUME": "Głośność", "INTRO_TITLE": "Witaj, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Ikona w zasobniku programu Twinkle Tray jest prawdopodobnie ukryta, więc powinieneś przenieść ją w miejsce, w którym możesz łatwo uzyskać do niej dostęp. Poniżej znajdują się instrukcje.", "SETTINGS_TITLE": "Ustawienia Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Ogólne", "SETTINGS_SIDEBAR_MONITORS": "Ustawienia monitora", "SETTINGS_SIDEBAR_FEATURES": "Funkcje DDC/CI", "SETTINGS_SIDEBAR_TIME": "Dostosowania czasowe", "SETTINGS_SIDEBAR_HOTKEYS": "Skróty klawiszowe", "SETTINGS_SIDEBAR_UPDATES": "Aktualizacje", "SETTINGS_GENERAL_TITLE": "Ogólne", "SETTINGS_GENERAL_STARTUP": "Uruchom przy starcie systemu", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Zastosuj jasność przy uruchamianiu", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Przywrócenie ostatniej znanej jasności dla każdego wyświetlacza po uruchomieniu aplikacji Twinkle Tray.", "SETTINGS_GENERAL_THEME_TITLE": "Motyw", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Styl UI Windowsa", "SETTINGS_GENERAL_THEME_SYSTEM": "Preferencje systemowe (domyślnie)", "SETTINGS_GENERAL_THEME_DARK": "Ciemny", "SETTINGS_GENERAL_THEME_LIGHT": "Jasny", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Język", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Język systemu (domyślny)", "SETTINGS_GENERAL_RESET_TITLE": "Resetowanie ustawień", "SETTINGS_GENERAL_RESET_DESC": "Naciśnij ten przycisk, aby wyczyścić konfigurację.", "SETTINGS_GENERAL_RESET_BUTTON": "Zresetuj ustawienia", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Rozmycie akrylowe", "SETTINGS_GENERAL_ACRYLIC_DESC": "Włączenie lub wyłączenie rozmycia za przezroczystym tłem w Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analityka", "SETTINGS_GENERAL_ANALYTICS_DESC": "Wyślij dane użytkowe, aby pomóc ulepszyć Twinkle Tray. Nie są wysyłane żadne dane osobowe. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Dowiedz się więcej", "SETTINGS_GENERAL_SCROLL_TITLE": "Skrót do przewijania ikony zasobnika", "SETTINGS_GENERAL_SCROLL_DESC": "Dostosuj jasność wszystkich wyświetlaczy jednocześnie, przewijając ikonę na pasku systemowym. Nie działa to z niektórymi gładzikami.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Ikona zasobnika", "SETTINGS_MONITORS_RATE_TITLE": "Szybkość aktualizacji jasności", "SETTINGS_MONITORS_RATE_DESC": "Jak często jasność będzie aktualizowana na wyświetlaczach podczas dostosowywania ich wartości. Zwiększ czas, jeśli wyświetlacze migoczą.", "SETTINGS_MONITORS_RATE_0": "Niedorzeczny", "SETTINGS_MONITORS_RATE_1": "Szybki (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normalny (500 ms)", "SETTINGS_MONITORS_RATE_3": "Powolny (1 sekunda)", "SETTINGS_MONITORS_RATE_4": "Bardzo powolny (2 sekundy)", "SETTINGS_MONITORS_RENAME_TITLE": "Zmiana nazwy monitorów", "SETTINGS_MONITORS_RENAME_DESC": "Jeśli wolisz, aby każdy monitor miał inną nazwę (np. \"Lewy monitor\", \"Środkowy monitor\"), możesz wprowadzić ją poniżej. Pozostawienie pustego pola spowoduje przywrócenie oryginalnej nazwy.", "SETTINGS_MONITORS_ENTER_NAME": "Wprowadź nazwę", "SETTINGS_MONITORS_REORDER_TITLE": "Kolejność monitorów", "SETTINGS_MONITORS_REORDER_DESC": "Zmień kolejność wyświetlania monitorów w zasobniku. Kliknij i przeciągnij, aby wprowadzić zmiany.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalizacja jasności", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitory często mają różne zakresy jasności. Dzięki ograniczeniu minimalnej/maksymalnej jasności dla każdego monitora, poziom jasności pomiędzy monitorami jest znacznie bardziej spójny.", "SETTINGS_MONITORS_DETAILS_NAME": "Nazwa", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Nazwa wewnętrzna", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Metoda komunikacji", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Aktualna jasność", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maks. jasność", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalizacja jasności", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_FEATURES_DESCRIPTION": "Włączanie lub wyłączanie określonych funkcji DDC/CI w panelu jasności. Przynajmniej jedna funkcja musi być włączona, aby monitor był widoczny w panelu jasności. Nie wszystkie wyświetlacze obsługują te funkcje, np. wyświetlacze laptopów/tabletów.", "SETTINGS_TIME_TITLE": "Regulacje pory dnia", "SETTINGS_TIME_DESC": "Automatycznie ustawia monitory na określony poziom jasności w wybranym czasie. Wszystkie monitory zostaną ustawione na te same, znormalizowane poziomy.", "SETTINGS_TIME_ADD": "Dodaj czas", "SETTINGS_TIME_REMOVE": "Usuń czas", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Ustawianie jasności dla poszczególnych wyświetlaczy", "SETTINGS_TIME_INDIVIDUAL_DESC": "Skonfiguruj jasność dla każdego wyświetlacza zamiast dla wszystkich wyświetlaczy jednocześnie.", "SETTINGS_TIME_STARTUP_TITLE": "Sprawdź przy uruchamianiu aplikacji", "SETTINGS_TIME_STARTUP_DESC": "Dostosuj jasność do najbardziej odpowiedniego czasu przy uruchamianiu Twinkle Tray.", "SETTINGS_HOTKEYS_TITLE": "Skróty klawiszowe", "SETTINGS_HOTKEYS_DESC": "Skonfiguruj klawisze szybkiego dostępu, aby dostosować jasność jednego lub wszystkich wyświetlaczy.", "SETTINGS_HOTKEYS_ADD": "Dodaj klawisz skrótu", "SETTINGS_HOTKEYS_REMOVE": "Usuń klawisz skrótu", "SETTINGS_HOTKEYS_INCREASE": "Zwiększanie jasności", "SETTINGS_HOTKEYS_DECREASE": "Zmniejszanie jasności", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Naciśnij tutaj klawisze", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Regulacja poziomu jasności", "SETTINGS_HOTKEYS_LEVEL_DESC": "W jakim stopniu jasność powinna być regulowana podczas używania klawiszy skrótu.", "SETTINGS_UPDATES_TITLE": "Aktualizacje", "SETTINGS_UPDATES_VERSION": "Wersja Twinkle Tray to {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automatyczne sprawdzanie aktualizacji", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Gdy pojawi się nowa wersja, będzie ona widoczna w panelu sterowania jasnością.", "SETTINGS_UPDATES_MS_STORE": "Aby sprawdzić dostępność aktualizacji, odwiedź Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Nowa wersja Twinkle Tray już dostępna!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Program jest aktualny. Ta wersja zawiera następujące zmiany:", "SETTINGS_UPDATES_DOWNLOADING": "Pobieranie aktualizacji…", "SETTINGS_UPDATES_DOWNLOAD": "Pobierz i zainstaluj {{1}}", "SETTINGS_HOTKEYS_TOD_NONE": "Brak (ukryj ikonę)", "SETTINGS_HOTKEYS_TOD_TITLE": "Akcja wyłączania monitora", "SETTINGS_HOTKEYS_TOD_NOTE": "*Uwaga: Nie wszystkie monitory DDC/CI wspierają tę funkcję.", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Jeśli Twinkle Tray nie reaguje po kliknięciu na ikonę zasobnika lub nie wykrywa wyświetlaczy, możesz spróbować wyłączyć niektóre metody wykrywania monitorów. Uruchom ponownie Twinkle Tray, aby zmiany zaczęły obowiązywać. {{1}}", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Sprawdzaj aktualne wartości", "PANEL_LABEL_TURN_OFF": "Wyłącz zasilanie", "GENERIC_SECONDS": "sekundy", "GENERIC_MINUTES": "minuty", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Zawsze sprawdzaj poziom jasności podczas otwierania strony jasności. Włącz tę opcję, jeśli jasność (lub inne kody VCP np. kontrast) często się zmieniają poza aplikacją Twinkle Tray.", "SETTINGS_TIME_IDLE_TITLE": "Wykrywanie bezczynności", "SETTINGS_GENERAL_MICA_DESC": "Włączenie lub wyłączenie rozmycia tła w Twinkle Tray.", "SETTINGS_FEATURES_UNSUPPORTED": "Ten monitor nie obsługuje funkcji DDC/CI.", "SETTINGS_GENERAL_MICA_TITLE": "Rozmycie Mica", "SETTINGS_HOTKEYS_TOD_DESC": "Dostosuj sygnał wysyłany podczas używania klawisza skrótu lub ikony Wyłącz wyświetlacze. Sygnał programowy wyświetli czarny ekran do czasu wykrycia wejścia (np. myszy lub klawiatury) przez system Windows. Sygnał sprzętowy wyłączy zasilanie monitorów.", "SETTINGS_TIME_IDLE_DESC": "Jeśli przez pewien czas nie zostanie wykryty żaden sygnał wejściowy, jasność wszystkich wyświetlaczy zostanie zmniejszona.", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Gdy klapa jest zamknięta lub wbudowany wyświetlacz został wyłączony w systemie Windows, ukryj suwak jasności na panelu.", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Ukryj nieaktywny wbudowany wyświetlacz", "SETTINGS_HOTKEYS_TOD_HARD": "Sygnał sprzętowy* (tylko DDC/CI)", "SETTINGS_HOTKEYS_TOD_SOFT": "Sygnał programowy (domyślnie)", "SETTINGS_HOTKEYS_TOD_BOTH": "Sygnał sprzętowy* i programowy", "SETTINGS_HOTKEYS_BREAK_TITLE": "Klawisze skrótu przerywają połączone poziomy", "SETTINGS_HOTKEYS_BREAK_DESC": "W przypadku użycia klawisza skrótu dla pojedynczego ekranu i gdy „połączone poziomy” są aktywne, zostaną one zdezaktywowane.", "GENERIC_PAUSE_TOD": "Regulacja czasu pauzy", "GENERIC_PAUSE_IDLE": "Wstrzymaj wykrywanie bezczynności", "GENERIC_DETECTING_DISPLAYS": "Wykrywanie wyświetlaczy…", "SETTINGS_GENERAL_TROUBLESHOOTING": "Rozwiązywanie problemów", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Włączone metody wykrywania monitorów", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Wyłączenie nakładki", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Ukryj wyświetlacze", "SETTINGS_TIME_TRANSITON_TITLE": "Szybkość zmiany jasności", "SETTINGS_TIME_ANIMATE_TITLE": "Animacja między czasami", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Jeśli nakładka klawiszy skrótu Twinkle Tray przeszkadza w działaniu aplikacji pełnoekranowych, możesz ją wyłączyć tutaj.", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Jeśli chcesz ukryć określone wyświetlacze z menu wysuwanego, możesz je tutaj wyłączyć.", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabilny (domyślnie)", "GENERIC_SPEED_FAST": "Szybko", "SETTINGS_TIME_TRANSITON_DESC": "Jak szybko powinna przechodzić jasność, gdy aktywowane są regulacje czasu dnia.", "SETTINGS_TIME_ANIMATE_DESC": "Wartości jasności będą animowane pomiędzy bieżącym i następnym zaplanowanym zdarzeniem. Może zwiększyć zużycie procesora. Ręczne ustawienia jasności zostaną szybko nadpisane, gdy ta funkcja jest aktywna.", "GENERIC_SPEED_NORMAL": "Normalna", "SETTINGS_UPDATES_CHANNEL": "Kanał aktualizacji", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "GENERIC_SPEED_VERY_FAST": "Bardzo szybko", "GENERIC_DDC_WARNING": "Funkcje DDC/CI mogą spowodować, że monitor przestanie odpowiadać. Używaj ich na własne ryzyko.", "GENERIC_SPEED_SLOW": "Powoli", "GENERIC_SPEED_INSTANT": "Natychmiast", "GENERIC_SPEED_VERY_SLOW": "Bardzo wolno", "SETTINGS_FEATURES_POWER_OFF": "Wyłącz zasilanie", "SETTINGS_GENERAL_OVERLAY_DESC": "Z jaką siłą nakładka wywoływana przez klawisz skrótu jasności będzie próbowała wyświetlić się nad innymi aplikacjami. Nie powinno być potrzeby dostosowywania tego.", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Nakładka będzie pokazywać się nad większością aplikacji, lecz nie będzie wymuszać się nad aplikacjami, które zaznaczono jako \"zawsze na górze\".", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Przestarzała detekcja DDC/CI", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Używaj starej metody v1.15.5 wykrywania ekranów DDC/CI.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Automatycznie stosuj jasność", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Jeśli twój monitor zachowuje się dziwnie po wyłączeniu tego/odłączaniu/podłączaniu urządzeń, wyłączenie tego może pomóc.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Pomiń auto stosowanie dla specyficznych monitorów", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Zawsze próbuj wyświetlać nakładkę ponad innymi oknami. To może spowodować problemy z aplikacjami i grami pełnoekranowymi. Może również wywoływać anti-cheat w niektórych grach.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Najbardziej kompatybilne", "GENERIC_DELETE": "Usuń", "GENERIC_DEFAULT": "Domyślnie", "GENERIC_OPTIONAL": "Opcjonalnie", "PANEL_LABEL_TURN_ON": "Włącz zasilanie", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Wymuszone", "SETTINGS_GENERAL_OVERLAY_TITLE": "Domyślne zachowanie nakładki", "SETTINGS_FEATURES_POWER_TITLE": "Sygnał stanu zasilania", "SETTINGS_TIME_LONG": "Długość", "SETTINGS_TIME_SUN_GET": "Uzyskaj współrzędne", "SETTINGS_GENERAL_REPORT_TITLE": "Wygeneruj raport", "SETTINGS_GENERAL_REPORT_DESC": "Zapisz plik tekstowy z informacjami o monitorach i ustawieniach debugowania.", "SETTINGS_FEATURES_POWER_STANDBY": "Gotowość", "SETTINGS_FEATURES_POWER_DESC": "Podczas wysyłania polecenia DDC/CI w celu wyłączenia wyświetlacza zostaną wysłane następujące wartości.", "SETTINGS_FEATURES_POWER_COMPAT": "Najbardziej kompatybilne", "SETTINGS_FEATURES_POWER_WARNING": "Opcja „Gotowość” ma większe prawdopodobieństwo umożliwienia włączania/wyłączania monitora z poziomu Twinkle Tray. Jednak wiele monitorów nie reaguje prawidłowo na zmianę stanu zasilania. Używaj na własne ryzyko.", "SETTINGS_FEATURES_ADD": "Dodaj funkcję", "SETTINGS_FEATURES_ADD_VCP": "Kod VCP", "SETTINGS_FEATURES_VCP_LIST_DESC": "Poniżej znajduje się lista dostępnych kodów VCP zgłaszanych przez ten wyświetlacz do systemu Windows. Twinkle Tray nie sprawdza funkcjonalności ani stabilności tych kodów VCP. Używaj ich na własne ryzyko.", "SETTINGS_FEATURES_VCP_EXPECTED": "Oczekiwane wartości", "SETTINGS_TIME_SUN_TITLE": "Współrzędne położenia słońca", "SETTINGS_TIME_SUN_DESC": "Aby użyć „pozycji słońca” do regulacji czasu, wprowadź swoją aktualną szerokość i długość geograficzną, aby można było określić prawidłowe godziny.", "SETTINGS_TIME_LAT": "Szerokość", "SETTINGS_TIME_IDLE_FS_TITLE": "Aplikacje pełnoekranowe blokują mechanizm wykrywania bezczynności", "SETTINGS_TIME_IDLE_FS_DESC": "Aplikacje pełnoekranowe blokują wykrywanie bezczynności. Dotyczy to tylko okna, w którym znajduje się fokus.", "SETTINGS_HOTKEY_TARGET": "Cel akcji", "SETTINGS_PROFILES_NAME": "Nazwa profilu", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Ustaw jasność gdy aktywny", "SETTINGS_PROFILES_APP_PATH": "Ścieżka aplikacji", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Wyłącz automatyczne stosowanie znanej jasności po wszystkich zdarzeniach sprzętowych/zasilania dla określonych monitorów. Obejmuje to funkcję wykrywania bezczynności.", "SETTINGS_FEATURES_ADD_DESC": "Wprowadź kod VCP funkcji, którą chcesz dodać do swojego wyświetlacza. Należy pamiętać, że Twinkle Tray nie sprawdza, czy Twój wyświetlacz rzeczywiście obsługuje ten kod VCP. Używaj na własne ryzyko.", "SETTINGS_HOTKEY_OFF_WARN": "Ta akcja użyje opcji wybranej w „Akcji wyłączania monitora”. Jeśli zamiast tego chcesz wyłączyć określone wyświetlacze, użyj zamiast tego skrótu klawiszowego „Ustaw” lub „Cykl”.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Media blokują wykrywanie bezczynności", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Wykrywanie bezczynności zostanie wyłączone podczas odtwarzania dowolnego multimediów. Dotyczy to zarówno obrazu, jak i dźwięku. Ma to zastosowanie tylko wtedy, gdy system Windows zgłasza, że multimedia są odtwarzane.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Ilość do przewijania", "SETTINGS_HOTKEY_VALUE": "Wartość", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Wprowadź liczbę", "SETTINGS_HOTKEY_VALUES": "Wartości", "SETTINGS_HOTKEY_ADD_VALUE": "Dodaj wartość", "SETTINGS_HOTKEY_ACTION": "Akcja", "SETTINGS_HOTKEY_ADD_ACTION": "Dodaj akcję", "SETTINGS_HOTKEY_ACTION_SET": "Ustaw wartość", "SETTINGS_HOTKEY_ACTION_OFFSET": "Dostosuj wartość", "SETTINGS_HOTKEY_ACTION_CYCLE": "Cykluj listę wartości", "SETTINGS_PROFILES_TITLE": "Profile", "SETTINGS_PROFILES_DESC": "Automatycznie dostosuj jasność lub zachowanie nakładki skrótów w zależności od wybranej aplikacji. Możesz także dodać profile do menu wyświetlanego prawym przyciskiem myszy w zasobniku systemowym, aby szybko zmienić jasność na wstępnie zdefiniowane profile.", "SETTINGS_PROFILES_ADD": "Nowy profil", "SETTINGS_PROFILES_SHOW_MENU": "Pokaż w menu zasobnika prawym przyciskiem myszy", "SETTINGS_PROFILES_TRIGGER_TITLE": "Ustawienia wyzwalacza aplikacji", "SETTINGS_PROFILES_APP_DESC": "Jeśli chcesz, aby ten profil aktywował się automatycznie, gdy aktywowana jest konkretna aplikacja, wprowadź poniżej pełną lub częściową ścieżkę pliku EXE.", "SETTINGS_PROFILES_OVERLAY_DESC": "Zmienia zachowanie nakładki klawisza skrótu, gdy aktywna jest określona aplikacja. Ta funkcja nie działa, gdy profil jest aktywowany ręcznie.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Zastąp typ nakładki", "SETTINGS_FEATURES_ADD_EXISTS": "Ta funkcja jest już aktywna.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Wszystkie kody VCP zgłaszane przez ten wyświetlacz", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "Kod VCP (np. 0x12)", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Odwróć przewijanie", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Podczas przewijania kółkiem myszki nad ikoną w zasobniku systemowym kierunek przewijania zostanie odwrócony.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Wyłącz, gdy ekran jest zablokowany", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Nie uzyskuj dostępu do monitorów, gdy sesja użytkownika jest zablokowana, aby uniknąć konfliktów w środowiskach z wieloma użytkownikami.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "Ustawienia wyświetlaczy HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Włącz suwaki jasności SDR dla określonych monitorów. Monitory muszą mieć włączony HDR w systemie Windows, aby to działało.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR Zastępuje główny suwak", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Steruj jasnością SDR za pomocą głównego suwaka jasności, gdy HDR jest aktywny.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Jasność SDR", "SETTINGS_TIME_USE_SUN_POSITION": "Użyj poz. słońca", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "Połączony z jasnością", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Zatrzymaj przy tej jasności", "PANEL_LABEL_INPUTS": "Źródła sygnału", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Wykrywaj zmianę motywu", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Wykrywa zmiany akcentów/tapet/motywów w systemie Windows w celu aktualizacji ikony w zasobniku systemowym i efektu Mica. Wyłączenie tej funkcji może pomóc, jeśli aplikacja innej firmy często zmienia motyw, zwiększając zużycie procesora.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Wykrywanie stanu zasialania monitora", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Wykrywa zmiany stanu zasilania monitorów. Wyłączenie tej opcji może pomóc w przypadku występowania błędów podczas wyłączania/włączania monitorów lub gdy są one w stanie bezczynności. Aby zmiany zaczęły obowiązywać, konieczne jest ponowne uruchomienie.", "GENERIC_CALIBRATION_POINT": "Punkt kalibracji", "SETTINGS_MONITORS_CALIBRATION_DESC": "Każdy monitor może mieć indywidualne punkty kalibracji dodane w celu kompensacji różnic w krzywych jasności. Wartością wejściową jest poziom jasności wskazany na suwaku, natomiast wartością wyjściową jest rzeczywisty poziom jasności zastosowany w monitorze.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "Jeśli monitor używa niestandardowego kodu VCP dla jasności (np. 0x13 lub 0x6B) lub jeśli chcesz zmienić przypisanie suwaka jasności do innego kodu VCP, możesz wprowadzić ten kod poniżej.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "Pozostaw puste, aby zachować wartość domyślną (0x10). Obsługiwane kody można znaleźć na liście poniżej." } ================================================ FILE: src/localization/pt-BR.json ================================================ { "LANGUAGE": "Inglês", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Cancelar", "GENERIC_SAVE": "Salvar", "GENERIC_CLEAR": "Limpar", "GENERIC_OFF": "Desligado", "GENERIC_ON": "Ativar", "GENERIC_OPTIONAL": "Opcional", "GENERIC_QUIT": "Sair", "GENERIC_CLOSE": "Fechar", "GENERIC_DEFAULT": "Padrão", "GENERIC_DELETE": "Remover", "GENERIC_SETTINGS": "Configurações", "GENERIC_INSTALL": "Instalar", "GENERIC_DISMISS": "Descartar", "GENERIC_DISPLAY_SINGLE": "Monitor", "GENERIC_ALL_DISPLAYS": "Todos os monitores", "GENERIC_REFRESH_DISPLAYS": "Atualizar monitores", "GENERIC_MINIMUM": "Mín", "GENERIC_MAXIMUM": "Max", "GENERIC_NO_DISPLAYS": "Não foi detectado nenhum monitor. Por favor, conecte um monitor ao seu PC.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Não foram encontrados monitores compatíveis. Por favor, verifique se os seus monitores possuem o \"DDC/CI\" ativado.", "GENERIC_NO_DISPLAYS_SHORT": "Não foram detectados monitores compatíveis.", "PANEL_TITLE": "Ajustar o brilho", "PANEL_UPDATE_AVAILABLE": "Nova versão disponível", "PANEL_BUTTON_LINK_LEVELS": "Níveis de ligação", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Desligar monitores", "PANEL_LABEL_BRIGHTNESS": "Brilho", "PANEL_LABEL_CONTRAST": "Contraste", "PANEL_LABEL_OFF_ON": "Estado de energia", "PANEL_LABEL_COLOR_TEMPERATURE": "Temperatura de cor", "PANEL_LABEL_VOLUME": "Volume", "INTRO_TITLE": "Olá, Twinkle Tray!", "INTRO_INSTRUCTIONS": "O ícone da bandeja para Twinkle Tray provavelmente está escondido, então você deve movê-lo para algum lugar que você possa facilmente acessá-lo. Veja abaixo as instruções.", "SETTINGS_TITLE": "Configurações do Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Geral", "SETTINGS_SIDEBAR_MONITORS": "Configurações do monitor", "SETTINGS_SIDEBAR_FEATURES": "Características do DDC/CI", "SETTINGS_SIDEBAR_TIME": "Ajustes de tempo", "SETTINGS_SIDEBAR_HOTKEYS": "Teclas de Atalho", "SETTINGS_SIDEBAR_UPDATES": "Atualizações", "SETTINGS_GENERAL_TITLE": "Geral", "SETTINGS_GENERAL_STARTUP": "Abrir ao iniciar o Windows", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Ajustar o brilho ao iniciar", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Restaure o último ajuste de brilho conhecido para cada monitor quando iniciar o Twinkle Tray.", "SETTINGS_GENERAL_THEME_TITLE": "Tema", "SETTINGS_GENERAL_THEME_SYSTEM": "Preferências do sistema (padrão)", "SETTINGS_GENERAL_THEME_DARK": "Escuro", "SETTINGS_GENERAL_THEME_LIGHT": "Claro", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Idioma", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Idioma do sistema (padrão)", "SETTINGS_GENERAL_RESET_TITLE": "Redefinir configurações", "SETTINGS_GENERAL_RESET_DESC": "Pressione este botão para limpar a sua configuração.", "SETTINGS_GENERAL_RESET_BUTTON": "Redefinir configurações", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Desfoque acrílico", "SETTINGS_GENERAL_ACRYLIC_DESC": "Ativar ou desativar o desfoque em fundos transparentes no Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Dados de uso", "SETTINGS_GENERAL_ANALYTICS_DESC": "Envie dados de uso para ajudar a melhorar o Twinkle Tray. Nenhuma informação pessoal é enviada. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Saiba mais", "SETTINGS_GENERAL_SCROLL_TITLE": "Atalho de rolagem do ícone da bandeja", "SETTINGS_GENERAL_SCROLL_DESC": "Ajuste o brilho de todos os monitores ao mesmo tempo, rolando sobre o ícone da bandeja do sistema. Isto não funciona com alguns trackpads.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Ícone da bandeja", "SETTINGS_MONITORS_RATE_TITLE": "Taxa de atualização de brilho", "SETTINGS_MONITORS_RATE_DESC": "Com que frequência o brilho será atualizado em seus monitores enquanto você ajusta seus valores. Aumente o tempo se os seus monitores estiverem a cintilar.", "SETTINGS_MONITORS_RATE_0": "Bizarro", "SETTINGS_MONITORS_RATE_1": "Rápido (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Lento (1 segundo)", "SETTINGS_MONITORS_RATE_4": "Muito lento (2 segundos)", "SETTINGS_MONITORS_RENAME_TITLE": "Renomear monitores", "SETTINGS_MONITORS_RENAME_DESC": "Se você preferir um nome diferente para cada monitor (ex \"Monitor esquerdo\", \"Monitor do meio\"), você pode digitá-lo abaixo. Deixando o campo vazio, o nome original será restaurado.", "SETTINGS_MONITORS_ENTER_NAME": "Digite o nome", "SETTINGS_MONITORS_REORDER_TITLE": "Reordenar monitores", "SETTINGS_MONITORS_REORDER_DESC": "Altere a ordem em que os monitores são exibidos na bandeja. Clique e arraste para fazer alterações.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalizar o brilho", "SETTINGS_MONITORS_NORMALIZE_DESC": "Os monitores têm muitas vezes diferentes gamas de luminosidade. Ao limitar o brilho mínimo/máximo por monitor, os níveis de brilho entre monitores é muito mais consistente. Monitores similares usarão as mesmas configurações.", "SETTINGS_MONITORS_DETAILS_NAME": "Nome", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Nome interno", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Método de comunicação", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Brilho atual", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Brilho máximo", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalização de brilho", "SETTINGS_FEATURES_DESCRIPTION": "Ativar ou desativar recursos específicos de DDC/CI no painel de brilho. Pelo menos um recurso deve estar ativado para que seu monitor apareça no painel de brilho. Nem todos os monitores suportam estes recursos, como os monitores de laptop/tablet.", "SETTINGS_FEATURES_POWER_COMPAT": "Mais compatível", "SETTINGS_FEATURES_POWER_DESC": "Quando enviando o comando DDC/CI para desligar seu monitor, o(s) seguinte valor será enviado.", "SETTINGS_TIME_TITLE": "Ajustes da hora do dia", "SETTINGS_TIME_DESC": "Ajuste automaticamente os seus monitores para um nível de brilho específico em um momento desejado. Todos os monitores serão ajustados para os mesmos níveis normalizados.", "SETTINGS_TIME_ADD": "Adicionar programação", "SETTINGS_TIME_REMOVE": "Remover programação", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Definir brilho para monitores individuais", "SETTINGS_TIME_INDIVIDUAL_DESC": "Configure o brilho por monitor, em vez de para todos os monitores ao mesmo tempo.", "SETTINGS_TIME_STARTUP_TITLE": "Verificar na inicialização da aplicação", "SETTINGS_TIME_STARTUP_DESC": "Ajuste o brilho para corresponder ao tempo mais relevante quando o Twinkle Tray inicia.", "SETTINGS_HOTKEYS_TITLE": "Teclas de atalho", "SETTINGS_HOTKEYS_DESC": "Configure as teclas de atalho para ajustar o brilho de um ou de todos os monitores.", "SETTINGS_HOTKEYS_ADD": "Adicionar tecla de atalho", "SETTINGS_HOTKEYS_REMOVE": "Remover tecla de atalho", "SETTINGS_HOTKEYS_INCREASE": "Aumentar o brilho", "SETTINGS_HOTKEYS_DECREASE": "Diminuir o brilho", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Pressione as teclas aqui", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Nível de ajuste de brilho", "SETTINGS_HOTKEYS_LEVEL_DESC": "Quanto o brilho deve ser ajustado ao usar as teclas de atalho.", "SETTINGS_UPDATES_TITLE": "Atualizações", "SETTINGS_UPDATES_VERSION": "Você tem Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Verificação automática de novas versões", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Quando houver uma nova versão, ela será mostrada no painel de brilho.", "SETTINGS_UPDATES_MS_STORE": "Para verificar novas versões, visite a Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Nova versão do Twinkle Tray disponível!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Atualizado. A versão atual inclui as seguintes alterações:", "SETTINGS_UPDATES_DOWNLOADING": "Baixando atualização…", "SETTINGS_UPDATES_DOWNLOAD": "Baixar & Instalar {{1}}", "GENERIC_MINUTES": "minutos", "GENERIC_SECONDS": "segundos", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Se o Twinkle Tray não responder ao clicar no ícone do tabuleiro ou não detectar os seus monitores, pode tentar desactivar certos métodos de detecção de monitores. Reinicie a Twinkle Tray para que as alterações tenham efeito. {{1}}", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Ocultar exposição interna inactiva", "SETTINGS_HOTKEYS_TOD_TITLE": "Desligar a ação de visualização", "SETTINGS_HOTKEYS_TOD_DESC": "Personalizar o sinal enviado ao utilizar a tecla de atalho ou o ícone Turn Off Displays. O sinal de software exibirá um ecrã preto até que a entrada (ex. rato ou teclado) seja detectada pelo Windows. O sinal de hardware desligará a alimentação dos monitores.", "SETTINGS_HOTKEYS_BREAK_TITLE": "As teclas de atalho quebram os níveis ligados", "SETTINGS_HOTKEYS_BREAK_DESC": "Ao utilizar uma tecla de atalho para uma única visualização e \"níveis ligados\" estiver activa, esta será desactivada.", "SETTINGS_GENERAL_MICA_TITLE": "Borrão de Mica", "SETTINGS_GENERAL_MICA_DESC": "Activar ou desactivar o borrão atrás dos fundos em Twinkle Tray.", "SETTINGS_FEATURES_UNSUPPORTED": "Este monitor não suporta características DDC/CI.", "SETTINGS_TIME_IDLE_DESC": "Quando não for detectada qualquer entrada durante um período de tempo, o brilho de todos os ecrãs será reduzido.", "SETTINGS_HOTKEYS_TOD_NONE": "Nenhum (ícone de esconder)", "SETTINGS_HOTKEYS_TOD_SOFT": "Sinal de software (predefinido)", "SETTINGS_HOTKEYS_TOD_HARD": "Sinal de Hardware* (apenas DDC/CI)", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Quando a tampa estiver fechada ou o visor interno tiver sido desactivado no Windows, esconda o selector de brilho no painel.", "SETTINGS_TIME_IDLE_TITLE": "Detecção de inactividade", "SETTINGS_HOTKEYS_TOD_BOTH": "Sinal de hardware* & software", "SETTINGS_HOTKEYS_TOD_NOTE": "*Nota: Nem todos os monitores DDC/CI apoiam esta funcionalidade.", "PANEL_LABEL_TURN_OFF": "Apagar", "PANEL_LABEL_TURN_ON": "Ligar", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Verificar valores atuais", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Sempre obtenha os valores mais recentes do monitor ao abrir o painel de brilho. Ative esta opção se o brilho (ou outros códigos VCP, como contraste) mudar com frequência de fora da bandeja cintilante.", "GENERIC_PAUSE_TOD": "Pausar Ajustes do tempo", "SETTINGS_GENERAL_TROUBLESHOOTING": "Solução de problemas", "SETTINGS_HOTKEY_ACTION": "Ação", "SETTINGS_HOTKEY_ACTION_CYCLE": "Percorrer lista de valores", "SETTINGS_HOTKEY_ACTION_OFFSET": "Ajustar valor", "SETTINGS_HOTKEY_ACTION_SET": "Definir valor", "SETTINGS_HOTKEY_ADD_VALUE": "Adicionar valor", "SETTINGS_HOTKEY_OFF_WARN": "Essa ação utilizará a opção selecionada em \"Desligar a ação de visualização\". Se você deseja desligar telas específicas, então use a ação \"Definir\" ou \"Percorrer lista\".", "SETTINGS_HOTKEY_TARGET": "Alvo", "SETTINGS_HOTKEY_VALUE": "Valor", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Insira um número", "SETTINGS_HOTKEY_VALUES": "Valores", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Desabilitar a sobreposição", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Ocultar monitores", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Se você gostaria de esconder exposições específicas do flyout, você pode alterná-las aqui.", "SETTINGS_TIME_TRANSITON_TITLE": "Velocidade de transição de luminosidade", "SETTINGS_TIME_TRANSITON_DESC": "Quão rapidamente o brilho deve transitar quando os ajustes da hora do dia são ativados.", "SETTINGS_TIME_ANIMATE_DESC": "Os valores de brilho serão animados entre o evento atual e o próximo evento programado. Pode aumentar o uso da CPU. Ajustes manuais de luminosidade serão rapidamente sobrescritos enquanto isto estiver ativo.", "GENERIC_PAUSE_IDLE": "Pausar detecção inativa", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Habilitar métodos de detecção de monitor", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Se a camada de hotkey da Twinkle Tray estiver interferindo nas aplicações em tela cheia, você pode desativá-la aqui.", "SETTINGS_TIME_ANIMATE_TITLE": "Animar entre os tempos", "GENERIC_SPEED_INSTANT": "Instantâneo", "GENERIC_SPEED_SLOW": "Lento", "GENERIC_SPEED_VERY_SLOW": "Muito lento", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_DDC_WARNING": "Características do DDC/CI podem fazer com que seu monitor não responda. Use por sua própria conta e risco.", "GENERIC_SPEED_FAST": "Rápido", "GENERIC_SPEED_VERY_FAST": "Muito rápido", "SETTINGS_UPDATES_CHANNEL": "Canal de atualização", "SETTINGS_UPDATES_BRANCH_STABLE": "Estável (padrão)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Apagar", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Mais compatível", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Aplicar brilho automaticamente", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Ignorar a aplicação automática em monitores específicos", "SETTINGS_GENERAL_OVERLAY_TITLE": "Padrão de comportamento da sobreposição", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Legado DDC/CI Método de detecção", "SETTINGS_GENERAL_REPORT_TITLE": "Gerar relatório", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR substitui o controle deslizante principal", "SETTINGS_FEATURES_POWER_TITLE": "Sinal do estado de energia", "SETTINGS_FEATURES_POWER_STANDBY": "Espera", "SETTINGS_TIME_SUN_TITLE": "Coordenadas para a posição do sol", "SETTINGS_TIME_IDLE_FS_TITLE": "Aplicativos de tela cheia bloqueiam a detecção de ociosidade", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Detecção de ociosidade de blocos de mídia", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Quantidade a ser rolada", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Inverter rolagem", "SETTINGS_TIME_IDLE_FS_DESC": "Os aplicativos em tela cheia bloqueiam a detecção de ociosidade. Isso se aplica apenas à janela focada.", "SETTINGS_PROFILES_DESC": "Ajuste automaticamente o brilho ou o comportamento de sobreposição de atalho, dependendo do aplicativo em foco. Você também pode adicionar perfis ao menu do botão direito do mouse na bandeja do sistema para alterar rapidamente o brilho para perfis predefinidos.", "SETTINGS_PROFILES_APP_DESC": "Se você quiser que esse perfil seja ativado automaticamente quando um aplicativo específico estiver em foco, insira o caminho completo ou parcial do EXE abaixo.", "SETTINGS_PROFILES_OVERLAY_DESC": "Altera o comportamento da sobreposição de teclas de atalho quando o aplicativo especificado está em foco. Esse recurso não funciona quando o perfil é ativado manualmente.", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Ao rolar sobre o ícone da bandeja do sistema, a direção de rolagem será invertida.", "SETTINGS_TIME_SUN_DESC": "Para usar a \"posição do sol\" para ajustes de tempo, insira sua latitude e longitude atuais para que os horários corretos possam ser determinados.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Desativar na tela de bloqueio", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Não acesse monitores enquanto a sessão do usuário estiver bloqueada para evitar conflitos em ambientes multiusuário.", "SETTINGS_GENERAL_OVERLAY_DESC": "Com que força a sobreposição da tecla de atalho de brilho tentará ser exibida sobre outros aplicativos. Você não deve precisar ajustar isso.", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "A sobreposição será exibida na maioria das janelas, mas não se forçará acima dos aplicativos marcados como \"sempre no topo\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Forçado a continuar", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Sempre tente mostrar a sobreposição em cima de outras janelas. Isso pode causar problemas com jogos exclusivos em tela cheia e outros aplicativos em tela cheia. Também pode acionar o anti-cheat em alguns jogos.", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Use o método antigo v1.15.5 para detectar exibições DDC/CI.", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Se o seu monitor responder de forma estranha depois de desligá-lo/ligá-lo ou desconectar/conectar o hardware, desabilitar isso pode ajudar.", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Desative a aplicação automática de brilho conhecido após todos os eventos de hardware/energia para monitores específicos. Isso inclui o recurso de detecção de marcha lenta.", "SETTINGS_TIME_LAT": "Latitude", "SETTINGS_TIME_LONG": "Longitude", "SETTINGS_TIME_SUN_GET": "Obter coordenadas", "SETTINGS_TIME_IDLE_MEDIA_DESC": "A detecção de inatividade será desativada enquanto qualquer mídia estiver sendo reproduzida. Isso inclui vídeo e áudio. Isso só se aplica quando o Windows relata que a mídia está sendo reproduzida.", "SETTINGS_PROFILES_TITLE": "Perfis", "SETTINGS_PROFILES_ADD": "Novo Perfil", "SETTINGS_PROFILES_NAME": "Nome do perfil", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Definir brilho quando ativo", "SETTINGS_PROFILES_SHOW_MENU": "Mostrar no menu da bandeja do botão direito", "SETTINGS_PROFILES_TRIGGER_TITLE": "Configurações de gatilho do aplicativo", "SETTINGS_PROFILES_APP_PATH": "Caminho do aplicativo", "SETTINGS_PROFILES_OVERLAY_TITLE": "Substituir tipo de sobreposição", "SETTINGS_GENERAL_REPORT_DESC": "Salve um arquivo de texto com informações sobre seus monitores e configurações para depuração.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "Configurações de exibição HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Ative os controles deslizantes de brilho SDR para monitores específicos. Os monitores devem ter o HDR habilitado no Windows para que isso funcione.", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Controle o brilho SDR no controle deslizante de brilho principal enquanto o HDR está ativo.", "SETTINGS_FEATURES_POWER_WARNING": "É mais provável que a opção \"Standby\" permita ligar/desligar o monitor na bandeja cintilante. No entanto, muitos monitores não respondem corretamente à alteração do estado de energia. Use por sua conta e risco.", "SETTINGS_FEATURES_ADD": "Adicionar recurso", "SETTINGS_FEATURES_ADD_DESC": "Insira o código VCP para o recurso que deseja adicionar ao seu monitor. Observe que o Twinkle Tray não valida se o seu monitor realmente suporta este código VCP. Use por sua conta e risco.", "SETTINGS_FEATURES_ADD_VCP": "Código VCP", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "Código VCP (Ex. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Esse recurso já está ativo.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Todos os códigos VCP relatados por este monitor", "SETTINGS_FEATURES_VCP_LIST_DESC": "A seguir está uma lista de códigos VCP disponíveis relatados por este monitor para Windows. O Twinkle Tray não valida a funcionalidade ou a estabilidade desses códigos VCP. Use-os por sua conta e risco.", "SETTINGS_FEATURES_VCP_EXPECTED": "Valores esperados", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Brilho SDR", "GENERIC_NOT_SUPPORTED": "Não compatível", "GENERIC_SUPPORTED": "Compatível", "GENERIC_UNSUPPORTED": "Sem suporte", "GENERIC_ACTIVE": "Ativo", "GENERIC_DETECTING_DISPLAYS": "Detectando telas…", "PANEL_LABEL_INPUTS": "Entradas", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Estilo de interface Windows", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Detecção de atualização de tema", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Monitora detecção do estado de energia", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_TIME_USE_SUN_POSITION": "Usar nascer do sol e pôr do sol", "SETTINGS_HOTKEY_ADD_ACTION": "Adicionar ação", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Detecta mudanças de papel de parede e tema no Windows para atualizar o ícone da barra de tarefas e o efeito de transparência. Desativar esse recurso pode ajudar caso algum aplicativo esteja alterando o tema com frequência, elevando o uso de CPU.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Detecta alterações no estado de energia dos monitores. Desativar esse recurso pode ajudar caso você enfrente erros quando os monitores são ligados, desligados ou ficam inativos. Requer reinicialização para entrar em vigor." } ================================================ FILE: src/localization/pt.json ================================================ { "LANGUAGE": "Português", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Cancelar", "GENERIC_SAVE": "Gravar", "GENERIC_CLEAR": "Limpar", "GENERIC_DELETE": "Eliminar", "GENERIC_OFF": "Desativar", "GENERIC_ON": "Ativar", "GENERIC_QUIT": "Sair", "GENERIC_CLOSE": "Fechar", "GENERIC_SETTINGS": "Configurações", "GENERIC_INSTALL": "Instalar", "GENERIC_DISMISS": "Descartar", "GENERIC_DEFAULT": "Predefinição", "GENERIC_OPTIONAL": "Opcional", "GENERIC_DISPLAY_SINGLE": "Monitor", "GENERIC_ALL_DISPLAYS": "Todos os monitores", "GENERIC_REFRESH_DISPLAYS": "Atualizar monitores", "GENERIC_MINIMUM": "Mín", "GENERIC_MAXIMUM": "Max", "GENERIC_NO_DISPLAYS": "Não foi detectado nenhum monitor. Por favor, conecte um monitor ao seu PC.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Não foram encontrados monitores compatíveis. Por favor, verifique se os seus monitores possuem o \"DDC/CI\" ativado.", "GENERIC_NO_DISPLAYS_SHORT": "Não foram detectados monitores compatíveis.", "GENERIC_NOT_SUPPORTED": "Não suportado", "GENERIC_SUPPORTED": "Suportado", "GENERIC_UNSUPPORTED": "Incompatível", "GENERIC_ACTIVE": "Ativo", "GENERIC_SECONDS": "segundos", "GENERIC_MINUTES": "minutos", "GENERIC_DDC_WARNING": "Características do DDC/CI, como o controle do estado de energia, podem fazer com que o seu monitor não responda. Use por sua própria conta e risco.", "GENERIC_SPEED_INSTANT": "Instantâneo", "GENERIC_SPEED_SLOW": "Lento", "GENERIC_SPEED_VERY_SLOW": "Muito lento", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_SPEED_FAST": "Rápido", "GENERIC_SPEED_VERY_FAST": "Muito rápido", "GENERIC_PAUSE_TOD": "Ajustes do tempo de pausa", "GENERIC_PAUSE_IDLE": "Pausa para detecção de ociosidade", "GENERIC_DETECTING_DISPLAYS": "A detetar monitores…", "PANEL_TITLE": "Ajustar o brilho", "PANEL_UPDATE_AVAILABLE": "Nova versão disponível", "PANEL_BUTTON_LINK_LEVELS": "Níveis de ligação", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Desligar monitores", "PANEL_LABEL_BRIGHTNESS": "Brilho", "PANEL_LABEL_CONTRAST": "Contraste", "PANEL_LABEL_INPUTS": "Entradas", "PANEL_LABEL_OFF_ON": "Estado de energia", "PANEL_LABEL_COLOR_TEMPERATURE": "Temperatura de cor", "PANEL_LABEL_VOLUME": "Volume", "PANEL_LABEL_TURN_OFF": "Desligar a energia", "PANEL_LABEL_TURN_ON": "Ligar a energia", "INTRO_TITLE": "Olá, Twinkle Tray!", "INTRO_INSTRUCTIONS": "O ícone da bandeja para Twinkle Tray provavelmente está escondido, então deve movê-lo para algum lugar que possa facilmente acessá-lo. Veja abaixo as instruções.", "SETTINGS_TITLE": "Configurações do Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Geral", "SETTINGS_SIDEBAR_MONITORS": "Configurações do monitor", "SETTINGS_SIDEBAR_FEATURES": "Características do DDC/CI", "SETTINGS_SIDEBAR_TIME": "Ajustes de tempo", "SETTINGS_SIDEBAR_HOTKEYS": "Teclas de Atalho", "SETTINGS_SIDEBAR_UPDATES": "Atualizações", "SETTINGS_GENERAL_TITLE": "Geral", "SETTINGS_GENERAL_STARTUP": "Abrir ao iniciar o Windows", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Ajustar o brilho ao iniciar", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Restaure o último ajuste de brilho conhecido para cada monitor quando iniciar o Twinkle Tray.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Desativar no ecrã de bloqueio", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Não aceder aos monitores enquanto a sessão do utilizador estiver bloqueada para evitar conflitos em ambientes multiutilizador.", "SETTINGS_GENERAL_THEME_TITLE": "Tema", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Estilo da IU do Windows", "SETTINGS_GENERAL_THEME_SYSTEM": "Preferências do sistema (padrão)", "SETTINGS_GENERAL_THEME_DARK": "Escuro", "SETTINGS_GENERAL_THEME_LIGHT": "Claro", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Idioma", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Idioma do sistema (padrão)", "SETTINGS_GENERAL_RESET_TITLE": "Redefinir configurações", "SETTINGS_GENERAL_RESET_DESC": "Pressione este botão para limpar a sua configuração.", "SETTINGS_GENERAL_RESET_BUTTON": "Redefinir configurações", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Desfoque acrílico", "SETTINGS_GENERAL_ACRYLIC_DESC": "Ativar ou desativar o desfoque em fundos transparentes no Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Borrão de Mica", "SETTINGS_GENERAL_MICA_DESC": "Activar ou desactivar o borrão atrás dos fundos em Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Dados de uso", "SETTINGS_GENERAL_ANALYTICS_DESC": "Envie dados de uso para ajudar a melhorar o Twinkle Tray. Nenhuma informação pessoal é enviada. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Saiba mais", "SETTINGS_GENERAL_SCROLL_TITLE": "Atalho de rolagem do ícone da bandeja", "SETTINGS_GENERAL_SCROLL_DESC": "Ajuste o brilho de todos os monitores ao mesmo tempo, rolando sobre o ícone da bandeja do sistema. Isto não funciona com alguns trackpads.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Ícone da bandeja", "SETTINGS_GENERAL_TROUBLESHOOTING": "Solução de problemas", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Desativar os métodos de detecção do monitor", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Se o Twinkle Tray não responder ao clicar no ícone do tabuleiro ou não detetar os seus monitores, pode tentar desactivar certos métodos de detecção de monitores. Reinicie a Twinkle Tray para que as alterações tenham efeito. {{1}}", "SETTINGS_GENERAL_OVERLAY_TITLE": "Comportamento predefinido da sobreposição", "SETTINGS_GENERAL_OVERLAY_DESC": "Define quão agressivamente a sobreposição das teclas de brilho tenta apresentar-se sobre outras aplicações. Normalmente não é necessário alterar esta opção.", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Desativar a sobreposição", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Se a camada de hotkey da Twinkle Tray estiver interferindo nas aplicações em ecrã inteiro, pode desativá-la aqui.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Mais compatível", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "A sobreposição é apresentada sobre a maioria das janelas, mas não se força acima de aplicações marcadas como \"sempre no topo\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Forçar apresentação", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Tentar sempre apresentar a sobreposição acima de outras janelas. Pode causar problemas com jogos em ecrã inteiro exclusivo e ativar sistemas anti-cheat.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Método antigo de deteção DDC/CI", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Utiliza o método v1.15.5 para detetar monitores DDC/CI.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Aplicar brilho automaticamente", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Se o monitor se comportar de forma estranha após o desligar/ligar ou ao ligar/desligar hardware, desativar esta opção poderá ajudar.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Ignorar aplicação automática em monitores específicos", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Desativa a aplicação automática do brilho conhecido após eventos de hardware/energia para monitores específicos, incluindo a função de deteção de inatividade.", "SETTINGS_GENERAL_REPORT_TITLE": "Gerar relatório", "SETTINGS_GENERAL_REPORT_DESC": "Guarda um ficheiro de texto com informações sobre os monitores e definições para efeitos de depuração.", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Deteção de alterações de tema", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Deteta alterações de acento/papel de parede/tema no Windows para atualizar o ícone da bandeja e o efeito Mica. Desativar pode ajudar se uma aplicação de terceiros estiver a alterar o tema com frequência.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Deteção do estado de energia dos monitores", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Deteta alterações no estado de energia dos monitores. Desativar pode ajudar se ocorrerem erros quando os monitores são desligados/ligados ou entram em repouso. Requer reiniciar para efetivar.", "SETTINGS_MONITORS_RATE_TITLE": "Taxa de atualização de brilho", "SETTINGS_MONITORS_RATE_DESC": "Com que frequência o brilho será atualizado nos seus monitores enquanto ajusta os valores deles. Aumente o tempo se os seus monitores estiverem a cintilar.", "SETTINGS_MONITORS_RATE_0": "Bizarro", "SETTINGS_MONITORS_RATE_1": "Rápido (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Lento (1 segundo)", "SETTINGS_MONITORS_RATE_4": "Muito lento (2 segundos)", "SETTINGS_MONITORS_RENAME_TITLE": "Renomear monitores", "SETTINGS_MONITORS_RENAME_DESC": "Se preferir um nome diferente para cada monitor (ex \"Monitor esquerdo\", \"Monitor do meio\"), pode digitá-lo abaixo. Se deixar o campo vazio, o nome original será restaurado.", "SETTINGS_MONITORS_ENTER_NAME": "Digite o nome", "SETTINGS_MONITORS_REORDER_TITLE": "Reordenar monitores", "SETTINGS_MONITORS_REORDER_DESC": "Altere a ordem em que os monitores são exibidos na bandeja. Clique e arraste para fazer alterações.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalizar o brilho", "SETTINGS_MONITORS_NORMALIZE_DESC": "Os monitores têm muitas vezes diferentes gamas de luminosidade. Ao limitar o brilho mínimo/máximo por monitor, os níveis de brilho entre monitores é muito mais consistente. Monitores similares usarão as mesmas configurações.", "SETTINGS_MONITORS_DETAILS_NAME": "Nome", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Nome interno", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Método de comunicação", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Brilho atual", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Brilho máximo", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalização de brilho", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Ocultar exposição interna inactiva", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Quando a tampa estiver fechada ou o visor interno tiver sido desactivado no Windows, esconda o selector de brilho no painel.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Ocultar monitores", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Se gostaria de esconder exposições específicas do flyout, pode alterná-las aqui.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "Definições de monitores HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Ativa controlos de brilho SDR para monitores específicos. Os monitores têm de ter o HDR ativo no Windows para que funcione.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "O SDR substitui o controlo principal", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Controla o brilho SDR através do controlo principal enquanto o HDR está ativo.", "SETTINGS_FEATURES_DESCRIPTION": "Ativar ou desativar recursos específicos de DDC/CI no painel de brilho. Pelo menos um recurso deve estar ativado para que o seu monitor apareça no painel de brilho. Nem todos os monitores suportam estes recursos, como os monitores de laptop/tablet.", "SETTINGS_FEATURES_UNSUPPORTED": "Este monitor não suporta características DDC/CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Obter Brilho de Corrente", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Obtenha sempre o mais recente nível de brilho do monitor ao abrir a página de brilho. Activar isto se o brilho for alterado frequentemente a partir do exterior do Twinkle Tray (ex. outra aplicação).", "SETTINGS_FEATURES_POWER_TITLE": "Sinal do estado de energia", "SETTINGS_FEATURES_POWER_DESC": "Ao enviar o comando DDC/CI para desligar o monitor, serão enviados os seguintes valores.", "SETTINGS_FEATURES_POWER_STANDBY": "Espera", "SETTINGS_FEATURES_POWER_OFF": "Desligar a energia", "SETTINGS_FEATURES_POWER_COMPAT": "Mais compatível", "SETTINGS_FEATURES_POWER_WARNING": "A opção \"Espera\" é mais propensa a permitir ligar/desligar o monitor a partir do Twinkle Tray. Contudo, muitos monitores não respondem corretamente a mudanças de estado de energia. Utilize por sua conta e risco.", "SETTINGS_FEATURES_ADD": "Adicionar funcionalidade", "SETTINGS_FEATURES_ADD_DESC": "Introduza o código VCP da funcionalidade que pretende adicionar ao monitor. O Twinkle Tray não valida se o monitor suporta realmente esse código. Utilize por sua conta e risco.", "SETTINGS_FEATURES_ADD_VCP": "Código VCP", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "Código VCP (Ex. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Esta funcionalidade já está ativa.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Todos os códigos VCP reportados por este monitor", "SETTINGS_FEATURES_VCP_LIST_DESC": "Segue-se a lista de códigos VCP disponibilizados por este monitor ao Windows. O Twinkle Tray não valida a funcionalidade ou estabilidade destes códigos. Use-os por sua conta e risco.", "SETTINGS_FEATURES_VCP_EXPECTED": "Valores esperados", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Brilho SDR", "SETTINGS_TIME_TITLE": "Ajustes da hora do dia", "SETTINGS_TIME_DESC": "Ajuste automaticamente os seus monitores para um nível de brilho específico num momento desejado. Todos os monitores serão ajustados para os mesmos níveis normalizados.", "SETTINGS_TIME_ADD": "Adicionar programação", "SETTINGS_TIME_REMOVE": "Remover programação", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Definir brilho para monitores individuais", "SETTINGS_TIME_INDIVIDUAL_DESC": "Configure o brilho por monitor, em vez de para todos os monitores ao mesmo tempo.", "SETTINGS_TIME_TRANSITON_TITLE": "Velocidade de transição de luminosidade", "SETTINGS_TIME_TRANSITON_DESC": "Quão rapidamente o brilho deve transitar quando os ajustes da hora do dia são ativados.", "SETTINGS_TIME_STARTUP_TITLE": "Verificar na inicialização da aplicação", "SETTINGS_TIME_STARTUP_DESC": "Ajuste o brilho para corresponder ao tempo mais relevante quando o Twinkle Tray inicia.", "SETTINGS_TIME_IDLE_TITLE": "Detecção de inactividade", "SETTINGS_TIME_IDLE_DESC": "Quando não for detectada qualquer entrada durante um período de tempo, o brilho de todos os ecrãs será reduzido.", "SETTINGS_TIME_ANIMATE_TITLE": "Animar entre os tempos", "SETTINGS_TIME_ANIMATE_DESC": "Os valores de brilho serão animados entre o evento atual e o próximo evento programado. Pode aumentar o uso da CPU. Ajustes manuais de luminosidade serão rapidamente sobrescritos enquanto isto estiver ativo.", "SETTINGS_TIME_SUN_TITLE": "Coordenadas para a posição do sol", "SETTINGS_TIME_SUN_DESC": "Para usar a \"posição do sol\" nos ajustes de tempo, introduza a latitude e longitude atuais para que os horários sejam calculados corretamente.", "SETTINGS_TIME_USE_SUN_POSITION": "Utilizar posição do sol", "SETTINGS_TIME_LAT": "Latitude", "SETTINGS_TIME_LONG": "Longitude", "SETTINGS_TIME_SUN_GET": "Obter coordenadas", "SETTINGS_TIME_IDLE_FS_TITLE": "Aplicações em ecrã inteiro bloqueiam a deteção de inatividade", "SETTINGS_TIME_IDLE_FS_DESC": "As aplicações em ecrã inteiro bloqueiam a deteção de inatividade. Apenas se aplica à janela em foco.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Multimédia bloqueia a deteção de inatividade", "SETTINGS_TIME_IDLE_MEDIA_DESC": "A deteção de inatividade é desativada enquanto houver reprodução de multimédia (vídeo ou áudio). Apenas se aplica quando o Windows reporta que existe multimédia em reprodução.", "SETTINGS_HOTKEYS_TITLE": "Teclas de atalho", "SETTINGS_HOTKEYS_DESC": "Configure as teclas de atalho para ajustar o brilho de um ou de todos os monitores.", "SETTINGS_HOTKEYS_ADD": "Adicionar tecla de atalho", "SETTINGS_HOTKEYS_REMOVE": "Remover tecla de atalho", "SETTINGS_HOTKEYS_INCREASE": "Aumentar o brilho", "SETTINGS_HOTKEYS_DECREASE": "Diminuir o brilho", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Pressione as teclas aqui", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Nível de ajuste de brilho", "SETTINGS_HOTKEYS_LEVEL_DESC": "Quanto o brilho deve ser ajustado ao usar as teclas de atalho.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Quantidade de deslocação", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Inverter deslocação", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Ao deslocar sobre o ícone da bandeja do sistema, a direção da deslocação é invertida.", "SETTINGS_HOTKEYS_TOD_TITLE": "Desligar a acção de visualização", "SETTINGS_HOTKEYS_TOD_DESC": "Personalize o sinal enviado quando usar a tecla de atalho ou ícone Desligar Ecrãs. O sinal do software exibirá um ecrã preto até que a entrada (ex. rato ou teclado) seja detetada pelo Windows. O sinal em hardware desligará a energia dos monitores.", "SETTINGS_HOTKEYS_TOD_NONE": "Nenhum (ícone de esconder)", "SETTINGS_HOTKEYS_TOD_SOFT": "Sinal de software (predefinido)", "SETTINGS_HOTKEYS_TOD_HARD": "Sinal de Hardware* (apenas DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Sinal de hardware* & software", "SETTINGS_HOTKEYS_TOD_NOTE": "*Nota: Nem todos os monitores DDC/CI apoiam esta funcionalidade.", "SETTINGS_HOTKEYS_BREAK_TITLE": "As teclas de atalho quebram os níveis ligados", "SETTINGS_HOTKEYS_BREAK_DESC": "Ao utilizar uma tecla de atalho para uma única visualização e \"níveis ligados\" estiver activa, esta será desactivada.", "SETTINGS_HOTKEY_OFF_WARN": "Esta ação utiliza a opção selecionada em \"Desligar a acção de visualização\". Se pretender desligar monitores específicos, utilize as ações \"Definir\" ou \"Percorrer\".", "SETTINGS_HOTKEY_TARGET": "Destino da ação", "SETTINGS_HOTKEY_VALUE": "Valor", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Introduza um número", "SETTINGS_HOTKEY_VALUES": "Valores", "SETTINGS_HOTKEY_ADD_VALUE": "Adicionar valor", "SETTINGS_HOTKEY_ADD_ACTION": "Adicionar ação", "SETTINGS_HOTKEY_ACTION": "Ação", "SETTINGS_HOTKEY_ACTION_SET": "Definir valor", "SETTINGS_HOTKEY_ACTION_OFFSET": "Ajustar valor", "SETTINGS_HOTKEY_ACTION_CYCLE": "Percorrer lista de valores", "SETTINGS_PROFILES_TITLE": "Perfis", "SETTINGS_PROFILES_DESC": "Ajusta automaticamente o brilho ou o comportamento da sobreposição consoante a aplicação em foco. Também pode adicionar perfis ao menu de contexto da bandeja para aplicar rapidamente perfis predefinidos.", "SETTINGS_PROFILES_ADD": "Novo perfil", "SETTINGS_PROFILES_NAME": "Nome do perfil", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Definir brilho quando ativo", "SETTINGS_PROFILES_SHOW_MENU": "Mostrar no menu de contexto da bandeja", "SETTINGS_PROFILES_TRIGGER_TITLE": "Definições de ativação da aplicação", "SETTINGS_PROFILES_APP_PATH": "Caminho da aplicação", "SETTINGS_PROFILES_APP_DESC": "Introduza o caminho completo ou parcial do EXE se pretender ativar este perfil automaticamente quando uma aplicação específica estiver em foco.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Substituir tipo de sobreposição", "SETTINGS_PROFILES_OVERLAY_DESC": "Altera o comportamento da sobreposição das teclas de atalho quando a aplicação especificada está em foco. Não tem efeito quando o perfil é ativado manualmente.", "SETTINGS_UPDATES_TITLE": "Atualizações", "SETTINGS_UPDATES_VERSION": "Tem Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Verificação automática de novas versões", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Quando houver uma nova versão, ela será mostrada no painel de brilho.", "SETTINGS_UPDATES_MS_STORE": "Para verificar novas versões, visite a Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Nova versão do Twinkle Tray disponível!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Atualizado. A versão atual inclui as seguintes alterações:", "SETTINGS_UPDATES_DOWNLOADING": "A descarregar uma atualização…", "SETTINGS_UPDATES_DOWNLOAD": "Descarregarr & Instalar {{1}}", "SETTINGS_UPDATES_CHANNEL": "Canal de atualização", "SETTINGS_UPDATES_BRANCH_STABLE": "Estável (padrão)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta" } ================================================ FILE: src/localization/ro.json ================================================ { "LANGUAGE": "Română", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Anulează", "GENERIC_SAVE": "Salvează", "GENERIC_CLEAR": "Șterge", "GENERIC_OFF": "Oprit", "GENERIC_ON": "Pornit", "GENERIC_QUIT": "Ieșire", "GENERIC_CLOSE": "Închide", "GENERIC_SETTINGS": "Setări", "GENERIC_INSTALL": "Instalează", "GENERIC_DISMISS": "Renunță", "GENERIC_DISPLAY_SINGLE": "Monitor", "GENERIC_ALL_DISPLAYS": "Toate monitoarele", "GENERIC_REFRESH_DISPLAYS": "Reîmprospătează monitoarele", "GENERIC_MINIMUM": "Minim", "GENERIC_MAXIMUM": "Maxim", "GENERIC_NO_DISPLAYS": "Nu a fost detectat niciun monitor. Vă rog conectați un monitor la calculator.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Niciun monitor compatibil nu a fost detectat. Te rog verifică dacă opțiunea \"DDC/CI\" este activată pentru monitoare.", "GENERIC_NO_DISPLAYS_SHORT": "Niciun monitor compatibil nu a fost detectat.", "GENERIC_SECONDS": "secunde", "GENERIC_MINUTES": "minute", "GENERIC_DDC_WARNING": "Funcțiile DDC/CI precum controlul alimentării pot face ca monitorul dumneavoastră să nu mai răspună. Utilizați-le pe propria răspundere.", "GENERIC_SPEED_INSTANT": "Instant", "GENERIC_SPEED_SLOW": "Lent", "GENERIC_SPEED_VERY_SLOW": "Foarte lent", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_SPEED_FAST": "Rapid", "GENERIC_SPEED_VERY_FAST": "Foarte rapid", "GENERIC_PAUSE_TOD": "Configurări ale timpului de pauză", "GENERIC_PAUSE_IDLE": "Întrerupeți detectarea inactivității", "PANEL_TITLE": "Configurați luminozitatea", "PANEL_UPDATE_AVAILABLE": "O nouă versiune este disponibilă", "PANEL_BUTTON_LINK_LEVELS": "Folosiți același nivel de luminozitate pentru toate monitoarele", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Oprește monitoarele", "PANEL_LABEL_BRIGHTNESS": "Luminozitate", "PANEL_LABEL_CONTRAST": "Contrast", "PANEL_LABEL_OFF_ON": "Starea de funcționare", "PANEL_LABEL_COLOR_TEMPERATURE": "Temperatura Culorii", "PANEL_LABEL_VOLUME": "Volume", "PANEL_LABEL_TURN_OFF": "Oprește", "INTRO_TITLE": "Bun venit, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Iconița din bara de sistemului a Twinkle Tray probabil a fost ascună, are trebui mutată într-un loc mai ușor accesibil. Pentru instrucțiuni, vezi mai jos.", "SETTINGS_TITLE": "Stări Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "General", "SETTINGS_SIDEBAR_MONITORS": "Setări Monitor", "SETTINGS_SIDEBAR_FEATURES": "Caracteristici DDC/CI", "SETTINGS_SIDEBAR_TIME": "Setări pentru timp", "SETTINGS_SIDEBAR_HOTKEYS": "Taste și Comenzi rapide", "SETTINGS_SIDEBAR_UPDATES": "Actualizări", "SETTINGS_GENERAL_TITLE": "General", "SETTINGS_GENERAL_STARTUP": "Pornește automat la deschidrea Calculatorului", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Aplică luminozitatea la pornirea sistemul", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Restabilește ultima luminozitate cunoscută pentru fiecare monitor, atunci când Twinkle Tray pornește.", "SETTINGS_GENERAL_THEME_TITLE": "Temă", "SETTINGS_GENERAL_THEME_SYSTEM": "Conform sistemului (implicit)", "SETTINGS_GENERAL_THEME_DARK": "Întunecat", "SETTINGS_GENERAL_THEME_LIGHT": "Luminos", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Limba", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Limba sistemului (implicit)", "SETTINGS_GENERAL_RESET_TITLE": "Resetează setările", "SETTINGS_GENERAL_RESET_DESC": "Apasă acest buton, pentru a șterge confingurările făcute.", "SETTINGS_GENERAL_RESET_BUTTON": "Resetează setările", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Acrilic Blur", "SETTINGS_GENERAL_ACRYLIC_DESC": "Activați or dezactivăți estomparea din spatele fundalurilor transparente din Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Mica Blur", "SETTINGS_GENERAL_MICA_DESC": "Activați sau dezactivați estomparea din spatele fundalurilor din Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analize", "SETTINGS_GENERAL_ANALYTICS_DESC": "Trimiteți datele de utilizare pentru a ajuta la îmbunătățirea Twinkle Tray. Nu se vor transmite date personale. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Aflați mai multe", "SETTINGS_GENERAL_SCROLL_TITLE": "Comandă rapidă de derulare a pictogramei din bara de sistem", "SETTINGS_GENERAL_SCROLL_DESC": "Reglați luminozitatea tuturor monitoarelor deodată, prin derluarea pictogramei din bara de sistem. Aceasă funcție nu este compatibilă cu unele trackpad-uri.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Pictograma din bara de sistem", "SETTINGS_GENERAL_TROUBLESHOOTING": "Depanare", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Dezactivăți metodele de detectare a monitorului", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Dacă Twinkle Tray nu răspunde când dați click pe pictograma din bara de activități sau nu găsește monitoarele dumneavoastră, puteți încerca să dezactivați anumite metode de detectare a monitorului. Reporniți Twinkle Tray pentru ca schimbările să aibă efect. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Dezactivați suprapunerea", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Dacă tastele rapide configurate în Twinkle Tray se suprapun cu cele ale aplicaților afișate pe întregul ecran, le puteți dezactiva aici.", "SETTINGS_MONITORS_RATE_TITLE": "Rata de actualizare a luminozității", "SETTINGS_MONITORS_RATE_DESC": "Cât de des va fi actualizată luminozitatea monitoarelor dumneavoastră, pe măsură ce configurați nivelul acesteia. Creșteți timpul, dacă monitoarele dumneavoastă pâlpâie (flickering).", "SETTINGS_MONITORS_RATE_0": "Ludicrous", "SETTINGS_MONITORS_RATE_1": "Rapid (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Lent (1 second)", "SETTINGS_MONITORS_RATE_4": "Foarte lent (2 seconds)", "SETTINGS_MONITORS_RENAME_TITLE": "Redenumiți monitoarele", "SETTINGS_MONITORS_RENAME_DESC": "Dacă preferați un alt nume pentru fiecare monitor (ex \"Monitorul din stânga\", \"Monitorul din mijloc\"), puteți să îl Introduceți mai jos. Dacă lăsați câmpul gol, se va restabili numele original.", "SETTINGS_MONITORS_ENTER_NAME": "Introduceți numele", "SETTINGS_MONITORS_REORDER_TITLE": "Reordonați monitoarele", "SETTINGS_MONITORS_REORDER_DESC": "Modificați oridnea în care monitoarele sunt afișate în bara de sistem. Dați click și trageți pentru a efectua modificări.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Echilibrarea luminozității", "SETTINGS_MONITORS_NORMALIZE_DESC": "De obicei, invervalele de luminozitate al monitoarelor diferă. Prin limitarea luminozității minime/maxime pentru fiecare monitor, nivelul de luminozitate între acestea devine mult mai echilbrat. Monitoarele similare vor utiliza aceleași setări.", "SETTINGS_MONITORS_DETAILS_NAME": "Nume", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Denumirea internă", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Metoda de comunicare", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Luminozitatea curentă", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Luminozitatea maximă", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Echilibrarea luminozității", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Ascundeți monitorul integrat inactiv", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Când capacul laptopului este închis sau când monitorul integrat a fost dezactivat în Windows, ascundeți bara de luminozitate din panou.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Ascundeți monitoarele", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Dacă doriți să ascundeți anumite monitoare din meniu, le puteți dezactiva aici.", "SETTINGS_FEATURES_DESCRIPTION": "Activați sau dezactivați funcțiile specifice DDC/CI din panoul de luminozitate. Cel puțin o funcție trebuie să fie activată pentru ca monitorul dvs. să apară în panoul de luminozitate. Nu toate monitoarele acceptă aceste caracteristici, cum ar fi cele integrate ale laptopurilor/tabletelor.", "SETTINGS_FEATURES_UNSUPPORTED": "Acest monitor nu suportă funcționalitățile DDC/CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Obțineți luminozitatatea curentă", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Obțineți întotdeauna cel mai recent nivel de luminozitate de la monitor atunci când deschideți pagina de luminozitate. Activați această opțiune doar dacă luminozitatea este schimbată frecvent din afara Twinkle Tray (de ex. o altă aplicație).", "SETTINGS_TIME_TITLE": "Configurări în fucție de oră", "SETTINGS_TIME_DESC": "Setatți automat luminozitatea monitoarelor pentru timpul dorit. Toate monitoarele vor avea aceeași luminozitate, nivelul acesteia fiind echilibrat.", "SETTINGS_TIME_ADD": "Adăugați o oră", "SETTINGS_TIME_REMOVE": "Eliminați ora", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Setați luminozitatea în mod individual pentru monitoare", "SETTINGS_TIME_INDIVIDUAL_DESC": "Configurați luminozitatea pentru fiecare monitor în mod separat, iar nu pentru toate monitoarele concomitent.", "SETTINGS_TIME_TRANSITON_TITLE": "Viteza de tranziție a luminozității", "SETTINGS_TIME_TRANSITON_DESC": "Cât de rapid ar trebui să se facă tranziția luminozității când este activată configurare nivelului acesteia în funcție de oră.", "SETTINGS_TIME_STARTUP_TITLE": "Verificați la pornirea aplicației", "SETTINGS_TIME_STARTUP_DESC": "Reglați luminozitatea pentru a se potrivi cu momentul cel mai relevant în care începe Twinkle Tray.", "SETTINGS_TIME_IDLE_TITLE": "Detectarea inactivității", "SETTINGS_TIME_IDLE_DESC": "Atuncit când nicio activitate nu a mai fost detectată pentru o anumită perioadă de timp, luminozitatea tuturor monitoarelor va fi redusă.", "SETTINGS_TIME_ANIMATE_TITLE": "Schimbați nivelul gradual între intervalele de timp", "SETTINGS_TIME_ANIMATE_DESC": "Valorile luminozității vor fi gradual schimbate între evenimentul curent și următorul eveniment programat. Acesta poate crește utilizarea CPU. Orice configurare manuală a luminozității va fi rapid suprascrisă cât timp această funcție este activă.", "SETTINGS_HOTKEYS_TITLE": "Taste de acces rapid", "SETTINGS_HOTKEYS_DESC": "Configurați scurtăturile pentu ajustarea luminozității unuia sau tuturor monitoarelor.", "SETTINGS_HOTKEYS_ADD": "Adăugați o tastă rapidă", "SETTINGS_HOTKEYS_REMOVE": "Ștergeți o tastă rapidă", "SETTINGS_HOTKEYS_INCREASE": "Cresțeți luminozitatatea", "SETTINGS_HOTKEYS_DECREASE": "Reduceți luminozitatatea", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Apăsați aici tastele", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Configurați nivelul de luminozitate", "SETTINGS_HOTKEYS_LEVEL_DESC": "Care este nivelul de shcimbare a luminozității când folosiți scurtăturile.", "SETTINGS_HOTKEYS_TOD_TITLE": "Opriți monitoarele", "SETTINGS_HOTKEYS_TOD_DESC": "Modificați semnalul ce va fi transims atunci când veți utiliza scurtătura funcției Opriți Ecranele sau pictograma acesteia. Semanul software va afișa ecranul negru până când o acțiune (ex. mouse sau tastatură) este detectată de către sistemul de operare Windows. Semnalul hardware va opri alimentare monitoarelor.", "SETTINGS_HOTKEYS_TOD_NONE": "Niciunl (ascundeți pictograma)", "SETTINGS_HOTKEYS_TOD_SOFT": "Semnal software (implicit)", "SETTINGS_HOTKEYS_TOD_HARD": "Semnal hardware* (doar DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Semnal hardware* & software", "SETTINGS_HOTKEYS_TOD_NOTE": "*Notă: Nu toate monitoarele compatibile DDC/CI acceptă această funcție.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Tastă rapidă pentru a opri controlul simultan al luminozității tuturor monitoarelor", "SETTINGS_HOTKEYS_BREAK_DESC": "Atuci când se utilizează o scurtătură pentru un singur monitor și funcția \"control simultan\" este activată, aceasta se va dezactiva.", "SETTINGS_UPDATES_TITLE": "Actualizări", "SETTINGS_UPDATES_VERSION": "Aveți Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Verificați în mod automat pentru versiuni mai noi", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Atunci când este disponibilă o versiune nouă, aceasta va fi afișată în panoul de luminozitate.", "SETTINGS_UPDATES_MS_STORE": "Pentru a verifica dacă exită versiuni mai noi, acesați aplicația Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "O nouă versiune a aplicației Twinkle Tray este disponibilă!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Actualizată. Versiunea curentă include următoarele modificări:", "SETTINGS_UPDATES_DOWNLOADING": "Se descarcă actulizarea…", "SETTINGS_UPDATES_DOWNLOAD": "Descărcați și instalați {{1}}", "SETTINGS_UPDATES_CHANNEL": "Canalul de actualizare", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabil (implicit)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Oprește", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Luminozitate" } ================================================ FILE: src/localization/ru.json ================================================ { "LANGUAGE": "Russian", "GENERIC_OK": "ОК", "GENERIC_CANCEL": "Отмена", "GENERIC_SAVE": "Сохранить", "GENERIC_CLEAR": "Очистить", "GENERIC_OFF": "Выкл", "GENERIC_ON": "Вкл", "GENERIC_QUIT": "Выйти", "GENERIC_CLOSE": "Закрыть", "GENERIC_SETTINGS": "Настройки", "GENERIC_INSTALL": "Установить", "GENERIC_DISMISS": "Отклонить", "GENERIC_DISPLAY_SINGLE": "Дисплей", "GENERIC_ALL_DISPLAYS": "Все дисплеи", "GENERIC_MINIMUM": "Мин", "GENERIC_MAXIMUM": "Макс", "GENERIC_NO_DISPLAYS": "Дисплеи не обнаружены. Пожалуйста, подключите дисплей к ПК.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Совместимых дисплеев не найдено. Пожалуйста, проверьте, что \"DDC/CI\" включен для ваших дисплеев.", "GENERIC_NO_DISPLAYS_SHORT": "Совместимых дисплеев не обнаружено.", "PANEL_TITLE": "Регулировка яркости", "PANEL_UPDATE_AVAILABLE": "Доступна новая версия", "PANEL_BUTTON_LINK_LEVELS": "Одновременная регулировка", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Выключить дисплеи", "INTRO_TITLE": "Привет, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Значок Twinkle Tray в панели задач вероятно скрыт, поэтому вы должны переместить его в то место, где можно легко получить к нему доступ. Инструкции см. ниже.", "SETTINGS_TITLE": "Настройки Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Общие", "SETTINGS_SIDEBAR_MONITORS": "Настройки монитора", "SETTINGS_SIDEBAR_TIME": "Корректировки по времени", "SETTINGS_SIDEBAR_HOTKEYS": "Сочетание клавиш и команды", "SETTINGS_SIDEBAR_UPDATES": "Обновления", "SETTINGS_GENERAL_TITLE": "Общие", "SETTINGS_GENERAL_STARTUP": "Запускать при запуске системы", "SETTINGS_GENERAL_THEME_TITLE": "Тема", "SETTINGS_GENERAL_THEME_SYSTEM": "Системные настройки (по умолчанию)", "SETTINGS_GENERAL_THEME_DARK": "Ночная", "SETTINGS_GENERAL_THEME_LIGHT": "Дневная", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Язык", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Язык системы (по умолчанию)", "SETTINGS_GENERAL_RESET_TITLE": "Сброс настроек", "SETTINGS_GENERAL_RESET_DESC": "Нажмите эту кнопку, чтобы очистить ваш конфиг.", "SETTINGS_GENERAL_RESET_BUTTON": "Сбросить настройки", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Аналитика", "SETTINGS_GENERAL_ANALYTICS_DESC": "Отправлять данные об использовании, чтобы помочь улучшить Twinkle Tray. Личная информация не отправляется. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Подробнее", "SETTINGS_MONITORS_RATE_TITLE": "Частота обновления яркости", "SETTINGS_MONITORS_RATE_DESC": "Как часто яркость будет обновляться на ваших дисплеях, когда вы регулируете их значения. Увеличьте время, если ваши дисплеи мерцают.", "SETTINGS_MONITORS_RATE_0": "Моментально", "SETTINGS_MONITORS_RATE_1": "Быстро (250 мс)", "SETTINGS_MONITORS_RATE_2": "Нормально (500 мс)", "SETTINGS_MONITORS_RATE_3": "Медленно (1 секунда)", "SETTINGS_MONITORS_RATE_4": "Очень медленно (2 секунды)", "SETTINGS_MONITORS_RENAME_TITLE": "Переименование мониторов", "SETTINGS_MONITORS_RENAME_DESC": "Если вы предпочитаете другое название для каждого монитора (например, \"Левый монитор\", \"Средний монитор\"), вы можете ввести его ниже. Если оставить это поле пустым, будет восстановлено исходное имя.", "SETTINGS_MONITORS_ENTER_NAME": "Введите название", "SETTINGS_MONITORS_REORDER_TITLE": "Упорядочивание мониторов", "SETTINGS_MONITORS_REORDER_DESC": "Измените порядок отображения мониторов в панели задач. Нажмите и перетащите, чтобы внести изменения.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Нормализация яркости", "SETTINGS_MONITORS_NORMALIZE_DESC": "Мониторы часто имеют различные диапазоны яркости. Ограничение мин/макс значение яркости каждого дисплея обеспечивает более равномерный уровень яркости между дисплеями.", "SETTINGS_TIME_TITLE": "Корректировка по времени суток", "SETTINGS_TIME_DESC": "Автоматически устанавливать мониторы на определенный уровень яркости в нужное время. Все мониторы будут установлены на одинаковые, нормализованные уровни.", "SETTINGS_TIME_ADD": "Добавить время", "SETTINGS_TIME_REMOVE": "Удалить время", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Настройка яркости для отдельных дисплеев", "SETTINGS_TIME_INDIVIDUAL_DESC": "Настройте яркость для каждого дисплея, а не для всех дисплеев сразу.", "SETTINGS_TIME_STARTUP_TITLE": "Проверка при запуске приложения", "SETTINGS_TIME_STARTUP_DESC": "Регулировка яркости в соответствии с наиболее подходящим временем при запуске Twinkle Tray.", "SETTINGS_HOTKEYS_TITLE": "Сочетание клавиш", "SETTINGS_HOTKEYS_DESC": "Настройка сочетания клавиш для регулировки яркости одного или всех дисплеев.", "SETTINGS_HOTKEYS_ADD": "Добавить сочетание клавиш", "SETTINGS_HOTKEYS_REMOVE": "Удалить сочетание клавиш", "SETTINGS_HOTKEYS_INCREASE": "Увеличение яркости", "SETTINGS_HOTKEYS_DECREASE": "Уменьшение яркости", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Нажмите клавиши здесь", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Регулировка уровня яркости", "SETTINGS_HOTKEYS_LEVEL_DESC": "Насколько яркость должна регулироваться при использовании горячих клавиш.", "SETTINGS_UPDATES_TITLE": "Обновления", "SETTINGS_UPDATES_VERSION": "Версия Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Автоматическая проверка наличия новых версий", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Когда появится новая версия, информация будет показана на панели яркости.", "SETTINGS_UPDATES_MS_STORE": "Чтобы проверить наличие новых версий, посетите Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Доступна новая версия Twinkle Tray!", "SETTINGS_UPDATES_NONE_AVAILABLE": "В актуальном состоянии. Текущая версия включает в себя следующие изменения:", "SETTINGS_UPDATES_DOWNLOADING": "Загрузка обновлений…", "SETTINGS_UPDATES_DOWNLOAD": "Скачать и установить {{1}}", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Показывать иконку в трее", "SETTINGS_GENERAL_ACRYLIC_DESC": "Включите или отключите размытие за прозрачным фоном в Twinkle Tray.", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Акриловое размытие", "SETTINGS_GENERAL_SCROLL_DESC": "Регулируйте яркость всех дисплеев одновременно, прокручивая поверх значка на панели задач. Это не работает с некоторыми трекпадами.", "SETTINGS_GENERAL_SCROLL_TITLE": "Скроллинг поверх значка на панели задач", "SETTINGS_MONITORS_FEATURES_DESCRIPTION": "Включите или отключите определенные функции DDC/CI на панели яркости. По крайней мере одна функция должна быть включена, чтобы ваш монитор отображался на панели яркости. Не все дисплеи поддерживают эти функции, например дисплеи ноутбуков и планшетов.", "SETTINGS_MONITORS_FEATURES_TITLE": "Функции DDC/CI", "PANEL_LABEL_COLOR_TEMPERATURE": "Цветовая температура", "PANEL_LABEL_OFF_ON": "Состояние питания", "PANEL_LABEL_CONTRAST": "Контрастность", "PANEL_LABEL_INPUTS": "Входы", "PANEL_LABEL_BRIGHTNESS": "Яркость", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Нормализация яркости", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Максимальная яркость", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Текущая яркость", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Способ связи", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Внутреннее название", "SETTINGS_MONITORS_DETAILS_NAME": "Название", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Применять яркость при запуске", "SETTINGS_SIDEBAR_FEATURES": "Функции DDC/CI", "GENERIC_REFRESH_DISPLAYS": "Обновить дисплеи", "PANEL_LABEL_VOLUME": "Громкость", "SETTINGS_HOTKEYS_TOD_NONE": "Не использовать (скрыть значок)", "SETTINGS_HOTKEYS_TOD_NOTE": "* Примечание: не все мониторы DDC/CI поддерживают эту функцию.", "SETTINGS_HOTKEYS_TOD_BOTH": "Аппаратный* и программный сигнал", "SETTINGS_HOTKEYS_TOD_HARD": "Аппаратный* сигнал (только DDC/CI)", "SETTINGS_HOTKEYS_TOD_SOFT": "Программный сигнал (по умолчанию)", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Восстановить последнее значение яркости для каждого дисплея при запуске программы.", "SETTINGS_FEATURES_DESCRIPTION": "Включить или выключить специфические возможности DDC/CI в панели яркости. Хотя бы одна возможность должна быть включена для вашего монитора чтобы отображаться в панели яркости. Не все дисплеи (например ноутбуки/планшеты) поддерживают данные возможности.", "SETTINGS_HOTKEYS_TOD_DESC": "Выберите тип сигнала, отправляемый по нажатию кнопки \"Выключить дисплеи\". Программный сигнал будет показывать чёрный экран, пока Windows не обнаружит активность от любого из устройств ввода (например, мыши или клавиатуры). Аппаратный сигнал отключит питание мониторов.", "SETTINGS_HOTKEYS_TOD_TITLE": "Действие кнопки \"Выключить дисплеи\"", "SETTINGS_HOTKEYS_BREAK_TITLE": "Сочетания клавиш отключают одновременную регулировку", "SETTINGS_HOTKEYS_BREAK_DESC": "Отключает одновременную регулировку яркости при использовании сочетаний клавиш, настроенных для одного монитора.", "SETTINGS_GENERAL_MICA_DESC": "Включить или выключить размытие заднего фона в Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Размытие Mica", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Скрыть неактивный экран ноутбука", "GENERIC_SECONDS": "секунд", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Когда крышка ноутбука закрыта или экран ноутбука был отключен в Windows, скрыть его слайдер яркости на панели.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Всегда получать актуальные значения с монитора при открытии панели яркости. Включите эту опцию, если яркость (или другие VCP-коды, например контрастность) часто изменяются вне Twinkle Tray.", "SETTINGS_TIME_IDLE_TITLE": "Обнаружение простоя", "PANEL_LABEL_TURN_OFF": "Выключить", "SETTINGS_TIME_IDLE_DESC": "Снижать яркость всех дисплеев при отсутствии активности в течение какого-то времени.", "SETTINGS_FEATURES_UNSUPPORTED": "Этот монитор не поддерживает функции DCC/CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Получать актуальные значения", "GENERIC_MINUTES": "минут", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Если Twinkle Tray не реагирует на нажатие на значок в трее или не обнаруживает ваши мониторы, вы можете попробовать отключить некоторые методы обнаружения мониторов. Перезапустите Twinkle Tray, чтобы изменения вступили в силу. {{1}}", "GENERIC_PAUSE_IDLE": "Приостановить обнаружение простоя", "SETTINGS_UPDATES_BRANCH_STABLE": "Стабильный (по умолчанию)", "GENERIC_PAUSE_TOD": "Приостановить корректировки по времени", "SETTINGS_GENERAL_TROUBLESHOOTING": "Устранение неполадок", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Включить методы обнаружения монитора", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Отключить оверлей", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Если оверлей горячих клавиш Twinkle Tray мешает работе полноэкранных приложений, вы можете отключить его здесь.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Скрыть дисплеи", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Если вы хотите скрыть определенные дисплеи из всплывающего окна, вы можете отключить их здесь.", "SETTINGS_TIME_TRANSITON_TITLE": "Скорость перехода яркости", "SETTINGS_TIME_TRANSITON_DESC": "Как быстро должна переключаться яркость при включении регулировки времени суток.", "SETTINGS_TIME_ANIMATE_TITLE": "Анимировать время", "GENERIC_SPEED_INSTANT": "Мгновенно", "GENERIC_SPEED_SLOW": "Медленный", "GENERIC_SPEED_VERY_SLOW": "Очень медленно", "GENERIC_SPEED_NORMAL": "Нормальный", "GENERIC_SPEED_FAST": "Быстрый", "GENERIC_SPEED_VERY_FAST": "Очень быстро", "GENERIC_DDC_WARNING": "Функции DDC/CI, могут привести к тому, что ваш монитор перестанет реагировать. Используйте их на свой страх и риск.", "SETTINGS_UPDATES_CHANNEL": "Канал обновлений", "SETTINGS_TIME_ANIMATE_DESC": "Значения яркости будут анимированы между текущим и следующим запланированным событием. Может увеличить использование процессора. Ручные настройки яркости будут быстро перезаписываться, пока эта функция активна.", "SETTINGS_UPDATES_BRANCH_BETA": "Бета", "SETTINGS_FEATURES_POWER_OFF": "Выключить", "GENERIC_DELETE": "Удалить", "GENERIC_DEFAULT": "По умолчанию", "GENERIC_OPTIONAL": "Опционально", "SETTINGS_HOTKEY_ACTION": "Действие", "SETTINGS_HOTKEY_ACTION_SET": "Присвоить значение", "SETTINGS_HOTKEY_ACTION_OFFSET": "Изменить значение", "SETTINGS_HOTKEY_ADD_VALUE": "Добавить значение", "PANEL_LABEL_TURN_ON": "Включить", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Отключить на экране блокировки", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Не взаимодействовать с мониторами, пока пользовательская сессия заблокирована, чтобы избежать конфликты при использовании системы несколькими пользователями.", "SETTINGS_PROFILES_APP_DESC": "Если вы хотите, чтобы этот профиль активировался автоматически при выборе конкретного приложения, введите полный или частичный путь к исполняемому файлу ниже.", "SETTINGS_PROFILES_TRIGGER_TITLE": "Настройки триггера приложения", "SETTINGS_PROFILES_APP_PATH": "Путь к приложению", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Установка яркости при включении", "SETTINGS_PROFILES_NAME": "Имя профиля", "SETTINGS_PROFILES_ADD": "Новый профиль", "SETTINGS_PROFILES_TITLE": "Профили", "SETTINGS_HOTKEY_ACTION_CYCLE": "Список значений цикла", "SETTINGS_GENERAL_OVERLAY_TITLE": "Оформление оверлея по умолчанию", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Наиболее совместимый", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Оверлей будет отображаться поверх большинства окон, но не будет отображаться над приложениями, которые помечены как \"поверх других приложений\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Принудительно включено", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Всегда пытаться показывать оверлей поверх других окон. Возможны проблемы с приложениями в полноэкранном режиме, включая игры. Может активировать системы защиты от читов в отдельных играх.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Устаревший метод обнаружения DDC/CI", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Использовать старый метод обнаружения дисплеев DDC/CI версии 1.15.5.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Автоматически применять яркость", "SETTINGS_GENERAL_REPORT_TITLE": "Создать отчет", "SETTINGS_GENERAL_REPORT_DESC": "Сохраните текстовый файл с информацией о ваших мониторах и настройках для отладки.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Переопределить тип оверлея", "SETTINGS_PROFILES_SHOW_MENU": "Показать в контекстном меню", "SETTINGS_HOTKEY_VALUES": "Значения", "SETTINGS_HOTKEY_VALUE": "Значение", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Шаг прокрутки", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Инвертировать прокрутку", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "При прокрутке значка в системном трее направление прокрутки будет инвертировано.", "SETTINGS_TIME_LAT": "Широта", "SETTINGS_TIME_LONG": "Долгота", "SETTINGS_TIME_SUN_GET": "Установить координаты", "SETTINGS_TIME_SUN_TITLE": "Координаты для положения солнца", "SETTINGS_TIME_SUN_DESC": "Чтобы использовать \"положение солнца\" для настройки времени, введите ваши текущие широту и долготу, чтобы можно было определить правильное время.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Яркость SDR", "SETTINGS_FEATURES_VCP_EXPECTED": "Ожидаемые значения", "SETTINGS_FEATURES_ADD_VCP": "VCP Код", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP код (Ex. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Эта функция уже активна.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Все коды VCP, отображаемые на этом дисплее", "SETTINGS_FEATURES_VCP_LIST_DESC": "Ниже приведен список доступных VCP-кодов, которые отображаются на этом дисплее в Windows. Приложение Twinkle Tray не проверяет функциональность или стабильность этих VCP-кодов. Используйте их на свой страх и риск.", "SETTINGS_FEATURES_ADD": "Добавить функцию", "SETTINGS_FEATURES_ADD_DESC": "Введите VCP-код для функции, которую вы хотите добавить в свой дисплей. Обратите внимание, что Twinkle Tray не проверяет, поддерживает ли ваш дисплей этот VCP-код. Используйте на свой страх и риск.", "SETTINGS_FEATURES_POWER_COMPAT": "Наиболее совместимый", "SETTINGS_FEATURES_POWER_STANDBY": "Режим ожидания", "SETTINGS_FEATURES_POWER_TITLE": "Сигнал состояния питания", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Управляйте яркостью SDR с помощью основного ползунка яркости, пока включена функция HDR.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR Заменяет основной ползунок", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Активировать ползунки яркости SDR для определённых мониторов. Для работы необходимо включить HDR для этих мониторов в Windows.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "Настройки HDR дисплея", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Если ваш монитор работает некорректно после включения/выключения или подключения/отключения оборудования, отключение этой функции может помочь.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Пропускать автонастройку для выбранных мониторов", "SETTINGS_PROFILES_OVERLAY_DESC": "Изменяет поведение наложения горячих клавиш при фокусировке на указанном приложении. Эта функция не работает, если профиль активирован вручную.", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Определение бездействия будет отключено, пока воспроизводится любой медиаконтент — видео или аудио. Учитывается только то, что Windows распознаёт как активное воспроизведение.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Отключать определение бездействия при воспроизведении медиаконтента", "SETTINGS_TIME_IDLE_FS_DESC": "Полноэкранные приложения блокируют определение бездействия. Учитывается только активное окно.", "SETTINGS_TIME_IDLE_FS_TITLE": "Полноэкранные приложения блокируют определение бездействия", "SETTINGS_PROFILES_DESC": "Автоматически регулировать яркость или режим наложения ярлыков в зависимости от выбранного приложения. Вы также можете добавить профили в контекстное меню значка в области трея, чтобы быстро переключаться на предустановленные режимы яркости.", "SETTINGS_FEATURES_POWER_DESC": "При отправке команды DDC/CI для выключения дисплея будут отправлены следующие значения.", "SETTINGS_FEATURES_POWER_WARNING": "Опция \"Режим ожидания\", позволит включать/выключать монитор из меню Twinkle Tray. Однако многие мониторы неправильно реагируют на изменение режима питания. Используйте на свой страх и риск.", "SETTINGS_HOTKEY_TARGET": "Цель действия", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Введите число", "SETTINGS_HOTKEY_OFF_WARN": "Это действие будет использовать параметр, выбранный в разделе \"Выключить дисплеи\". Если вы хотите отключить определенные дисплеи, используйте действие «присвоить значение» или «цикл» горячих клавиш.", "SETTINGS_GENERAL_OVERLAY_DESC": "Как будет отображаться оверлей яркости поверх других приложений. Настройка не требуется.", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Отключить автоматическое восстановление сохранённой яркости после всех аппаратных событий и событий управления питанием для выбранных мониторов. Включая функцию определения бездействия.", "GENERIC_NOT_SUPPORTED": "Нет", "GENERIC_SUPPORTED": "Поддерживается", "GENERIC_UNSUPPORTED": "Не поддерживает", "GENERIC_ACTIVE": "Активно", "GENERIC_DETECTING_DISPLAYS": "Поиск мониторов…", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Стиль интерфейса Windows", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Отслеживание изменений темы, обоев или акцентов Windows для обновления иконки в трее и эффекта Mica. Отключение этой функции может снизить нагрузку на процессор, если сторонние программы часто меняют оформление системы.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Обнаруживает изменения состояния питания мониторов. Отключение этой функции может помочь, если вы сталкиваетесь с ошибками при включении/выключении мониторов или их переходе в спящий режим. Для вступления изменений в силу требуется перезагрузка.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Отслеживание состояния питания мониторов", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_TIME_USE_SUN_POSITION": "Использовать положение солнца", "SETTINGS_HOTKEY_ADD_ACTION": "Добавить действие", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "Оставьте поле пустым для значения по умолчанию (0x10). Поддерживаемые коды можно найти в списке ниже.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "Если ваш монитор использует нестандартный VCP-код для управления яркостью (например, 0x13 или 0x6B) или вы хотите переназначить ползунок яркости на другой VCP-код, введите его ниже.", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Остановить после этого уровня яркости", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "Привязать к яркости", "SETTINGS_MONITORS_CALIBRATION_DESC": "Для каждого монитора можно добавить индивидуальные точки калибровки, чтобы компенсировать различия в кривых яркости. Входное значение — это уровень яркости, установленный на ползунке, а выходное значение — фактический уровень яркости, применяемый к монитору.", "GENERIC_CALIBRATION_POINT": "Точка калибровки" } ================================================ FILE: src/localization/sk.json ================================================ { "LANGUAGE": "Slovenčina", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Zrušiť", "GENERIC_SAVE": "Uložiť", "GENERIC_CLEAR": "Vymazať", "GENERIC_OFF": "Vypnúť", "GENERIC_ON": "Zapnúť", "GENERIC_QUIT": "Ukončiť", "GENERIC_CLOSE": "Zatvoriť", "GENERIC_SETTINGS": "Nastavenia", "GENERIC_INSTALL": "Inštalovať", "GENERIC_DISMISS": "Odmietnuť", "GENERIC_DISPLAY_SINGLE": "Displej", "GENERIC_ALL_DISPLAYS": "Všetky displeje", "GENERIC_REFRESH_DISPLAYS": "Obnoviť displeje", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Max", "GENERIC_NO_DISPLAYS": "Neboli zistené žiadne displeje. Pripojte prosím displej k vášmu PC.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Neboli nájdené žiadne kompatibilné displeje. Skontrolujte, či je \"DDC/CI\" povolené pre vaše displeje.", "GENERIC_NO_DISPLAYS_SHORT": "Neboli zistené žiadne kompatibilné displeje.", "GENERIC_SECONDS": "sekúnd", "GENERIC_MINUTES": "minút", "GENERIC_DDC_WARNING": "DDC/CI funkcie môžu spôsobiť, že váš monitor prestane reagovať. Používajte na vlastné nebezpečenstvo.", "GENERIC_SPEED_INSTANT": "Okamžité", "GENERIC_SPEED_SLOW": "Pomalé", "GENERIC_SPEED_VERY_SLOW": "Veľmi pomalé", "GENERIC_SPEED_NORMAL": "Normálne", "GENERIC_SPEED_FAST": "Rýchle", "GENERIC_SPEED_VERY_FAST": "Veľmi rýchle", "GENERIC_PAUSE_TOD": "Pozastaviť úpravy času", "GENERIC_PAUSE_IDLE": "Pozastaviť detekciu nečinnosti", "PANEL_TITLE": "Nastavenie jasu", "PANEL_UPDATE_AVAILABLE": "K dispozícii je nová verzia", "PANEL_BUTTON_LINK_LEVELS": "Prepojiť úrovne", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Vypnúť displeje", "PANEL_LABEL_BRIGHTNESS": "Jas", "PANEL_LABEL_CONTRAST": "Kontrast", "PANEL_LABEL_OFF_ON": "Stav napájania", "PANEL_LABEL_COLOR_TEMPERATURE": "Teplota farieb", "PANEL_LABEL_VOLUME": "Hlasitosť", "PANEL_LABEL_TURN_OFF": "Vypnúť displej", "INTRO_TITLE": "Ahoj, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Ikona panela pre Twinkle Tray je pravdepodobne skrytá, takže ju musíte presunúť na miesto, kde ju budete mať ľahko prístupnú. Pozrite nižšie pokyny.", "SETTINGS_TITLE": "Nastavenia Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Všeobecné", "SETTINGS_SIDEBAR_MONITORS": "Nastavenia monitorov", "SETTINGS_SIDEBAR_FEATURES": "Funkcie DDC/CI", "SETTINGS_SIDEBAR_TIME": "Úpravy času", "SETTINGS_SIDEBAR_HOTKEYS": "Skratky", "SETTINGS_SIDEBAR_UPDATES": "Aktualizácie", "SETTINGS_GENERAL_TITLE": "Všeobecné", "SETTINGS_GENERAL_STARTUP": "Spustiť pri štarte", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Použiť jas pri štarte", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Obnoviť posledný známy jas pre každý displej po spustení Twinkle Tray.", "SETTINGS_GENERAL_THEME_TITLE": "Téma", "SETTINGS_GENERAL_THEME_SYSTEM": "Systémové preferencie (predvolené)", "SETTINGS_GENERAL_THEME_DARK": "Tmavé", "SETTINGS_GENERAL_THEME_LIGHT": "Svetlé", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Jazyk", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Jazyk systému (predvolené)", "SETTINGS_GENERAL_RESET_TITLE": "Obnoviť nastavenia", "SETTINGS_GENERAL_RESET_DESC": "Kliknutím na toto tlačidlo vymažete svoju konfiguráciu.", "SETTINGS_GENERAL_RESET_BUTTON": "Obnoviť nastavenia", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akrylové rozmazanie", "SETTINGS_GENERAL_ACRYLIC_DESC": "Povoľte alebo zakážte rozmazanie za transparentnými pozadiami v Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Mica rozmazanie", "SETTINGS_GENERAL_MICA_DESC": "Povoľte alebo zakážte rozmazanie pozadia v Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analytika", "SETTINGS_GENERAL_ANALYTICS_DESC": "Posielajte údaje o používaní, aby ste pomohli vylepšiť Twinkle Tray. Žiadne osobné údaje nie sú odosielané. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Zistiť viac", "SETTINGS_GENERAL_SCROLL_TITLE": "Skratka pre posuvník panela", "SETTINGS_GENERAL_SCROLL_DESC": "Pomocou posúvania cez ikonu systémového panela môžete zvýšiť jas všetkých displejov naraz. S niektorými trackpadmi toto nepracuje.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Ikona panela", "SETTINGS_GENERAL_TROUBLESHOOTING": "Odstraňovanie problémov", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Aktivovať metódy detekcie monitorov", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Ak Twinkle Tray neodpovedá pri kliknutí na ikonu panela alebo nedeteguje vaše displeje, môžete skúsiť deaktivovať určité metódy detekcie monitorov. Pre uplatnenie zmien je potrebné reštartovať Twinkle Tray. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Deaktivovať prekrytie", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Ak prekrytie klávesových skratiek Twinkle Tray ruší režim celoobrazovkových aplikácií, môžete ho tu deaktivovať.", "SETTINGS_MONITORS_RATE_TITLE": "Frekvencia aktualizácie jasu", "SETTINGS_MONITORS_RATE_DESC": "Ako často sa bude aktualizovať jas na vašich displejoch pri úprave ich hodnôt. Ak vaše displeje blikajú, zvýšte čas.", "SETTINGS_MONITORS_RATE_0": "Neskutočne", "SETTINGS_MONITORS_RATE_1": "Rýchle (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normálne (500 ms)", "SETTINGS_MONITORS_RATE_3": "Pomalé (1 sekunda)", "SETTINGS_MONITORS_RATE_4": "Veľmi pomalé (2 sekundy)", "SETTINGS_MONITORS_RENAME_TITLE": "Premenovať monitory", "SETTINGS_MONITORS_RENAME_DESC": "Ak preferujete iné meno pre každý monitor (napr. \"Ľavý monitor\", \"Stredný monitor\"), môžete ho tu zadať. Ak pole ponecháte prázdne, obnoví sa pôvodné meno.", "SETTINGS_MONITORS_ENTER_NAME": "Zadajte názov", "SETTINGS_MONITORS_REORDER_TITLE": "Zmeniť poradie monitorov", "SETTINGS_MONITORS_REORDER_DESC": "Zmeňte poradie, v akom sú monitory zobrazené v paneli. Kliknite a ťahajte na vykonanie zmien.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalizovať jas", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitory často majú rôzne rozsahy jasu. Obmedzením min/max jasu pre každý displej je jas medzi displejmi oveľa konzistentnejší. Podobné monitory použijú rovnaké nastavenia.", "SETTINGS_MONITORS_DETAILS_NAME": "Názov", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Interný názov", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Metóda komunikácie", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Aktuálny jas", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maximálny jas", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalizácia jasu", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Skryť neaktívny interný displej", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Keď je uzáver zatvorený alebo interný displej je v systéme Windows deaktivovaný, skryje sa posuvník jasu v paneli.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Skryť displeje", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Ak chcete skryť konkrétne displeje z rozbalovacieho zoznamu, môžete ich tu vypnúť.", "SETTINGS_FEATURES_DESCRIPTION": "Povoľte alebo zakážte konkrétne funkcie DDC/CI v paneli jasu. Aspoň jedna funkcia musí byť povolená, aby sa váš monitor zobrazil v paneli jasu. Nie všetky displeje podporujú tieto funkcie, ako napríklad displeje notebookov/tabletov.", "SETTINGS_FEATURES_UNSUPPORTED": "Tento monitor nepodporuje funkcie DDC/CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Skontrolovať aktuálne hodnoty jasu", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Vždy získa najnovšie hodnoty z monitora pri otvorení panela jasu. Povoľte túto možnosť, ak sa jas (alebo iné VCP kódy ako kontrast) často mení mimo Twinkle Tray.", "SETTINGS_TIME_TITLE": "Úpravy podľa času", "SETTINGS_TIME_DESC": "Automaticky nastavte vaše monitory na konkrétnu úroveň jasu v požadovanom čase. Všetky monitory budú nastavené na rovnaké, normalizované úrovne.", "SETTINGS_TIME_ADD": "Pridať čas", "SETTINGS_TIME_REMOVE": "Odstrániť čas", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Nastaviť jas pre jednotlivé displeje", "SETTINGS_TIME_INDIVIDUAL_DESC": "Nakonfigurujte jas na každom displeji namiesto všetkých displejov naraz.", "SETTINGS_TIME_TRANSITON_TITLE": "Rýchlosť prechodu jasu", "SETTINGS_TIME_TRANSITON_DESC": "Ako rýchlo by sa mal meniť jas pri aktivácii úprav podľa času.", "SETTINGS_TIME_STARTUP_TITLE": "Skontrolovať pri spustení aplikácie", "SETTINGS_TIME_STARTUP_DESC": "Nastavte jas, aby zodpovedal najrelevantnejšiemu času pri spustení Twinkle Tray.", "SETTINGS_TIME_IDLE_TITLE": "Detekcia nečinnosti", "SETTINGS_TIME_IDLE_DESC": "Keď sa po určitý čas nezaznamená žiadny vstup, jas všetkých displejov sa zníži.", "SETTINGS_TIME_ANIMATE_TITLE": "Animovať medzi časmi", "SETTINGS_TIME_ANIMATE_DESC": "Hodnoty jasu sa budú animovať medzi súčasným a nasledujúcim naplánovaným udalosťami. Môže to zvýšiť využitie CPU. Manuálne úpravy jasu sa rýchlo prepíšu, kým je táto funkcia aktívna.", "SETTINGS_HOTKEYS_TITLE": "Skratky", "SETTINGS_HOTKEYS_DESC": "Nakonfigurujte skratky na úpravu jasu jedného alebo všetkých displejov.", "SETTINGS_HOTKEYS_ADD": "Pridať skratku", "SETTINGS_HOTKEYS_REMOVE": "Odstrániť skratku", "SETTINGS_HOTKEYS_INCREASE": "Zvýšiť jas", "SETTINGS_HOTKEYS_DECREASE": "Znížiť jas", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Stlačte klávesy tu", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Úprava úrovne jasu", "SETTINGS_HOTKEYS_LEVEL_DESC": "O koľko by sa mal jas zvýšiť alebo znížiť pri použití skratiek.", "SETTINGS_HOTKEYS_TOD_TITLE": "Akcia vypnutia displejov", "SETTINGS_HOTKEYS_TOD_DESC": "Prispôsobte signál odoslaný pri použití skratky alebo ikony Vypnúť displeje. Softvérový signál zobrazí čiernu obrazovku, kým sa nezistí vstup (napr. myš alebo klávesnica) systémom Windows. Hardvérový signál vypne napájanie monitorov.", "SETTINGS_HOTKEYS_TOD_NONE": "Žiadne (skryť ikonu)", "SETTINGS_HOTKEYS_TOD_SOFT": "Softvérový signál (predvolené)", "SETTINGS_HOTKEYS_TOD_HARD": "Hardvérový* signál (iba DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Hardvérový* a softvérový signál", "SETTINGS_HOTKEYS_TOD_NOTE": "*Poznámka: Nie všetky DDC/CI monitory podporujú túto funkciu.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Skratky zrušia prepojené úrovne", "SETTINGS_HOTKEYS_BREAK_DESC": "Keď používate skratky pre jeden displej a \"prepojené úrovne\" je aktívne, prepojené úrovne sa deaktivuje.", "SETTINGS_UPDATES_TITLE": "Aktualizácie", "SETTINGS_UPDATES_VERSION": "Máte Twinkle Tray verzia {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Automaticky kontrolovať nové verzie", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Keď je k dispozícii nová verzia, zobrazí sa v paneli jasu.", "SETTINGS_UPDATES_MS_STORE": "Ak chcete skontrolovať dostupnosť nových verzií, navštívte aplikáciu Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Je k dispozícii nová verzia Twinkle Tray!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Máte aktuálnu verziu. Aktuálna verzia obsahuje nasledujúce zmeny:", "SETTINGS_UPDATES_DOWNLOADING": "Sťahovanie aktualizácie…", "SETTINGS_UPDATES_DOWNLOAD": "Stiahnuť a nainštalovať {{1}}", "SETTINGS_UPDATES_CHANNEL": "Kanál aktualizácií", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabilný (predvolený)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Vypnúť displej", "GENERIC_DELETE": "Odstrániť", "GENERIC_DEFAULT": "Predvolené", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Najkompatibilnejšie", "SETTINGS_FEATURES_VCP_EXPECTED": "Očakávané hodnoty", "SETTINGS_FEATURES_POWER_COMPAT": "Najviac kompatibilné", "GENERIC_OPTIONAL": "Voliteľné", "PANEL_LABEL_TURN_ON": "Zapnúť displej", "SETTINGS_GENERAL_OVERLAY_TITLE": "Predvolené správanie prekrytia", "SETTINGS_GENERAL_OVERLAY_DESC": "Ako silno sa bude prekrytie klávesovej skratky jasu pokúšať zobraziť nad ostatnými aplikáciami. Toto by ste nemali potrebovať upraviť.", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Prekrytie sa zobrazí nad väčšinou okien, ale nebude sa pretláčať nasilu nad aplikácie, ktoré sú označené ako \"vždy na vrchu\".", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Vynútené zobrazenie", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Vždy sa pokúsi zobraziť prekrytie nad všetkými oknami. Toto môže spôsobiť problémy s hrami v exkluzívnom zobrazení na celú obrazovku alebo inými aplikáciami na celú obrazovku. Môže to tiež aktivovať ochrany proti podvádzaniu v niektorých hrách.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Staršia metóda detekcie DDC/CI", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Použiť starú v1.15.5 metódu detekcie displejov DDC/CI.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Automaticky aplikovať jas", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Ak Váš displej reaguje zvláštne po vypnutí/zapnutí alebo odpojení/pripojení hardvéru, vypnúť toto môže pomôcť.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Vynechať automatickú aplikáciu pre určité monitory", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Vypne automatickú aplikáciu známeho jasu po všetkých hardvérových udalostiach napájania pre určité monitory. Toto zahŕňa funkciu detekcie nečinnosti.", "SETTINGS_GENERAL_REPORT_TITLE": "Generuj zostavu", "SETTINGS_GENERAL_REPORT_DESC": "Uloží textový súbor s informáciou o Vašich monitoroch a nastaveniach pre ladenie.", "SETTINGS_FEATURES_POWER_TITLE": "Signál stavu napájania", "SETTINGS_FEATURES_POWER_DESC": "Pri odosielaní DDC/CI príkazu na vypnutie Vášho displeja budú použité nasledujúce hodnoty.", "SETTINGS_FEATURES_POWER_STANDBY": "Pohotovosť", "SETTINGS_FEATURES_POWER_WARNING": "Voľba \"Pohotovosť\" pravdepodobnejšie dovolí prepínanie zapnutia/vypnutia monitora z Twinkle Tray. Avšak mnoho monitorov nereaguje správne na zmenu stavu napájania. Použite na vlastné riziko.", "SETTINGS_FEATURES_ADD": "Pridať funkciu", "SETTINGS_FEATURES_ADD_DESC": "Vložte VCP kód pre funkciu, ktorú chcete pridať pre Vás displej. Berte na vedomie, prosím, že Twinkle Tray neoveruje, či Váš displej skutočne podporuje VCP kód. Použite na vlastné riziko.", "SETTINGS_FEATURES_ADD_VCP": "VCP kód", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP kód (napr. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "Táto funkcia už je aktívna.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Všetky VCP kód hlásenie displejom", "SETTINGS_FEATURES_VCP_LIST_DESC": "Nasledujúci zoznam dostupných VCP kódov hlásených týmto displejom pre Windows. Twinkle Tray neoveruje funkčnosť alebo stabilitu týchto VCP kódov. Použite ich na vlastné riziko.", "SETTINGS_TIME_SUN_TITLE": "Súradnice pre polohu slnka", "SETTINGS_TIME_SUN_DESC": "Pre použitie \"polohy slnka\" na úpravu času, vložte Vašu aktuálnu zemepisnú šírku a dĺžku, aby boli stanovené správne časy.", "SETTINGS_TIME_LAT": "Zemepisná šírka", "SETTINGS_TIME_LONG": "Zemepisná dĺžka", "SETTINGS_TIME_SUN_GET": "Získať súradnice", "SETTINGS_TIME_IDLE_FS_TITLE": "Aplikácie na celú obrazovku blokujú detekciu nečinnosti", "SETTINGS_TIME_IDLE_FS_DESC": "Aplikácie na celú obrazovku blokujú detekciu nečinnosti. Toto sa vzťahuje len na aktívne okno.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Médiá blokujú detekciu nečinnosti", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Detekcia nečinnosti bude vypnutá počas prehrávania akéhokoľvek média. To zahŕňa súčasne obraz aj zvuk. Toto sa aplikuje len v prípade, ak Windows hlási, že sa médium prehráva.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Hodnota pre rolovanie", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Obrátené rolovanie", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "Pri rolovaní nad ikonou lišty bude rolovanie obrátené opačne.", "SETTINGS_HOTKEY_OFF_WARN": "Táto akcia použije možnosť vybranú pod \"Akcia vypnutia displejov\". Ak si želáte vypnúť len určité displeje, použite akciu klávesovej skratky \"Nastaviť\" alebo \"Cyklovať\".", "SETTINGS_HOTKEY_TARGET": "Cieľ akcie", "SETTINGS_HOTKEY_VALUE": "Hodnota", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Vložte číslo", "SETTINGS_HOTKEY_VALUES": "Hodnoty", "SETTINGS_HOTKEY_ADD_VALUE": "Pridať hodnotu", "SETTINGS_HOTKEY_ACTION": "Akcia", "SETTINGS_HOTKEY_ACTION_SET": "Nastaviť hodnotu", "SETTINGS_HOTKEY_ACTION_OFFSET": "Upraviť hodnotu", "SETTINGS_HOTKEY_ACTION_CYCLE": "Prechádzať zoznam hodnôt", "SETTINGS_PROFILES_TITLE": "Profily", "SETTINGS_PROFILES_DESC": "Automaticky upraví jas alebo správanie prekrytia skratiek v závislosti od aktívnej aplikácie. Môžete tiež pridať profily pre kontextové menu v systémovej lište pre rýchlu zmenu jasu na preddefinované profily.", "SETTINGS_PROFILES_ADD": "Nový profil", "SETTINGS_PROFILES_NAME": "Názov profilu", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Nastaviť jas, ak je aktívny", "SETTINGS_PROFILES_SHOW_MENU": "Zobraziť v kontextovom menu lišty", "SETTINGS_PROFILES_TRIGGER_TITLE": "Nastavenie spúšťača podľa aplikácie", "SETTINGS_PROFILES_APP_PATH": "Cesta k aplikácii", "SETTINGS_PROFILES_APP_DESC": "Ak chcete tento profil aktivovať automaticky, keď je aktívna určitá aplikácia, vložte úplnú alebo čiastočnú cestu k EXE nižšie.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Nadradiť typ prekrytia", "SETTINGS_PROFILES_OVERLAY_DESC": "Zmení správanie prekrytia skratky keď je určitá aplikácia aktívna. Táto funkcia nepracuje, keď je profil aktivovaný ručne.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Vypnúť na obrazovke uzamknutia", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Nepristupovať k monitorom, kým je používateľská relácia uzamknutá, aby sa predišlo konfliktom v prostrediach s viacerými používateľmi.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "Nastavenie HDR displeja", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Zapne posuvníky SDR jasu pre špecifické monitory. Monitory musia mať HDR zapnuté vo Windows, aby to fungovalo.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR nahradí primárny posuvník", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Kontroluje SDR jas z hlavného jasového posuvníka, ak je HDR aktívne.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR jas", "GENERIC_CALIBRATION_POINT": "Kalibračný bod", "GENERIC_SLIDER_NAME": "Zadajte názov pre posuvník", "GENERIC_TEXT": "Text", "GENERIC_ICON": "Ikona", "PANEL_LABEL_INPUTS": "Vstupy", "GENERIC_DETECTING_DISPLAYS": "Detekcia displejov…" } ================================================ FILE: src/localization/sv.json ================================================ { "LANGUAGE": "Svenska", "GENERIC_OK": "OK", "GENERIC_CANCEL": "Avbryt", "GENERIC_SAVE": "Spara", "GENERIC_CLEAR": "Rensa", "GENERIC_OFF": "Av", "GENERIC_ON": "På", "GENERIC_QUIT": "Avsluta", "GENERIC_CLOSE": "Stäng", "GENERIC_SETTINGS": "Inställningar", "GENERIC_INSTALL": "Installera", "GENERIC_DISMISS": "Avfärda", "GENERIC_DISPLAY_SINGLE": "Bildskärm", "GENERIC_ALL_DISPLAYS": "Alla bildskärmar", "GENERIC_REFRESH_DISPLAYS": "Uppdatera bildskärmar", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Max", "GENERIC_NO_DISPLAYS": "Ingen bildskärm upptäcktes. Anslut en bildskärm till datorn.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Inga kompatibla bildskärmar hittades. Se till att ”DDC/CI” är aktiverat på dina bildskärmar.", "GENERIC_NO_DISPLAYS_SHORT": "Inga kompatibla bildskärmar upptäcktes.", "GENERIC_SECONDS": "sekunder", "GENERIC_MINUTES": "minuter", "PANEL_TITLE": "Justera ljusstyrka", "PANEL_UPDATE_AVAILABLE": "Ny version tillgänglig", "PANEL_BUTTON_LINK_LEVELS": "Länka nivåer", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Stäng av bildskärmar", "PANEL_LABEL_BRIGHTNESS": "Ljusstyrka", "PANEL_LABEL_CONTRAST": "Kontrast", "PANEL_LABEL_OFF_ON": "Strömtillstånd", "PANEL_LABEL_COLOR_TEMPERATURE": "Färgtemperatur", "PANEL_LABEL_VOLUME": "Volym", "PANEL_LABEL_TURN_OFF": "Stäng av", "INTRO_TITLE": "Hallå, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Twinkle Trays systemfältsikon är antagligen dold, så du bör flytta den till en plats där du lätt kan nå den. Se nedanstående instruktioner.", "SETTINGS_TITLE": "Twinkle Tray-inställningar", "SETTINGS_SIDEBAR_GENERAL": "Allmänt", "SETTINGS_SIDEBAR_MONITORS": "Bildskärmsinställningar", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI-funktioner", "SETTINGS_SIDEBAR_TIME": "Tidsjusteringar", "SETTINGS_SIDEBAR_HOTKEYS": "Snabbtangenter & genvägar", "SETTINGS_SIDEBAR_UPDATES": "Uppdateringar", "SETTINGS_GENERAL_TITLE": "Allmänt", "SETTINGS_GENERAL_STARTUP": "Starta med datorn", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Tillämpa ljusstyrka vid uppstart", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Återställ den senast kända ljusstyrkan för varje bildskärm när Twinkle Tray startas.", "SETTINGS_GENERAL_THEME_TITLE": "Tema", "SETTINGS_GENERAL_THEME_SYSTEM": "Systeminställningar (standard)", "SETTINGS_GENERAL_THEME_DARK": "Mörk", "SETTINGS_GENERAL_THEME_LIGHT": "Ljus", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Språk", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Systemspråk (standard)", "SETTINGS_GENERAL_RESET_TITLE": "Återställ inställningar", "SETTINGS_GENERAL_RESET_DESC": "Tryck på den här knappen för att rensa din konfigurering.", "SETTINGS_GENERAL_RESET_BUTTON": "Återställ inställningar", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akryloskärpa", "SETTINGS_GENERAL_ACRYLIC_DESC": "Aktivera eller inaktivera oskärpa bakom genomskinliga bakgrunder i Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Micaoskärpa", "SETTINGS_GENERAL_MICA_DESC": "Aktivera eller inaktivera oskärpa bakom bakgrunder i Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analys", "SETTINGS_GENERAL_ANALYTICS_DESC": "Skicka användningsdata för att hjälpa till att förbättra Twinkle Tray. Ingen personlig information skickas. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Lär dig mer", "SETTINGS_GENERAL_SCROLL_TITLE": "Rullgenväg för systemfältsikon", "SETTINGS_GENERAL_SCROLL_DESC": "Justera alla skärmars ljusstyrka samtidigt genom att rulla mushjulet över aktivitetsikonen. Detta fungerar inte med vissa styrplattor.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Systemfältsikon", "SETTINGS_MONITORS_RATE_TITLE": "Ljusstyrkans uppdateringshastighet", "SETTINGS_MONITORS_RATE_DESC": "Hur ofta ljusstyrkan uppdateras på dina bildskärmar medan du justerar deras värden. Öka tiden om dina bildskärmar flimrar.", "SETTINGS_MONITORS_RATE_0": "Löjligt snabb", "SETTINGS_MONITORS_RATE_1": "Snabb (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Långsam (1 sekund)", "SETTINGS_MONITORS_RATE_4": "Mycket långsam (2 sekunder)", "SETTINGS_MONITORS_RENAME_TITLE": "Byt namn på bildskärmar", "SETTINGS_MONITORS_RENAME_DESC": "Om du föredrar att ha olika namn för varje bildskärm (t.ex. ”Vänstra bildskärmen”, ”Mittersta bildskärmen”) så kan du skriva det nedan. Att lämna fältet tomt återställer det ursprungliga namnet.", "SETTINGS_MONITORS_ENTER_NAME": "Ange namn", "SETTINGS_MONITORS_REORDER_TITLE": "Ordna om bildskärmar", "SETTINGS_MONITORS_REORDER_DESC": "Ändra ordningen som bildskärmar visas i aktivitetsfältet. Klicka och dra för att göra ändringar.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Normalisera ljusstyrka", "SETTINGS_MONITORS_NORMALIZE_DESC": "Bildskärmar kan ofta ha olika intervall för ljusstyrka. Genom att begränsa varje bildskärms min/max-ljusstyrka blir bildskärmarnas ljusstyrka mycket jämnare. Liknande bildskärmar kommer använda samma inställningar.", "SETTINGS_MONITORS_DETAILS_NAME": "Namn", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Internt namn", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Kommunikationsmetod", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Nuvarande ljusstyrka", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Max-ljusstyrka", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Normalisering av ljusstyrka", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Dölj inaktiv inbyggd bildskärm", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Dölj reglaget för ljusstyrka i panelen när locket stängs eller den inbyggda bildskärmen inaktiverats i Windows.", "SETTINGS_FEATURES_DESCRIPTION": "Aktivera eller inaktivera specifika DDC/CI-funktioner i ljusstyrkepanelen. Minst en funktion måste vara aktiverad för att bildskärmen ska visas i ljusstyrkepanelen. Alla bildskärmar har inte stöd för dessa funktioner, t.ex. bildskärmar i laptops/surfplattor.", "SETTINGS_FEATURES_UNSUPPORTED": "Denna bildskärm stöder inte DDC/CI-funktioner.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Kontrollera aktuella värden", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Få alltid de senaste värdena från bildskärmen när du öppnar ljusstyrkepanelen. Aktivera detta om ljusstyrkan (eller andra VCP-koder som t.ex. kontrast) ofta ändras utanför Twinkle Tray.", "SETTINGS_TIME_TITLE": "Justeringar av tid på dygnet", "SETTINGS_TIME_DESC": "Ställ automatiskt in bildskärmarna på en viss ljusstyrka vid en önskad tidpunkt. Alla bildskärmar kommer att ställas in på samma, normaliserade nivåer.", "SETTINGS_TIME_ADD": "Lägg till en tid", "SETTINGS_TIME_REMOVE": "Ta bort tid", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Ställ in ljusstyrkan för enskilda bildskärmar", "SETTINGS_TIME_INDIVIDUAL_DESC": "Konfigurera ljusstyrkan per bildskärm i stället för alla bildskärmar samtidigt.", "SETTINGS_TIME_STARTUP_TITLE": "Kontrollera vid appstart", "SETTINGS_TIME_STARTUP_DESC": "Justera ljusstyrkan för att matcha den mest relevanta tiden när Twinkle Tray startar.", "SETTINGS_TIME_IDLE_TITLE": "Inaktivitetsdetektering", "SETTINGS_TIME_IDLE_DESC": "När ingen inmatning har upptäckts under en viss tid minskas ljusstyrkan på alla bildskärmar.", "SETTINGS_HOTKEYS_TITLE": "Snabbtangenter", "SETTINGS_HOTKEYS_DESC": "Konfigurera snabbtangenter för att justera ljusstyrkan på en eller alla bildskärmar.", "SETTINGS_HOTKEYS_ADD": "Lägg till snabbtangent", "SETTINGS_HOTKEYS_REMOVE": "Ta bort snabbtangent", "SETTINGS_HOTKEYS_INCREASE": "Öka ljusstyrkan", "SETTINGS_HOTKEYS_DECREASE": "Minska ljusstyrkan", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Tryck på tangenterna här", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Justeringsnivå av ljusstyrkan", "SETTINGS_HOTKEYS_LEVEL_DESC": "Hur mycket ljusstyrkan ska justeras när du använder snabbtangenter.", "SETTINGS_HOTKEYS_TOD_TITLE": "Stäng-av-bildskärmar-åtgärd", "SETTINGS_HOTKEYS_TOD_DESC": "Anpassa signalen som skickas när du använder stäng-av-bildskärmar-snabbtangenten eller -ikonen. Mjukvarusignalen visar en svart skärm tills Windows upptäcker inmatning (t.ex. mus eller tangentbord). Hårdvarusignalen stänger av strömmen till skärmarna.", "SETTINGS_HOTKEYS_TOD_NONE": "Ingen (dölj ikon)", "SETTINGS_HOTKEYS_TOD_SOFT": "Mjukvarusignal (standard)", "SETTINGS_HOTKEYS_TOD_HARD": "Hårdvarusignal* (endast DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Hårdvaru-* & mjukvarusignal", "SETTINGS_HOTKEYS_TOD_NOTE": "*Anmärkning: Alla DDC/CI bildskärmar stöder inte denna funktion.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Snabbtangenter avbryter länkade nivåer", "SETTINGS_HOTKEYS_BREAK_DESC": "När du använder en snabbtangent för en enskild bildskärm och ”länkade nivåer” är aktiv, kommer den att avaktiveras.", "SETTINGS_UPDATES_TITLE": "Uppdateringar", "SETTINGS_UPDATES_VERSION": "Du har Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Kontrollera automatiskt om det finns nya versioner", "SETTINGS_UPDATES_AUTOMATIC_DESC": "När det finns en ny version kommer den att visas i ljusstyrkepanelen.", "SETTINGS_UPDATES_MS_STORE": "Gå till Microsoft Store-appen för att kontrollera om det finns nya versioner.", "SETTINGS_UPDATES_AVAILABLE": "Ny version av Twinkle Tray är tillgänglig!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Uppdaterad. Den aktuella versionen innehåller följande ändringar:", "SETTINGS_UPDATES_DOWNLOADING": "Hämtar uppdatering…", "SETTINGS_UPDATES_DOWNLOAD": "Ladda ner & installera {{1}}", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Om Twinkle Tray inte reagerar när du klickar på ikonen eller inte känner av dina bildskärmar kan du försöka inaktivera vissa metoder för bildskärmsidentifiering. Starta om Twinkle Tray för att ändringarna ska träda i kraft. {{1}}", "GENERIC_PAUSE_TOD": "Justeringar av paustiden", "GENERIC_PAUSE_IDLE": "Pausa inaktivitetsdetektering", "SETTINGS_GENERAL_TROUBLESHOOTING": "Felsökning", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Aktiverade metoder för bildskärmsidentifiering", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Dölj bildskärmar", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Om du vill dölja specifika bildskärmar från utskjutningsfönstret kan du stänga av dem här.", "SETTINGS_TIME_ANIMATE_TITLE": "Animera mellan olika tider", "SETTINGS_TIME_TRANSITON_TITLE": "Övergångshastighet för ljusstyrka", "SETTINGS_TIME_TRANSITON_DESC": "Hur snabbt ljusstyrkan ska övergå när justeringar av tid på dygnet aktiverats.", "SETTINGS_TIME_ANIMATE_DESC": "Ljusstyrkan kommer att animeras mellan den aktuella och nästa schemalagda händelsen. Kan öka CPU-användningen. Manuella justeringar av ljusstyrkan kommer snabbt att skrivas över när detta är aktivt.", "GENERIC_SPEED_INSTANT": "Omedelbar", "GENERIC_SPEED_SLOW": "Långsam", "GENERIC_DDC_WARNING": "DDC/CI-funktioner som t.ex. styrning av strömtillståndet kan leda till att din bildskärm inte svarar. Använd på egen risk.", "GENERIC_SPEED_VERY_SLOW": "Mycket långsam", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_SPEED_FAST": "Snabb", "GENERIC_SPEED_VERY_FAST": "Mycket snabb", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Om Twinkle Trays snabbtangentöverlagring stör helskärmsapplikationer kan du inaktivera det här.", "SETTINGS_UPDATES_CHANNEL": "Uppdateringskanal", "SETTINGS_UPDATES_BRANCH_STABLE": "Stabil (standard)", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Inaktivera överlagring", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "SETTINGS_FEATURES_POWER_OFF": "Stäng av", "GENERIC_DELETE": "Radera", "GENERIC_DEFAULT": "Standard", "GENERIC_OPTIONAL": "Valfri", "PANEL_LABEL_TURN_ON": "Sätt på", "SETTINGS_GENERAL_OVERLAY_TITLE": "Standardbeteende för överlagring", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Mest kompatibel", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Tvingad på", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Försök alltid att visa överlagringen över andra fönster. Detta kan orsaka problem med spel i exklusiv helskärm och andra appar i helskärm. Det kan även utlösa anti-fusk i vissa spel.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Äldre metod för DDC/CI-detektering", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Använd den gamla v1.15.5-metoden för att upptäcka DDC/CI-bildskärmar.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Tillämpa ljusstyrka automatiskt", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Hoppa över automatisk tillämpning för specifika bildskärmar", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Inaktivera automatisk tillämpning av känd ljusstyrka efter alla hårdvaru-/strömhändelser för specifika bildskärmar. Detta inkluderar funktionen för inaktivitetsdetektering.", "SETTINGS_FEATURES_POWER_TITLE": "Strömtillståndssignal", "SETTINGS_FEATURES_POWER_STANDBY": "Standby", "SETTINGS_FEATURES_VCP_LIST_DESC": "Följande är en lista över tillgängliga VCP-koder som rapporteras av denna bildskärm till Windows. Twinkle Tray validerar inte funktionaliteten eller stabiliteten av dessa VCP-koder. Använd dem på egen risk.", "SETTINGS_GENERAL_REPORT_DESC": "Spara en textfil med information om dina bildskärmar och inställningar för felsökning.", "SETTINGS_FEATURES_POWER_DESC": "När DDC/CI-kommadot för att stänga av din bildskärm skickas, kommer följande värde(n) att skickas.", "SETTINGS_FEATURES_POWER_COMPAT": "Mest kompatibel", "SETTINGS_FEATURES_POWER_WARNING": "Med alternativet ”Standby” är det mer sannolikt att du kan slå på/av bildskärmen från Twinkle Tray. Många bildskärmar reagerar dock inte korrekt när strömtillståndet ändras. Använd på egen risk.", "SETTINGS_FEATURES_ADD": "Lägg till funktion", "SETTINGS_FEATURES_ADD_VCP": "VCP-kod", "SETTINGS_FEATURES_ADD_EXISTS": "Denna funktion är redan aktiv.", "SETTINGS_GENERAL_REPORT_TITLE": "Generera rapport", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP-kod (t.ex. 0x12)", "SETTINGS_FEATURES_VCP_EXPECTED": "Förväntade värden", "SETTINGS_TIME_SUN_TITLE": "Koordinater för solens position", "SETTINGS_TIME_SUN_DESC": "För att använda ”solens position” för tidsjusteringar anger du din aktuella latitud och longitud så att rätt tider kan bestämmas.", "SETTINGS_TIME_SUN_GET": "Hämta koordinater", "SETTINGS_TIME_IDLE_FS_TITLE": "Helskärmsappar blockerar identifiering av inaktivitet", "SETTINGS_TIME_IDLE_FS_DESC": "Appar i helskärm blockerar inaktivitetsdetektering. Detta gäller endast för fönstret i fokus.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Alla VCP-koder som rapporteras av din bildskärm", "SETTINGS_PROFILES_ADD": "Ny profil", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Invertera rullning", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "När du rullar över systemfältsikonen kommer rullningsriktningen att vändas.", "SETTINGS_GENERAL_OVERLAY_DESC": "Hur kraftfullt snabbtangentöverlagringen för ljusstyrka kommer försöka visas över andra appar. Du borde inte behöva justera detta.", "SETTINGS_TIME_LAT": "Latitud", "SETTINGS_TIME_LONG": "Longitud", "SETTINGS_PROFILES_DESC": "Justera automatiskt ljusstyrkan eller genvägsöverlagringens beteende beroende på vilken app som är i fokus. Du kan också lägga till profiler i högerklicksmenyn i systemfältet för att snabbt ändra ljusstyrkan till förinställda profiler.", "SETTINGS_HOTKEY_ACTION_OFFSET": "Justera värde", "SETTINGS_FEATURES_ADD_DESC": "Ange VCP-koden för den funktion som du vill lägga till i din bildskärm. Observera att Twinkle Tray inte validerar att din bildskärm faktiskt stöder denna VCP-kod. Använd på egen risk.", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Om din bildskärm reagerar konstigt när den slås av/på eller hårdvara kopplas bort/ansluts kan det hjälpa att inaktivera detta.", "SETTINGS_HOTKEY_OFF_WARN": "Denna åtgärd använder det alternativ som valts under ”stäng-av-bildskärmar-åtgärd”. Om du vill stänga av specifika bildskärmar använder du snabbtangenten ”Ställ in” eller ”Cykla” istället.", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Överlagringen kommer visas över de flesta fönstren, men kommer inte tvinga sig över appar som är markerade som ”alltid överst”.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Media blockerar inaktivitetsdetektering", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Inaktivitetsdetektering kommer stängas av medan media spelas upp. Detta inkluderar både video och ljud. Detta gäller endast när Windows rapporterar att media spelas upp.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Mängd att rulla", "SETTINGS_HOTKEY_TARGET": "Mål för åtgärd", "SETTINGS_HOTKEY_VALUE": "Värde", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Ange ett tal", "SETTINGS_HOTKEY_VALUES": "Värden", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Ställ in ljusstyrka när aktiv", "SETTINGS_PROFILES_APP_PATH": "Sökväg till app", "SETTINGS_PROFILES_APP_DESC": "Om du vill att denna profil ska aktiveras automatiskt när en specifik app är i fokus, ange hel eller delvis sökväg till EXE-filen nedan.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Åsidosätt överlagringstyp", "SETTINGS_PROFILES_OVERLAY_DESC": "Ändrar snabbtangentöverlagringens beteende när den angivna appen är i fokus. Den här funktionen fungerar inte när profilen aktiveras manuellt.", "SETTINGS_PROFILES_TRIGGER_TITLE": "App-utlösningsinställningar", "SETTINGS_HOTKEY_ACTION": "Åtgärd", "SETTINGS_HOTKEY_ACTION_SET": "Ställ in värde", "SETTINGS_HOTKEY_ACTION_CYCLE": "Cykla listan med värden", "SETTINGS_PROFILES_TITLE": "Profiler", "SETTINGS_PROFILES_NAME": "Profilnamn", "SETTINGS_PROFILES_SHOW_MENU": "Visa i systemfältets högerklicksmeny", "SETTINGS_HOTKEY_ADD_VALUE": "Lägg till värde", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Ljusstyrka" } ================================================ FILE: src/localization/ta.json ================================================ { "LANGUAGE": "ஆங்கிலம்", "GENERIC_OK": "சரி", "GENERIC_CANCEL": "ரத்துசெய்", "GENERIC_SAVE": "சேமி", "GENERIC_CLEAR": "தெளிவான", "GENERIC_DELETE": "நீக்கு", "GENERIC_OFF": "அணை", "GENERIC_ON": "ஆன்", "GENERIC_QUIT": "வெளியேறு", "GENERIC_CLOSE": "மூடு", "GENERIC_SETTINGS": "அமைப்புகள்", "GENERIC_INSTALL": "நிறுவவும்", "GENERIC_DISMISS": "தள்ளுபடி", "GENERIC_DEFAULT": "இயல்புநிலை", "GENERIC_OPTIONAL": "விரும்பினால்", "GENERIC_DISPLAY_SINGLE": "காட்சி", "GENERIC_ALL_DISPLAYS": "அனைத்து காட்சிகள்", "GENERIC_REFRESH_DISPLAYS": "காட்சிகளைப் புதுப்பிக்கவும்", "GENERIC_MINIMUM": "மணித்துளி", "GENERIC_MAXIMUM": "அதிகபட்சம்", "GENERIC_NO_DISPLAYS": "காட்சிகள் எதுவும் கண்டறியப்படவில்லை. உங்கள் கணினியுடன் ஒரு காட்சியை இணைக்கவும்.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "இணக்கமான காட்சிகள் எதுவும் கிடைக்கவில்லை. உங்கள் காட்சிகளுக்கு \"டி.டி.சி/சிஐ\" இயக்கப்பட்டதா என்பதை சரிபார்க்கவும்.", "GENERIC_NO_DISPLAYS_SHORT": "இணக்கமான காட்சிகள் எதுவும் கண்டறியப்படவில்லை.", "GENERIC_SECONDS": "நொடிகள்", "GENERIC_MINUTES": "நிமிடங்கள்", "GENERIC_DDC_WARNING": "மின் நிலையைக் கட்டுப்படுத்துவது போன்ற டி.டி.சி/சிஐ நற்பொருத்தங்கள் உங்கள் மானிட்டர் பதிலளிக்காமல் இருக்கும். உங்கள் சொந்த ஆபத்தில் பயன்படுத்தவும்.", "GENERIC_SPEED_INSTANT": "உடனடி", "GENERIC_SPEED_SLOW": "மெதுவாக", "GENERIC_SPEED_VERY_SLOW": "மிகவும் மெதுவாக", "GENERIC_SPEED_NORMAL": "சாதாரண", "GENERIC_SPEED_FAST": "வேகமாக", "GENERIC_SPEED_VERY_FAST": "மிக வேகமாக", "GENERIC_PAUSE_TOD": "நேர மாற்றங்களை இடைநிறுத்தவும்", "GENERIC_PAUSE_IDLE": "செயலற்ற கண்டறிதல் இடைநிறுத்தம்", "PANEL_TITLE": "பிரகாசத்தை சரிசெய்யவும்", "PANEL_UPDATE_AVAILABLE": "புதிய பதிப்பு கிடைக்கிறது", "PANEL_BUTTON_LINK_LEVELS": "இணைப்பு நிலைகள்", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "காட்சிகளை அணைக்கவும்", "PANEL_LABEL_BRIGHTNESS": "ஒளிரும்", "PANEL_LABEL_CONTRAST": "மாறுபாடு", "PANEL_LABEL_OFF_ON": "ஆற்றல் நிலை", "PANEL_LABEL_COLOR_TEMPERATURE": "வண்ண வெப்பநிலை", "PANEL_LABEL_VOLUME": "தொகுதி", "PANEL_LABEL_TURN_OFF": "ஆற்றல் முடக்குகிறது", "PANEL_LABEL_TURN_ON": "ஆற்றல்", "INTRO_TITLE": "வணக்கம், ட்விங்கிள் தட்டு!", "INTRO_INSTRUCTIONS": "ட்விங்கிள் தட்டுக்கான தட்டு படவுரு அநேகமாக மறைக்கப்பட்டிருக்கலாம், எனவே நீங்கள் அதை எளிதாக அணுகக்கூடிய ஏதேனும் ஒரு இடத்திற்கு நகர்த்த வேண்டும். வழிமுறைகளுக்கு கீழே காண்க.", "SETTINGS_TITLE": "ட்விங்கிள் தட்டு அமைப்புகள்", "SETTINGS_SIDEBAR_GENERAL": "பொது", "SETTINGS_SIDEBAR_MONITORS": "அமைப்புகளை கண்காணிக்கவும்", "SETTINGS_SIDEBAR_FEATURES": "டி.டி.சி/சி.ஐ நற்பொருத்தங்கள்", "SETTINGS_SIDEBAR_TIME": "நேர சரிசெய்தல்", "SETTINGS_SIDEBAR_HOTKEYS": "ஆட்கீச் மற்றும் குறுக்குவழிகள்", "SETTINGS_SIDEBAR_UPDATES": "புதுப்பிப்புகள்", "SETTINGS_GENERAL_TITLE": "பொது", "SETTINGS_GENERAL_STARTUP": "தொடக்கத்தில் தொடங்கவும்", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "தொடக்கத்தில் பிரகாசத்தைப் பயன்படுத்துங்கள்", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "ட்விங்கிள் தட்டு தொடங்கும் போது ஒவ்வொரு காட்சிக்கும் கடைசியாக அறியப்பட்ட பிரகாசத்தை மீட்டெடுக்கவும்.", "SETTINGS_GENERAL_THEME_TITLE": "கருப்பொருள்", "SETTINGS_GENERAL_THEME_SYSTEM": "கணினி விருப்பத்தேர்வுகள் (இயல்புநிலை)", "SETTINGS_GENERAL_THEME_DARK": "இருண்ட", "SETTINGS_GENERAL_THEME_LIGHT": "ஒளி", "SETTINGS_GENERAL_LANGUAGE_TITLE": "மொழி", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "கணினி மொழி (இயல்புநிலை)", "SETTINGS_GENERAL_RESET_TITLE": "அமைப்புகளை மீட்டமைக்கவும்", "SETTINGS_GENERAL_RESET_DESC": "உங்கள் உள்ளமைவை அழிக்க இந்த பொத்தானை அழுத்தவும்.", "SETTINGS_GENERAL_RESET_BUTTON": "அமைப்புகளை மீட்டமைக்கவும்", "SETTINGS_GENERAL_ACRYLIC_TITLE": "அக்ரிலிக் மங்கலானது", "SETTINGS_GENERAL_ACRYLIC_DESC": "ட்விங்கிள் தட்டில் வெளிப்படையான பின்னணியின் பின்னால் உள்ள மங்கலை இயக்கவும் அல்லது முடக்கவும்.", "SETTINGS_GENERAL_MICA_TITLE": "சிறிய மங்கலானது", "SETTINGS_GENERAL_MICA_DESC": "ட்விங்கிள் தட்டில் பின்னணிக்கு பின்னால் மங்கலை இயக்கவும் அல்லது முடக்கவும்.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "பகுப்பாய்வு", "SETTINGS_GENERAL_ANALYTICS_DESC": "ட்விங்கிள் தட்டில் மேம்படுத்த உதவ பயன்பாட்டு தரவை அனுப்பவும். தனிப்பட்ட செய்தி எதுவும் அனுப்பப்படவில்லை. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "மேலும் அறிக", "SETTINGS_GENERAL_SCROLL_TITLE": "தட்டு படவுரு சுருள் குறுக்குவழி", "SETTINGS_GENERAL_SCROLL_DESC": "கணினி தட்டு ஐகானை ச்க்ரோலிங் செய்வதன் மூலம் அனைத்து காட்சிகளின் பிரகாசத்தையும் ஒரே நேரத்தில் சரிசெய்யவும். இது சில டிராக்பேட்களுடன் வேலை செய்யாது.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "தட்டு படவுரு", "SETTINGS_GENERAL_TROUBLESHOOTING": "சரிசெய்தல்", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "இயக்கப்பட்ட மானிட்டர் கண்டறிதல் முறைகள்", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "தட்டு ஐகானைக் சொடுக்கு செய்யும்போது அல்லது உங்கள் காட்சிகளைக் கண்டறியாதபோது ட்விங்கிள் தட்டு பதிலளிக்கவில்லை என்றால், சில மானிட்டர் கண்டறிதல் முறைகளை முடக்க முயற்சி செய்யலாம். மாற்றங்கள் நடைமுறைக்கு வருவதற்கு ட்விங்கிள் தட்டில் மறுதொடக்கம் செய்யுங்கள். {{1}}", "SETTINGS_GENERAL_OVERLAY_TITLE": "இயல்புநிலை மேலடுக்கு நடத்தை", "SETTINGS_GENERAL_OVERLAY_DESC": "பிரகாசமான ஆட்ச்கி மேலடுக்கு மற்ற பயன்பாடுகளை எவ்வளவு வலுக்கட்டமாகக் காட்ட முயற்சிக்கும். இதை நீங்கள் சரிசெய்ய தேவையில்லை.", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "மேலடுக்கை முடக்கு", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "ட்விங்கிள் ட்ரேயின் ஆட்ச்கி மேலடுக்கு முழுத்திரை பயன்பாடுகளில் தலையிடினால், நீங்கள் அதை இங்கே முடக்கலாம்.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "மிகவும் இணக்கமானது", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "மேலடுக்கு பெரும்பாலான சாளரங்களில் காண்பிக்கப்படும், ஆனால் \"எப்போதும் மேலே\" எனக் குறிக்கப்பட்ட பயன்பாடுகளுக்கு மேலே தன்னை கட்டாயப்படுத்தாது.", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "கட்டாயப்படுத்தப்பட்டது", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "மற்ற சன்னல்களின் மேல் மேலடுக்கைக் காட்ட எப்போதும் முயற்சிக்கவும். இது பிரத்யேக முழுத்திரை விளையாட்டுகள் மற்றும் பிற முழுத்திரை பயன்பாடுகளில் சிக்கல்களை ஏற்படுத்தும். இது சில விளையாட்டுகளில் ஏமாற்றுக்காயைத் தூண்டும்.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "மரபு டி.டி.சி/சிஐ கண்டறிதல் முறை", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "டி.டி.சி/சிஐ காட்சிகளைக் கண்டறியும் பழைய V1.15.5 முறையைப் பயன்படுத்தவும்.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "தானாகவே பயன்பாட்டு ஒளி", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "உங்கள் மானிட்டர் அதை அணைத்த பிறகு அணை/இயக்கு அல்லது துண்டிக்க/இணைத்தபிறகு வேறுவிதமாகப் பதிலளித்தால், இதை முடக்குவது உதவக்கூடும்.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "குறிப்பிட்ட மானிட்டர்களுக்கு தானாக விண்ணப்பிக்கத் தவிர்க்கவும்", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "குறிப்பிட்ட மானிட்டர்களுக்கான அனைத்து வன்பொருள்/சக்தி நிகழ்வுகளுக்குப் பிறகு தானாகவே பயன்படுத்தப்பட்ட பிரகாசத்தை முடக்கு. செயலற்ற கண்டறிதல் நற்பொருத்தம் இதில் அடங்கும்.", "SETTINGS_GENERAL_REPORT_TITLE": "அறிக்கையை உருவாக்குங்கள்", "SETTINGS_GENERAL_REPORT_DESC": "உங்கள் மானிட்டர்கள் மற்றும் பிழைத்திருத்தத்திற்கான அமைப்புகள் பற்றிய தகவல்களுடன் உரை கோப்பை சேமிக்கவும்.", "SETTINGS_MONITORS_RATE_TITLE": "ஒளி புதுப்பிப்பு வீதம்", "SETTINGS_MONITORS_RATE_DESC": "நீங்கள் அவற்றின் மதிப்புகளை சரிசெய்யும்போது உங்கள் காட்சிகளில் ஒளி எவ்வளவு அடிக்கடி புதுப்பிக்கப்படும். உங்கள் காட்சிகள் ஒளிரும் என்றால் நேரத்தை அதிகரிக்கவும்.", "SETTINGS_MONITORS_RATE_0": "நகைச்சுவையான", "SETTINGS_MONITORS_RATE_1": "வேகமாக (250 எம்.எச்)", "SETTINGS_MONITORS_RATE_2": "இயல்பானது (500 எம்.எச்)", "SETTINGS_MONITORS_RATE_3": "மெதுவாக (1 வினாடி)", "SETTINGS_MONITORS_RATE_4": "மிகவும் மெதுவாக (2 விநாடிகள்)", "SETTINGS_MONITORS_RENAME_TITLE": "மானிட்டர்கள் மறுபெயரிடுங்கள்", "SETTINGS_MONITORS_RENAME_DESC": "ஒவ்வொரு மானிட்டருக்கும் (முன்னாள் \"இடது மானிட்டர்\", \"நடுத்தர மானிட்டர்\") வெவ்வேறு பெயரை நீங்கள் விரும்பினால், நீங்கள் அதை கீழே உள்ளிடலாம். புலத்தை காலியாக விட்டுவிடுவது அசல் பெயரை மீட்டெடுக்கும்.", "SETTINGS_MONITORS_ENTER_NAME": "பெயரை உள்ளிடவும்", "SETTINGS_MONITORS_REORDER_TITLE": "மறுதொடக்கம் மானிட்டர்கள்", "SETTINGS_MONITORS_REORDER_DESC": "தட்டில் மானிட்டர்கள் காட்டப்படும் வரிசையை மாற்றவும். மாற்றங்களைச் செய்ய சொடுக்கு செய்து இழுக்கவும்.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "பிரகாசத்தை இயல்பாக்குங்கள்", "SETTINGS_MONITORS_NORMALIZE_DESC": "மானிட்டர்கள் பெரும்பாலும் வெவ்வேறு பிரகாசமான வரம்புகளைக் கொண்டுள்ளன. ஒரு காட்சிக்கு நிமிடம்/அதிகபட்ச பிரகாசத்தை கட்டுப்படுத்துவதன் மூலம், காட்சிகளுக்கு இடையிலான ஒளி அளவுகள் மிகவும் சீரானவை. இதே போன்ற மானிட்டர்கள் அதே அமைப்புகளைப் பயன்படுத்தும்.", "SETTINGS_MONITORS_DETAILS_NAME": "பெயர்", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "உள் பெயர்", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "தொடர்பு முறை", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "தற்போதைய ஒளி", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "அதிகபட்ச ஒளி", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "ஒளி இயல்பாக்கம்", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "செயலற்ற உள் காட்சியை மறைக்கவும்", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "மூடி மூடப்பட்டால் அல்லது சன்னல்களில் உள் காட்சி முடக்கப்பட்டால், பேனலில் பிரகாசமான ச்லைடரை மறைக்கவும்.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "காட்சிகளை மறைக்கவும்", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "ஃப்ளைஅவுட்டிலிருந்து குறிப்பிட்ட காட்சிகளை மறைக்க விரும்பினால், அவற்றை இங்கே மாற்றலாம்.", "SETTINGS_FEATURES_DESCRIPTION": "பிரகாசமான பேனலில் குறிப்பிட்ட டி.டி.சி/சிஐ அம்சங்களை இயக்கவும் அல்லது முடக்கவும். உங்கள் மானிட்டர் பிரகாசமான குழுவில் காண்பிக்க குறைந்தபட்சம் ஒரு நற்பொருத்தம் இயக்கப்பட வேண்டும். எல்லா காட்சிகளும் மடிக்கணினி/டேப்லெட் காட்சிகள் போன்ற இந்த அம்சங்களை ஆதரிக்கவில்லை.", "SETTINGS_FEATURES_UNSUPPORTED": "இந்த மானிட்டர் டிடிசி/சிஐ அம்சங்களை ஆதரிக்கவில்லை.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "தற்போதைய மதிப்புகளை சரிபார்க்கவும்", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "ஒளி பேனலைத் திறக்கும்போது மானிட்டரிலிருந்து அண்மைக் கால மதிப்புகளை எப்போதும் பெறுங்கள். ட்விங்கிள் தட்டுக்கு வெளியே இருந்து ஒளி (அல்லது மாறுபாடு போன்ற பிற வி.சி.பி குறியீடுகள்) அடிக்கடி மாறினால் இதை இயக்கவும்.", "SETTINGS_FEATURES_POWER_TITLE": "ஆற்றல் நிலை சமிக்ஞை", "SETTINGS_FEATURES_POWER_DESC": "உங்கள் காட்சியை அணைக்க DDC/CI கட்டளையை அனுப்பும்போது, பின்வரும் மதிப்பு (கள்) அனுப்பப்படும்.", "SETTINGS_FEATURES_POWER_STANDBY": "காத்திருப்பு", "SETTINGS_FEATURES_POWER_OFF": "ஆற்றல் முடக்குகிறது", "SETTINGS_FEATURES_POWER_COMPAT": "மிகவும் இணக்கமானது", "SETTINGS_FEATURES_POWER_WARNING": "\"காத்திருப்பு\" விருப்பம் ட்விங்கிள் தட்டில் இருந்து மானிட்டரை மாற்ற அனுமதிக்க அதிக வாய்ப்புள்ளது. இருப்பினும், பல மானிட்டர்கள் மின் நிலையை மாற்றுவதற்கு சரியாக பதிலளிக்கவில்லை. உங்கள் சொந்த ஆபத்தில் பயன்படுத்தவும்.", "SETTINGS_FEATURES_ADD": "அம்சத்தைச் சேர்க்கவும்", "SETTINGS_FEATURES_ADD_DESC": "உங்கள் காட்சியில் நீங்கள் சேர்க்க விரும்பும் அம்சத்திற்காக VCP குறியீட்டை உள்ளிடவும். இந்த வி.சி.பி குறியீட்டை உங்கள் காட்சி உண்மையில் ஆதரித்தால் ட்விங்கிள் தட்டு சரிபார்க்காது என்பதை நினைவில் கொள்க. உங்கள் சொந்த ஆபத்தில் பயன்படுத்தவும்.", "SETTINGS_FEATURES_ADD_VCP": "வி.சி.பி குறியீடு", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "வி.சி.பி குறியீடு (எ.கா. 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "இந்த நற்பொருத்தம் ஏற்கனவே செயலில் உள்ளது.", "SETTINGS_FEATURES_VCP_LIST_TITLE": "இந்த காட்சியால் அறிவிக்கப்பட்ட அனைத்து வி.சி.பி குறியீடுகளும்", "SETTINGS_FEATURES_VCP_LIST_DESC": "விண்டோசுக்கு இந்த காட்சி மூலம் புகாரளிக்கப்பட்ட VCP குறியீடுகளின் பட்டியல் பின்வருமாறு. இந்த வி.சி.பி குறியீடுகளின் செயல்பாடு அல்லது நிலைத்தன்மையை ட்விங்கிள் தட்டு சரிபார்க்காது. அவற்றை உங்கள் சொந்த ஆபத்தில் பயன்படுத்தவும்.", "SETTINGS_FEATURES_VCP_EXPECTED": "எதிர்பார்க்கப்படும் மதிப்புகள்", "SETTINGS_TIME_TITLE": "நாள் சரிசெய்தல் நேரம்", "SETTINGS_TIME_DESC": "விரும்பிய நேரத்தில் உங்கள் மானிட்டர்களை ஒரு குறிப்பிட்ட பிரகாச நிலைக்கு தானாக அமைக்கவும். அனைத்து மானிட்டர்களும் ஒரே, இயல்பாக்கப்பட்ட நிலைகளுக்கு அமைக்கப்படும்.", "SETTINGS_TIME_ADD": "ஒரு நேரத்தைச் சேர்க்கவும்", "SETTINGS_TIME_REMOVE": "நேரத்தை அகற்று", "SETTINGS_TIME_INDIVIDUAL_TITLE": "தனிப்பட்ட காட்சிகளுக்கு பிரகாசத்தை அமைக்கவும்", "SETTINGS_TIME_INDIVIDUAL_DESC": "எல்லா காட்சிகளுக்கும் பதிலாக ஒரே நேரத்தில் ஒரு காட்சிக்கு பிரகாசத்தை உள்ளமைக்கவும்.", "SETTINGS_TIME_TRANSITON_TITLE": "ஒளி மாற்றம் விரைவு", "SETTINGS_TIME_TRANSITON_DESC": "பகல் மாற்றங்களின் நேரம் செயல்படுத்தப்படும்போது எவ்வளவு விரைவாக ஒளி மாற வேண்டும்.", "SETTINGS_TIME_STARTUP_TITLE": "பயன்பாட்டு தொடக்கத்தில் சரிபார்க்கவும்", "SETTINGS_TIME_STARTUP_DESC": "ட்விங்கிள் தட்டு தொடங்கும் போது மிகவும் பொருத்தமான நேரத்தை பொருத்த பிரகாசத்தை சரிசெய்யவும்.", "SETTINGS_TIME_IDLE_TITLE": "செயலற்ற கண்டறிதல்", "SETTINGS_TIME_IDLE_DESC": "ஒரு குறிப்பிட்ட காலத்திற்கு எந்த உள்ளீடும் கண்டறியப்படாதபோது, அனைத்து காட்சிகளின் பிரகாசமும் குறைக்கப்படும்.", "SETTINGS_TIME_ANIMATE_TITLE": "நேரங்களுக்கு இடையில் உயிரூட்டவும்", "SETTINGS_TIME_ANIMATE_DESC": "தற்போதைய மற்றும் அடுத்த திட்டமிடப்பட்ட நிகழ்வுக்கு இடையில் பிரகாச மதிப்புகள் அனிமேசன் செய்யப்படும். சிபியு பயன்பாட்டை அதிகரிக்கலாம். இது செயலில் இருக்கும்போது கையேடு பிரகாச மாற்றங்கள் விரைவாக மேலெழுதப்படும்.", "SETTINGS_TIME_SUN_TITLE": "சூரிய நிலைக்கான ஒருங்கிணைப்புகள்", "SETTINGS_TIME_SUN_DESC": "நேர மாற்றங்களுக்கு \"சூரிய நிலை\" பயன்படுத்த, உங்கள் தற்போதைய அட்சரேகை மற்றும் தீர்க்கரேகையை உள்ளிடவும், இதனால் சரியான நேரங்களை தீர்மானிக்க முடியும்.", "SETTINGS_TIME_LAT": "அகலாங்கு", "SETTINGS_TIME_LONG": "நெட்டாங்கு", "SETTINGS_TIME_SUN_GET": "ஒருங்கிணைப்புகளைப் பெறுங்கள்", "SETTINGS_TIME_IDLE_FS_TITLE": "முழுத்திரை பயன்பாடுகள் செயலற்ற கண்டறிதலைத் தடுக்கின்றன", "SETTINGS_TIME_IDLE_FS_DESC": "முழுத்திரை பயன்பாடுகள் செயலற்ற கண்டறிதலைத் தடுக்கின்றன. இது கவனம் செலுத்திய சாளரத்திற்கு மட்டுமே பொருந்தும்.", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "செயலற்ற கண்டறிதல் மீடியா தொகுதிகள்", "SETTINGS_TIME_IDLE_MEDIA_DESC": "எந்தவொரு ஊடகமும் விளையாடும்போது செயலற்ற கண்டறிதல் முடக்கப்படும். இதில் வீடியோ மற்றும் ஆடியோ இரண்டுமே அடங்கும். மீடியா விளையாடுவதாக சாளரங்கள் தெரிவிக்கும்போது மட்டுமே இது பொருந்தும்.", "SETTINGS_HOTKEYS_TITLE": "ஆட்கீச்", "SETTINGS_HOTKEYS_DESC": "ஒன்று அல்லது அனைத்து காட்சிகளின் பிரகாசத்தை சரிசெய்ய ஆட்கீசை உள்ளமைக்கவும்.", "SETTINGS_HOTKEYS_ADD": "ஆட்ச்கி சேர்க்கவும்", "SETTINGS_HOTKEYS_REMOVE": "ஆட்ச்கியை அகற்று", "SETTINGS_HOTKEYS_INCREASE": "பிரகாசத்தை அதிகரிக்கவும்", "SETTINGS_HOTKEYS_DECREASE": "பிரகாசத்தைக் குறைத்தல்", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "சாவியை இங்கே அழுத்தவும்", "SETTINGS_HOTKEYS_LEVEL_TITLE": "பிரகாசமான நிலை சரிசெய்தல்", "SETTINGS_HOTKEYS_LEVEL_DESC": "ஆட்கிகளைப் பயன்படுத்தும் போது பிரகாசத்தை எவ்வளவு சரிசெய்ய வேண்டும்.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "உருட்டும் தொகை", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "தலைகீழ் சுருள்", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "கணினி தட்டு ஐகானை ச்க்ரோலிங் செய்யும் போது, உருள் திசை மாற்றப்படும்.", "SETTINGS_HOTKEYS_TOD_TITLE": "முடக்குகிறது செயலைக் காட்டுகிறது", "SETTINGS_HOTKEYS_TOD_DESC": "டர்ன் ஆஃப் டிச்ப்ளேச் ஆட்ச்கி அல்லது ஐகானைப் பயன்படுத்தும் போது அனுப்பப்பட்ட சமிக்ஞையைத் தனிப்பயனாக்கவும். உள்ளீடு (எ.கா. சுட்டி அல்லது விசைப்பலகை) விண்டோசால் கண்டறியப்படும் வரை மென்பொருள் சமிக்ஞை கருப்பு திரையைக் காண்பிக்கும். வன்பொருள் சமிக்ஞை மானிட்டர்களுக்கு சக்தியை அணைக்கும்.", "SETTINGS_HOTKEYS_TOD_NONE": "எதுவுமில்லை (ஐகானை மறைக்க)", "SETTINGS_HOTKEYS_TOD_SOFT": "மென்பொருள் சமிக்ஞை (இயல்புநிலை)", "SETTINGS_HOTKEYS_TOD_HARD": "வன்பொருள்* சமிக்ஞை (டி.டி.சி/சிஐ மட்டும்)", "SETTINGS_HOTKEYS_TOD_BOTH": "வன்பொருள்* & மென்பொருள் சமிக்ஞை", "SETTINGS_HOTKEYS_TOD_NOTE": "*குறிப்பு: எல்லா டி.டி.சி/சிஐ மானிட்டர்களும் இந்த அம்சத்தை ஆதரிக்கவில்லை.", "SETTINGS_HOTKEYS_BREAK_TITLE": "ஆட்கிகள் இணைக்கப்பட்ட நிலைகளை உடைக்கின்றன", "SETTINGS_HOTKEYS_BREAK_DESC": "ஒற்றை காட்சி மற்றும் \"இணைக்கப்பட்ட நிலைகள்\" செயலில் இருக்கும் போது, அது செயலிழக்கப்படும்.", "SETTINGS_HOTKEY_OFF_WARN": "இந்த நடவடிக்கை \"டர்ன் ஆஃப் டிச்ப்ளேச் செயல்\" இன் கீழ் தேர்ந்தெடுக்கப்பட்ட விருப்பத்தைப் பயன்படுத்தும். அதற்கு பதிலாக குறிப்பிட்ட காட்சிகளை அணைக்க விரும்பினால், அதற்கு பதிலாக \"செட்\" அல்லது \"சுழற்சி\" ஆட்கி செயலைப் பயன்படுத்தவும்.", "SETTINGS_HOTKEY_TARGET": "செயல் இலக்கு", "SETTINGS_HOTKEY_VALUE": "மதிப்பு", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "ஒரு எண்ணை உள்ளிடவும்", "SETTINGS_HOTKEY_VALUES": "மதிப்புகள்", "SETTINGS_HOTKEY_ADD_VALUE": "மதிப்பு சேர்க்கவும்", "SETTINGS_HOTKEY_ACTION": "செயல்", "SETTINGS_HOTKEY_ACTION_SET": "மதிப்பை அமைக்கவும்", "SETTINGS_HOTKEY_ACTION_OFFSET": "மதிப்பை சரிசெய்யவும்", "SETTINGS_HOTKEY_ACTION_CYCLE": "மதிப்புகளின் சுழற்சி பட்டியல்", "SETTINGS_PROFILES_TITLE": "சுயவிவரங்கள்", "SETTINGS_PROFILES_DESC": "கவனம் செலுத்திய பயன்பாட்டைப் பொறுத்து தானாகவே ஒளி அல்லது குறுக்குவழி மேலடுக்கு நடத்தை சரிசெய்யவும். முன்பே வரையறுக்கப்பட்ட சுயவிவரங்களுக்கு பிரகாசத்தை விரைவாக மாற்ற கணினி தட்டில் வலது சொடுக்கு பட்டியலில் சுயவிவரங்களையும் சேர்க்கலாம்.", "SETTINGS_PROFILES_ADD": "புதிய சுயவிவரம்", "SETTINGS_PROFILES_NAME": "சுயவிவர பெயர்", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "செயலில் இருக்கும்போது பிரகாசத்தை அமைக்கவும்", "SETTINGS_PROFILES_SHOW_MENU": "வலது சொடுக்கு தட்டு பட்டியலில் காண்பி", "SETTINGS_PROFILES_TRIGGER_TITLE": "பயன்பாட்டு தூண்டுதல் அமைப்புகள்", "SETTINGS_PROFILES_APP_PATH": "பயன்பாட்டு பாதை", "SETTINGS_PROFILES_APP_DESC": "ஒரு குறிப்பிட்ட பயன்பாடு கவனம் செலுத்தும்போது இந்த சுயவிவரம் தானாகவே செயல்படுத்த விரும்பினால், கீழே உள்ள EXE இன் முழு அல்லது பகுதி பாதையை உள்ளிடவும்.", "SETTINGS_PROFILES_OVERLAY_TITLE": "மேலெழுதும் வகை", "SETTINGS_PROFILES_OVERLAY_DESC": "குறிப்பிட்ட பயன்பாடு கவனம் செலுத்தும்போது ஆட்ச்கி மேலடுக்கின் நடத்தையை மாற்றுகிறது. சுயவிவரம் கைமுறையாக செயல்படுத்தப்படும்போது இந்த நற்பொருத்தம் செயல்படாது.", "SETTINGS_UPDATES_TITLE": "புதுப்பிப்புகள்", "SETTINGS_UPDATES_VERSION": "உங்களிடம் ட்விங்கிள் தட்டு உள்ளது {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "புதிய பதிப்புகளை தானாக சரிபார்க்கவும்", "SETTINGS_UPDATES_AUTOMATIC_DESC": "புதிய பதிப்பு இருக்கும்போது, அது ஒளி பேனலில் காண்பிக்கப்படும்.", "SETTINGS_UPDATES_MS_STORE": "புதிய பதிப்புகளைச் சரிபார்க்க, நுண்மென் கடை பயன்பாட்டைப் பார்வையிடவும்.", "SETTINGS_UPDATES_AVAILABLE": "ட்விங்கிள் தட்டின் புதிய பதிப்பு கிடைக்கிறது!", "SETTINGS_UPDATES_NONE_AVAILABLE": "புதுப்பித்த நிலையில். தற்போதைய பதிப்பில் பின்வரும் மாற்றங்கள் உள்ளன:", "SETTINGS_UPDATES_DOWNLOADING": "புதுப்பிப்பைப் பதிவிறக்குகிறது…", "SETTINGS_UPDATES_DOWNLOAD": "பதிவிறக்கம் செய்து நிறுவவும் {{1}}", "SETTINGS_UPDATES_CHANNEL": "சேனலைப் புதுப்பிக்கவும்", "SETTINGS_UPDATES_BRANCH_STABLE": "நிலையான (இயல்புநிலை)", "SETTINGS_UPDATES_BRANCH_BETA": "பீட்டா", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "ஒளிரும்" } ================================================ FILE: src/localization/th.json ================================================ { "LANGUAGE": "ภาษาไทย", "GENERIC_OK": "ตกลง", "GENERIC_CANCEL": "ยกเลิก", "GENERIC_SAVE": "บันทึก", "GENERIC_CLEAR": "ล้าง", "GENERIC_DELETE": "ลบ", "GENERIC_OFF": "ปิด", "GENERIC_ON": "เปิด", "GENERIC_QUIT": "ออก", "GENERIC_CLOSE": "ปิด", "GENERIC_SETTINGS": "การตั้งค่า", "GENERIC_INSTALL": "ติดตั้ง", "GENERIC_DISMISS": "ยกเลิก", "GENERIC_DEFAULT": "ค่าเริ่มต้น", "GENERIC_OPTIONAL": "ไม่บังคับ", "GENERIC_DISPLAY_SINGLE": "หน้าจอ", "GENERIC_ALL_DISPLAYS": "ทุกหน้าจอ", "GENERIC_REFRESH_DISPLAYS": "รีเฟรชหน้าจอ", "GENERIC_MINIMUM": "น้อยที่สุด", "GENERIC_MAXIMUM": "มากที่สุด", "GENERIC_NO_DISPLAYS": "ไม่พบหน้าจอ! โปรดเชื่อมต่อหน้าจอกับพีซีของคุณ", "GENERIC_NO_COMPATIBLE_DISPLAYS": "ไม่พบความเข้ากันได้ของหน้าจอ! โปรดตรวจสอบ DDC/CI ว่าหน้าจอของคุณได้เปิดใช้งานแล้ว", "GENERIC_NO_DISPLAYS_SHORT": "ไม่พบจอแสดงผลที่เข้ากันได้", "GENERIC_SECONDS": "วินาที", "GENERIC_MINUTES": "นาที", "PANEL_TITLE": "ปรับความสว่าง", "PANEL_UPDATE_AVAILABLE": "เวอร์ชั่นใหม่มาแล้ว", "PANEL_BUTTON_LINK_LEVELS": "ระดับลิงค์", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "ปิดหน้าจอ", "PANEL_LABEL_BRIGHTNESS": "ความสว่าง", "PANEL_LABEL_CONTRAST": "ตัดกัน", "PANEL_LABEL_OFF_ON": "สถานะพลังงาน", "PANEL_LABEL_COLOR_TEMPERATURE": "อุณหภูมิสี", "PANEL_LABEL_VOLUME": "ปริมาณ", "PANEL_LABEL_TURN_OFF": "ปิด", "PANEL_LABEL_TURN_ON": "เปิด", "INTRO_TITLE": "สวัสดี Twinkle Tray!", "INTRO_INSTRUCTIONS": "อาจซ่อนไอคอนถาดสำหรับ Twinkle Tray ดังนั้นคุณควรย้ายไปยังตำแหน่งที่คุณสามารถเข้าถึงได้ง่าย ดูคำแนะนำด้านล่าง", "SETTINGS_TITLE": "การตั้งค่าถาด Twinkle", "SETTINGS_SIDEBAR_GENERAL": "ทั่วไป", "SETTINGS_SIDEBAR_MONITORS": "การตั้งค่าจอภาพ", "SETTINGS_SIDEBAR_FEATURES": "คุณสมบัติ DDC/CI", "SETTINGS_SIDEBAR_TIME": "การปรับเวลา", "SETTINGS_SIDEBAR_HOTKEYS": "ปุ่มลัด & ทางลัด", "SETTINGS_SIDEBAR_UPDATES": "อัพเดท", "SETTINGS_GENERAL_TITLE": "ทั่วไป", "SETTINGS_GENERAL_STARTUP": "เปิดตัวเมื่อเริ่มต้น", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "ใช้ความสว่างเมื่อเริ่มต้น", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "คืนค่าความสว่างที่รู้จักล่าสุดสำหรับแต่ละจอแสดงผลเมื่อ Twinkle Tray เริ่มทำงาน", "SETTINGS_GENERAL_THEME_TITLE": "ธีม", "SETTINGS_GENERAL_THEME_SYSTEM": "การตั้งค่าระบบ (ค่าเริ่มต้น)", "SETTINGS_GENERAL_THEME_DARK": "มืด", "SETTINGS_GENERAL_THEME_LIGHT": "แสงสว่าง", "SETTINGS_GENERAL_LANGUAGE_TITLE": "ภาษา", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "ภาษาของระบบ (ค่าเริ่มต้น)", "SETTINGS_GENERAL_RESET_TITLE": "คืนค่าการตั้งค่า", "SETTINGS_GENERAL_RESET_DESC": "กดปุ่มนี้เพื่อล้างการกำหนดค่าของคุณ", "SETTINGS_GENERAL_RESET_BUTTON": "คืนค่าการตั้งค่า", "SETTINGS_GENERAL_ACRYLIC_TITLE": "อะคริลิคเบลอ", "SETTINGS_GENERAL_ACRYLIC_DESC": "เปิดหรือปิดการเบลอเบื้องหลังพื้นหลังโปร่งใสใน Twinkle Tray", "SETTINGS_GENERAL_MICA_TITLE": "ไมกาเบลอ", "SETTINGS_GENERAL_MICA_DESC": "เปิดหรือปิดการเบลอเบื้องหลังพื้นหลังใน Twinkle Tray", "SETTINGS_GENERAL_ANALYTICS_TITLE": "การวิเคราะห์", "SETTINGS_GENERAL_ANALYTICS_DESC": "ส่งข้อมูลการใช้งานเพื่อช่วยปรับปรุง Twinkle Tray ไม่มีการส่งข้อมูลส่วนบุคคล {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "เรียนรู้เพิ่มเติม", "SETTINGS_GENERAL_SCROLL_TITLE": "ทางลัดเลื่อนไอคอนถาด", "SETTINGS_GENERAL_SCROLL_DESC": "ปรับความสว่างของจอแสดงผลทั้งหมดพร้อมกันโดยเลื่อนไปที่ไอคอนถาดระบบ วิธีนี้ใช้ไม่ได้กับแทร็คแพดบางตัว", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "ไอคอนถาด", "SETTINGS_GENERAL_TROUBLESHOOTING": "การแก้ไขปัญหา", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "ปิดใช้งานวิธีการตรวจหามอนิเตอร์", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "หาก Twinkle Tray ไม่ตอบสนองเมื่อคลิกที่ไอคอนถาดหรือตรวจไม่พบจอแสดงผลของคุณ คุณสามารถลองปิดใช้งานวิธีการตรวจหาจอภาพบางวิธีได้ รีสตาร์ท Twinkle Tray เพื่อให้การเปลี่ยนแปลงมีผล {{1}}", "SETTINGS_GENERAL_OVERLAY_TITLE": "พฤติกรรมการซ้อนทับเริ่มต้น", "SETTINGS_GENERAL_OVERLAY_DESC": "ความแรงของปุ่มลัดปรับความสว่างที่จะพยายามแสดงทับแอพอื่น คุณไม่จำเป็นต้องปรับค่านี้", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "เข้ากันได้ดีที่สุด", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "โอเวอร์เลย์จะแสดงทับหน้าต่างส่วนใหญ่ แต่จะไม่บังคับให้ตัวเองอยู่เหนือแอปที่ทำเครื่องหมายว่า \"อยู่ด้านบนเสมอ\"", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "บังคับเปิด", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "พยายามแสดงโอเวอร์เลย์ทับบนหน้าต่างอื่นๆ เสมอ การกระทำดังกล่าวอาจทำให้เกิดปัญหาในเกมแบบเต็มจอพิเศษและแอปแบบเต็มจออื่นๆ ได้ นอกจากนี้ยังอาจทำให้ระบบป้องกันการโกงตรวจับในบางเกมอีกด้วย", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "การควบคุม DDC/CI แบบเก่า", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "ใช้การตรวจจับการแสดงผล DDC/CI เวอร์ชันเก่า v1.15.5", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "การปรับความสว่างอัตโนมัติ", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "หากจอภาพของคุณตอบสนองแปลก ๆ หลังจากปิด/เปิด หรือถอด/เชื่อมต่อฮาร์ดแวร์ การปิดใช้งานนี้อาจช่วยได้", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "ข้ามการใช้อัตโนมัติกับจอภาพเฉพาะ", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "ปิดใช้งานการปรับความสว่างอัตโนมัติหลังจากเหตุการณ์ฮาร์ดแวร์/พลังงานทั้งหมดสำหรับจอภาพเฉพาะ รวมถึงฟีเจอร์ตรวจจับการไม่ได้ใช้งาน", "SETTINGS_GENERAL_REPORT_TITLE": "สร้างรายงาน", "SETTINGS_GENERAL_REPORT_DESC": "บันทึกไฟล์ข้อความที่มีข้อมูลเกี่ยวกับจอภาพและการตั้งค่าของคุณเพื่อแก้ไขข้อบกพร่อง", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "ปิดใช้งานการซ้อนทับ", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "หากการซ้อนทับปุ่มลัดของ Twinkle Tray รบกวนการใช้งานแบบเต็มหน้าจอ คุณสามารถปิดใช้งานได้ที่นี่", "SETTINGS_MONITORS_RATE_TITLE": "อัตราการอัปเดตความสว่าง", "SETTINGS_MONITORS_RATE_DESC": "ความถี่ที่ความสว่างจะได้รับการอัปเดตบนจอแสดงผลของคุณในขณะที่คุณปรับค่า เพิ่มเวลาหากจอภาพของคุณกะพริบ", "SETTINGS_MONITORS_RATE_0": "ทันที", "SETTINGS_MONITORS_RATE_1": "เร็ว (250 มิลลิวินาที)", "SETTINGS_MONITORS_RATE_2": "ปกติ (500 มิลลิวินาที)", "SETTINGS_MONITORS_RATE_3": "ช้า (1 วินาที)", "SETTINGS_MONITORS_RATE_4": "ช้ามาก (2 วินาที)", "SETTINGS_MONITORS_RENAME_TITLE": "เปลี่ยนชื่อจอภาพ", "SETTINGS_MONITORS_RENAME_DESC": "หากคุณต้องการใช้ชื่อที่แตกต่างกันสำหรับจอภาพแต่ละจอ (เช่น \"จอภาพด้านซ้าย\" \"จอภาพกลาง\") คุณสามารถป้อนชื่อด้านล่างนี้ การเว้นฟิลด์ว่างไว้จะเป็นการคืนค่าชื่อเดิม", "SETTINGS_MONITORS_ENTER_NAME": "ใส่ชื่อ", "SETTINGS_MONITORS_REORDER_TITLE": "เรียงลำดับจอภาพใหม่", "SETTINGS_MONITORS_REORDER_DESC": "เปลี่ยนลำดับการแสดงจอภาพในถาด คลิกและลากเพื่อทำการเปลี่ยนแปลง", "SETTINGS_MONITORS_NORMALIZE_TITLE": "ปรับความสว่างให้เป็นปกติ", "SETTINGS_MONITORS_NORMALIZE_DESC": "จอภาพมักมีช่วงความสว่างที่แตกต่างกัน ด้วยการจำกัดความสว่างต่ำสุด/สูงสุดต่อจอแสดงผล ระดับความสว่างระหว่างจอแสดงผลจะมีความสอดคล้องกันมากขึ้น จอภาพที่คล้ายกันจะใช้การตั้งค่าเดียวกัน", "SETTINGS_MONITORS_DETAILS_NAME": "ชื่อ", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "ชื่อภายใน", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "วิธีการสื่อสาร", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "ความสว่างปัจจุบัน", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "ความสว่างสูงสุด", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "การปรับความสว่างให้เป็นปกติ", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "ซ่อนจอแสดงผลภายใน", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "เมื่อปิดฝาหรือจอแสดงผลภายในถูกปิดใช้งานใน Windows ให้ซ่อนแถบเลื่อนความสว่างในแผงควบคุม", "SETTINGS_FEATURES_DESCRIPTION": "เปิดหรือปิดใช้งานคุณลักษณะ DDC/CI เฉพาะในแผงความสว่าง ต้องเปิดใช้งานคุณสมบัติอย่างน้อยหนึ่งรายการเพื่อให้จอภาพของคุณแสดงในแผงความสว่าง จอภาพบางจอไม่รองรับคุณสมบัติเหล่านี้ เช่น จอแล็ปท็อป/แท็บเล็ต", "SETTINGS_FEATURES_UNSUPPORTED": "จอภาพนี้ไม่รองรับคุณสมบัติ DDC/CI", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "รับความสว่างปัจจุบัน", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "รับระดับความสว่างล่าสุดจากจอภาพเสมอเมื่อเปิดหน้าความสว่าง เปิดใช้งานสิ่งนี้หากความสว่างมักเปลี่ยนจากภายนอก Twinkle Tray (เช่น แอพพลิเคชั่นอื่น)", "SETTINGS_TIME_TITLE": "การปรับเวลาของวัน", "SETTINGS_TIME_DESC": "ตั้งค่าจอภาพของคุณเป็นระดับความสว่างที่กำหนดโดยอัตโนมัติในเวลาที่ต้องการ จอภาพทั้งหมดจะถูกตั้งค่าเป็นระดับเดียวกันและเป็นมาตรฐาน", "SETTINGS_TIME_ADD": "เพิ่มเวลา", "SETTINGS_TIME_REMOVE": "ลบเวลา", "SETTINGS_TIME_INDIVIDUAL_TITLE": "ตั้งค่าความสว่างสำหรับจอภาพแต่ละจอ", "SETTINGS_TIME_INDIVIDUAL_DESC": "กำหนดค่าความสว่างต่อจอแสดงผลแทนการแสดงผลทั้งหมดพร้อมกัน", "SETTINGS_TIME_STARTUP_TITLE": "ตรวจสอบเมื่อเริ่มต้นแอป", "SETTINGS_TIME_STARTUP_DESC": "ปรับความสว่างให้ตรงกับเวลาที่เกี่ยวข้องมากที่สุดเมื่อเริ่ม Twinkle Tray", "SETTINGS_TIME_IDLE_TITLE": "การตรวจจับเมื่อไม่ได้ใช้งาน", "SETTINGS_TIME_IDLE_DESC": "เมื่อตรวจไม่พบสัญญาณเข้าในช่วงระยะเวลาหนึ่ง ความสว่างของจอแสดงผลทั้งหมดจะลดลง", "SETTINGS_HOTKEYS_TITLE": "ปุ่มลัด", "SETTINGS_HOTKEYS_DESC": "กำหนดค่าปุ่มลัดเพื่อปรับความสว่างของจอแสดงผลหนึ่งจอหรือทั้งหมด", "SETTINGS_HOTKEYS_ADD": "เพิ่มปุ่มลัด", "SETTINGS_HOTKEYS_REMOVE": "ลบปุ่มลัด", "SETTINGS_HOTKEYS_INCREASE": "เพิ่มความสว่าง", "SETTINGS_HOTKEYS_DECREASE": "ลดความสว่าง", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "กดปุ่มที่นี่", "SETTINGS_HOTKEYS_LEVEL_TITLE": "การปรับระดับความสว่าง", "SETTINGS_HOTKEYS_LEVEL_DESC": "ควรปรับความสว่างเท่าใดเมื่อใช้ปุ่มลัด", "SETTINGS_HOTKEYS_TOD_TITLE": "ปิดการแสดงการกระทำ", "SETTINGS_HOTKEYS_TOD_DESC": "ปรับแต่งสัญญาณที่ส่งเมื่อใช้ปุ่มลัดหรือไอคอน Turn Off Displays สัญญาณซอฟต์แวร์จะแสดงหน้าจอสีดำจนกว่า Windows จะตรวจพบอินพุต (เช่น เมาส์หรือแป้นพิมพ์) สัญญาณฮาร์ดแวร์จะปิดไฟไปยังจอภาพ", "SETTINGS_HOTKEYS_TOD_NONE": "ไม่มี (ซ่อนไอคอน)", "SETTINGS_HOTKEYS_TOD_SOFT": "สัญญาณซอฟต์แวร์ (ค่าเริ่มต้น)", "SETTINGS_HOTKEYS_TOD_HARD": "สัญญาณฮาร์ดแวร์* (DDC/CI เท่านั้น)", "SETTINGS_HOTKEYS_TOD_BOTH": "ฮาร์ดแวร์* และสัญญาณซอฟต์แวร์", "SETTINGS_HOTKEYS_TOD_NOTE": "*หมายเหตุ: จอภาพ DDC/CI บางตัวไม่รองรับคุณสมบัตินี้", "SETTINGS_HOTKEYS_BREAK_TITLE": "ปุ่มลัดแบ่งระดับที่เชื่อมโยง", "SETTINGS_HOTKEYS_BREAK_DESC": "เมื่อใช้ปุ่มลัดสำหรับหน้าจอเดียวและ \"ระดับที่เชื่อมโยง\" เปิดใช้งานอยู่ ปุ่มนี้จะปิดใช้งาน", "SETTINGS_UPDATES_TITLE": "อัพเดท", "SETTINGS_UPDATES_VERSION": "คุณมี Twinkle Tray {{1}}", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "ตรวจสอบเวอร์ชันใหม่โดยอัตโนมัติ", "SETTINGS_UPDATES_AUTOMATIC_DESC": "เมื่อมีเวอร์ชันใหม่จะปรากฏในแผงความสว่าง", "SETTINGS_UPDATES_MS_STORE": "หากต้องการตรวจสอบเวอร์ชันใหม่ ให้ไปที่แอป Microsoft Store", "SETTINGS_UPDATES_AVAILABLE": "Twinkle Tray เวอร์ชั่นใหม่มาแล้ว!", "SETTINGS_UPDATES_NONE_AVAILABLE": "ปัจจุบัน. เวอร์ชันปัจจุบันมีการเปลี่ยนแปลงดังต่อไปนี้:", "SETTINGS_UPDATES_DOWNLOADING": "กำลังดาวน์โหลดอัปเดต…", "SETTINGS_UPDATES_DOWNLOAD": "ดาวน์โหลดและติดตั้ง {{1}}", "GENERIC_PAUSE_TOD": "การปรับเวลาหยุดชั่วคราว", "GENERIC_PAUSE_IDLE": "หยุดการตรวจจับที่ไม่ได้ใช้งานชั่วคราว", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "ซ่อนการแสดง", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "หากคุณต้องการซ่อนการแสดงเฉพาะจากเมนูลอย คุณสามารถสลับปิดได้ที่นี่", "SETTINGS_TIME_ANIMATE_TITLE": "เคลื่อนไหวระหว่างเวลา", "SETTINGS_TIME_ANIMATE_DESC": "ค่าความสว่างจะเคลื่อนไหวระหว่างเหตุการณ์ปัจจุบันและกำหนดการถัดไป อาจเพิ่มการใช้งาน CPU การปรับความสว่างแบบแมนนวลจะถูกเขียนทับอย่างรวดเร็วในขณะที่เปิดใช้งานอยู่", "GENERIC_DDC_WARNING": "คุณสมบัติ DDC/CI เช่น การควบคุมสถานะพลังงานอาจทำให้จอภาพของคุณไม่ตอบสนอง ใช้ความเสี่ยงของคุณเอง", "GENERIC_SPEED_VERY_FAST": "เร็วมาก", "SETTINGS_TIME_TRANSITON_DESC": "ความสว่างควรเปลี่ยนเร็วเพียงใดเมื่อเปิดใช้งานการปรับเวลาของวัน", "GENERIC_SPEED_INSTANT": "ทันที", "GENERIC_SPEED_SLOW": "ช้า", "GENERIC_SPEED_VERY_SLOW": "ช้ามาก", "GENERIC_SPEED_NORMAL": "ปกติ", "GENERIC_SPEED_FAST": "เร็ว", "SETTINGS_TIME_TRANSITON_TITLE": "ความเร็วในการเปลี่ยนความสว่าง", "SETTINGS_UPDATES_BRANCH_STABLE": "เสถียร (ค่าเริ่มต้น)", "SETTINGS_UPDATES_CHANNEL": "ช่องทางการอัปเดต", "SETTINGS_UPDATES_BRANCH_BETA": "เบต้า", "SETTINGS_FEATURES_POWER_COMPAT": "เข้ากันได้ดีที่สุด", "SETTINGS_FEATURES_POWER_OFF": "ปิด" } ================================================ FILE: src/localization/tr.json ================================================ { "LANGUAGE": "Türkçe", "GENERIC_OK": "Tamam", "GENERIC_CANCEL": "İptal", "GENERIC_SAVE": "Kaydet", "GENERIC_CLEAR": "Temizle", "GENERIC_OFF": "Kapat", "GENERIC_ON": "Açık", "GENERIC_QUIT": "Çıkış", "GENERIC_CLOSE": "Kapat", "GENERIC_SETTINGS": "Ayarlar", "GENERIC_INSTALL": "Yükle", "GENERIC_DISMISS": "Reddet", "GENERIC_DISPLAY_SINGLE": "Ekran", "GENERIC_ALL_DISPLAYS": "Tüm Ekranlar", "GENERIC_REFRESH_DISPLAYS": "Ekranları yenile", "GENERIC_MINIMUM": "Min", "GENERIC_MAXIMUM": "Maks", "GENERIC_NO_DISPLAYS": "Ekran bulunamadı. Lütfen bilgisayarınıza bir ekran bağlayın.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Uyumlu ekran bulunamadı. Lütfen monitörünüzün ayarlarında \"DDC/CI\" seçeneğinin etkin olduğundan emin olun.", "GENERIC_NO_DISPLAYS_SHORT": "Uyumlu ekran bulunamadı.", "PANEL_TITLE": "Parlaklık Ayarı", "PANEL_UPDATE_AVAILABLE": "Yeni sürüm mevcut", "PANEL_BUTTON_LINK_LEVELS": "Seviyeleri eşitle", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Ekranları kapat", "PANEL_LABEL_BRIGHTNESS": "Parlaklık", "PANEL_LABEL_CONTRAST": "Kontrast", "PANEL_LABEL_OFF_ON": "Güç durumu", "PANEL_LABEL_COLOR_TEMPERATURE": "Renk Sıcaklığı", "PANEL_LABEL_VOLUME": "Ses", "INTRO_TITLE": "Merhaba, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Muhtemelen Twinkle Tray simgesi sistem tepsisinde gizlenmiş, onu kolayca erişebileceğiniz bir yere taşımalısınız. Talimatlar için aşağıya bakın.", "SETTINGS_TITLE": "Twinkle Tray Ayarları", "SETTINGS_SIDEBAR_GENERAL": "Genel", "SETTINGS_SIDEBAR_MONITORS": "Monitör Ayarları", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI Ayarları", "SETTINGS_SIDEBAR_TIME": "Zaman Ayarlamaları", "SETTINGS_SIDEBAR_HOTKEYS": "Tuşlar & Kısayollar", "SETTINGS_SIDEBAR_UPDATES": "Güncellemeler", "SETTINGS_GENERAL_TITLE": "Genel", "SETTINGS_GENERAL_STARTUP": "Başlangıçta çalıştır", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Başlangıçta parlaklığı uygula", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Twinkle Tray başladığında her ekran için bilinen son parlaklığı geri yüklesin.", "SETTINGS_GENERAL_THEME_TITLE": "Tema", "SETTINGS_GENERAL_THEME_SYSTEM": "Sistem tercihleri (varsayılan)", "SETTINGS_GENERAL_THEME_DARK": "Koyu", "SETTINGS_GENERAL_THEME_LIGHT": "Açık", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Lisan", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Sistem dili (varsayılan)", "SETTINGS_GENERAL_RESET_TITLE": "Ayarları sıfırla", "SETTINGS_GENERAL_RESET_DESC": "Yapılandırmanızı temizlemek için bu düğmeye basın.", "SETTINGS_GENERAL_RESET_BUTTON": "Ayarları sıfırla", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Akrilik Bulanıklık", "SETTINGS_GENERAL_ACRYLIC_DESC": "Twinkle Tray'de saydam arka planların arkasındaki bulanıklığı etkinleştirin veya devre dışı bırakın.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Analitik", "SETTINGS_GENERAL_ANALYTICS_DESC": "Twinkle Tray'i iyileştirmeye yardımcı olmak için kullanım verilerini gönderin. Hiçbir kişisel bilgi gönderilmez. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Daha fazla bilgi edinin", "SETTINGS_GENERAL_SCROLL_TITLE": "Tepsi simgesi kaydırma kısayolu", "SETTINGS_GENERAL_SCROLL_DESC": "Sistem tepsisi simgesini kaydırarak tüm ekranların parlaklığını bir kerede ayarlayın. Bu, bazı dokunmatik yüzeyler ile çalışmaz.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Tepsi ikonu", "SETTINGS_MONITORS_RATE_TITLE": "Parlaklık güncelleme oranı", "SETTINGS_MONITORS_RATE_DESC": "Parlaklık ayarı yaparken monitörlerin ne sıklıkla güncelleneceğini ayarlayın. Ekranlarda titreme oluyorsa bu süreyi artırın.", "SETTINGS_MONITORS_RATE_0": "Gülünç", "SETTINGS_MONITORS_RATE_1": "Hızlı (250 ms)", "SETTINGS_MONITORS_RATE_2": "Normal (500 ms)", "SETTINGS_MONITORS_RATE_3": "Yavaş (1 saniye)", "SETTINGS_MONITORS_RATE_4": "Çok Yavaş (2 saniye)", "SETTINGS_MONITORS_RENAME_TITLE": "Monitörleri Yeniden Adlandır", "SETTINGS_MONITORS_RENAME_DESC": "Her monitör için farklı bir ad tercih ederseniz (ör. \"Sol Monitör\", \"Orta Monitör\"), aşağıda girebilirsiniz. Alanı boş bırakmak orijinal adı geri yükleyecektir.", "SETTINGS_MONITORS_ENTER_NAME": "İsim giriniz", "SETTINGS_MONITORS_REORDER_TITLE": "Monitörleri Yeniden Sırala", "SETTINGS_MONITORS_REORDER_DESC": "Monitörlerin tepside görüntülenme sırasını değiştirin. Değişiklik yapmak için tıklayın ve sürükleyin.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Parlaklığı Normalleştir", "SETTINGS_MONITORS_NORMALIZE_DESC": "Monitörler genellikle farklı parlaklık aralıklarına sahiptir. Ekran başına minimum/maks parlaklığı sınırlayarak bu ekranlar arasındaki parlaklık seviyelerini daha tutarlı hale getirebilirsiniz. Benzer monitörler aynı ayarları kullanır.", "SETTINGS_MONITORS_DETAILS_NAME": "İsim", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Dahili İsim", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "İletişim metodu", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Mevcut Parlaklık", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Maksimum Parlaklık", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Parlaklık Normalleştirme", "SETTINGS_FEATURES_DESCRIPTION": "Parlaklık panelinde belirli DDC/CI özelliklerini etkinleştirin veya devre dışı bırakın. Monitörünüzün parlaklık panelinde görünmesi için en az bir özelliğin etkinleştirilmesi gerekir. Tüm ekranlar bu özellikleri desteklemeyebilir (örneğin Dizüstü bilgisayar/tablet).", "SETTINGS_TIME_TITLE": "Günün Saati Ayarlamaları", "SETTINGS_TIME_DESC": "Monitörlerinizi istediğiniz zaman belirli bir parlaklık düzeyine otomatik olarak ayarlayın. Tüm monitörler aynı, normalleştirilmiş seviyelere ayarlanacaktır.", "SETTINGS_TIME_ADD": "Bir zaman ekle", "SETTINGS_TIME_REMOVE": "Zamanı kaldır", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Farklı ekranlar için parlaklığı ayarlayın", "SETTINGS_TIME_INDIVIDUAL_DESC": "Tüm ekranlar için aynı anda değil, ekran başına parlaklığı yapılandırın.", "SETTINGS_TIME_STARTUP_TITLE": "Uygulama başlangıcında kontrol et", "SETTINGS_TIME_STARTUP_DESC": "Twinkle Tray başladığında parlaklığı zamana en uygun şekilde ayarla.", "SETTINGS_HOTKEYS_TITLE": "Kısayol Tuşları", "SETTINGS_HOTKEYS_DESC": "Ekran parlaklığını ayarlamak için kısayol tuşlarını yapılandırın.", "SETTINGS_HOTKEYS_ADD": "Kısayol tuşu ekle", "SETTINGS_HOTKEYS_REMOVE": "Kısayol tuşunu kaldır", "SETTINGS_HOTKEYS_INCREASE": "Parlaklığı Artır", "SETTINGS_HOTKEYS_DECREASE": "Parlaklığı Azalt", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Burada tuşlara basın", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Parlaklık seviyesi ayarı", "SETTINGS_HOTKEYS_LEVEL_DESC": "Kısayol tuşlarını kullanırken parlaklığın ayarlanma seviyesi.", "SETTINGS_HOTKEYS_TOD_TITLE": "Ekranları Kapat eylemi", "SETTINGS_HOTKEYS_TOD_DESC": "Ekranları Kapat kısayol tuşunu veya simgesini kullanırken gönderilen sinyali özelleştirin. Yazılım sinyali, bir giriş (ör. fare veya klavye) Windows tarafından algılanana kadar siyah bir ekran gösterecektir. Donanım sinyali, monitörleri kapatır.", "SETTINGS_HOTKEYS_TOD_NONE": "Yok (simgeyi gizle)", "SETTINGS_HOTKEYS_TOD_SOFT": "Yazılım sinyali (varsayılan)", "SETTINGS_HOTKEYS_TOD_HARD": "Donanım* sinyali (yalnızca DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Donanım* ve yazılım sinyali", "SETTINGS_HOTKEYS_TOD_NOTE": "*Not: Tüm DDC/CI monitörler bu özelliği desteklemez.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Kısayol tuşları bağlantılı seviyeleri bozar", "SETTINGS_HOTKEYS_BREAK_DESC": "Tek bir ekran için bir kısayol tuşu kullanıldığında ve \"bağlı seviyeler\" aktif olduğunda, devre dışı bırakılacaktır.", "SETTINGS_UPDATES_TITLE": "Güncellemeler", "SETTINGS_UPDATES_VERSION": "Mevcut Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Yeni sürümleri otomatik olarak kontrol et", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Yeni bir sürüm çıktığında parlaklık panelinde gösterilsin.", "SETTINGS_UPDATES_MS_STORE": "Yeni sürümleri kontrol etmek için Microsoft Store uygulamasını ziyaret edin.", "SETTINGS_UPDATES_AVAILABLE": "Twinkle Tray'in yeni versiyonu mevcut!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Güncel. Geçerli sürüm aşağıdaki değişiklikleri içerir:", "SETTINGS_UPDATES_DOWNLOADING": "Güncelleme indiriliyor…", "SETTINGS_UPDATES_DOWNLOAD": "{{1}} İndir ve Yükle", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Twinkle Tray, tepsi simgesine tıklandığında yanıt vermiyorsa veya ekranlarınızı algılamıyorsa, belirli monitör algılama yöntemlerini devre dışı bırakmayı deneyebilirsiniz. Değişikliklerin etkili olması için Twinkle Tray'i yeniden başlatın. {{1}}", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Etkin Olmayan Dahili Ekranı Gizle", "SETTINGS_GENERAL_MICA_TITLE": "Mika Bulanıklığı", "SETTINGS_GENERAL_MICA_DESC": "Twinkle Tray'de arka planların arkasındaki bulanıklığı etkinleştirin veya devre dışı bırakın.", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Kapak kapalıyken veya dahili ekran Windows'ta devre dışı bırakıldığında, paneldeki parlaklık kaydırıcısını gizleyin.", "SETTINGS_FEATURES_UNSUPPORTED": "Bu monitör DDC/CI özelliklerini desteklemez.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Geçerli Parlaklığı Al", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Parlaklık sayfasını açarken her zaman monitörden en son parlaklık seviyesini alın. Parlaklık sık sık Twinkle Tray dışından değiştiriliyorsa (örn. başka bir uygulama) bunu etkinleştirin.", "GENERIC_MINUTES": "dakika", "GENERIC_SECONDS": "saniye", "SETTINGS_TIME_IDLE_TITLE": "Boşta Algılama", "PANEL_LABEL_TURN_OFF": "Güç kapalı", "SETTINGS_TIME_IDLE_DESC": "Belirli bir süre boyunca hiçbir giriş algılanmadığında, tüm ekranların parlaklığı azalacaktır.", "GENERIC_PAUSE_TOD": "Duraklama Süresi Ayarlamaları", "GENERIC_PAUSE_IDLE": "Rölanti Algılamayı Duraklat", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Aktif Edilmiş Monitör Algılama Yöntemleri", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Üzerıne Bindirmeyi Devre Dışı Bırak", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Twinkle Tray'in kısayol tuşu tam ekran uygulamalara müdahale ediyorsa, buradan devre dışı bırakabilirsiniz.", "SETTINGS_TIME_TRANSITON_TITLE": "Parlaklık geçiş hızı", "SETTINGS_TIME_TRANSITON_DESC": "Günün saati ayarlamaları etkinleştirildiğinde parlaklığın ne kadar hızlı geçiş yapması gerektiği.", "SETTINGS_TIME_ANIMATE_TITLE": "Zamanlar arasında canlandırma", "SETTINGS_TIME_ANIMATE_DESC": "Parlaklık değerleri mevcut ve bir sonraki zamanlanmış olay arasında canlandırılacaktır. CPU kullanımını artırabilir. Bu aktifken manuel parlaklık ayarlamaları hızlı bir şekilde üzerine yazılacaktır.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Ekranları Gizle", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Belirli ekranları açılır menüden gizlemek isterseniz, bunları buradan kapatabilirsiniz.", "GENERIC_SPEED_INSTANT": "Anında", "GENERIC_SPEED_SLOW": "Yavaş", "GENERIC_SPEED_VERY_SLOW": "Çok Yavaş", "GENERIC_SPEED_NORMAL": "Normal", "GENERIC_DDC_WARNING": "Güç durumunu kontrol etme gibi DDC/CI özellikleri monitörünüzün yanıt vermemesine neden olabilir. Kullanım riski size aittir.", "GENERIC_SPEED_FAST": "Hızlı", "GENERIC_SPEED_VERY_FAST": "Çok hızlı", "SETTINGS_GENERAL_TROUBLESHOOTING": "Sorun Giderme", "SETTINGS_UPDATES_CHANNEL": "Güncelleme kanalı", "SETTINGS_UPDATES_BRANCH_STABLE": "Kararlı (varsayılan)", "SETTINGS_UPDATES_BRANCH_BETA": "Beta", "GENERIC_DELETE": "Sil", "GENERIC_DEFAULT": "Varsayılan", "GENERIC_OPTIONAL": "Opsiyonel", "PANEL_LABEL_TURN_ON": "Aç", "SETTINGS_GENERAL_OVERLAY_TITLE": "Varsayılan Kaplama Davranışı", "SETTINGS_GENERAL_OVERLAY_DESC": "Parlaklık kısayol tuşu çıktısının diğer uygulamalar üzerinde ne kadar güçlü bir şekilde görüntülenmeye çalışacağı. Bunu ayarlamanıza gerek yoktur.", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "En Uygun", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Kaplama çoğu pencerenin üzerinde görüntülenecek, ancak “her zaman üstte” olarak işaretlenmiş uygulamaların üzerinde kendini zorlamayacaktır.", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Zorla Yap", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Kaplamayı her zaman diğer pencerelerin üstünde göstermeye çalışın. Bu, özel tam ekran oyunlarda ve diğer tam ekran uygulamalarda sorunlara neden olabilir. Ayrıca bazı oyunlarda anti-hile tetikleyebilir.", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Eski DDC/CI algılama yöntemi", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "DDC/CI ekranlarını tespit etmek için eski v1.15.5 yöntemini kullanın.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Otomatik parlaklık uygulama", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Monitörünüz kapattıktan ve/veya donanım bağlantısını kestikten/bağladıktan sonra garip bir şekilde tepki veriyorsa, bunu devre dışı bırakmak yardımcı olabilir.", "SETTINGS_GENERAL_REPORT_TITLE": "Rapor Oluştur", "SETTINGS_GENERAL_REPORT_DESC": "Hata ayıklama için monitörleriniz ve ayarlarınız hakkında bilgi içeren bir metin dosyası kaydedin.", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Belirli monitörlerde otomatik uygulamayı atla", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Belirli monitörler için tüm donanım/güç olaylarından sonra bilinen parlaklığın otomatik olarak uygulanmasını devre dışı bırakın. Buna boşta algılama özelliği de dahildir.", "SETTINGS_PROFILES_ADD": "Yeni Profil", "SETTINGS_PROFILES_NAME": "Profil Adı", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Aktifken parlaklığı ayarla", "SETTINGS_PROFILES_SHOW_MENU": "Sağ tuş tepsi menüsünde göster", "SETTINGS_PROFILES_TRIGGER_TITLE": "Uygulama tetiklenme ayarları", "SETTINGS_PROFILES_APP_PATH": "Uygulama yolu", "SETTINGS_PROFILES_APP_DESC": "Belirli bir uygulamaya odaklanıldığında bu profilin otomatik olarak etkinleştirilmesini istiyorsanız, EXE'nin tam veya kısmi yolunu aşağıya girin.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Baskılama türünü geçersiz kıl", "SETTINGS_PROFILES_OVERLAY_DESC": "Belirtilen uygulama odaklandığında kısayol tuşu baskılama davranışını değiştirir. Profil manuel olarak etkinleştirildiğinde bu özellik çalışmaz.", "SETTINGS_FEATURES_POWER_COMPAT": "En Uygun", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Parlaklık" } ================================================ FILE: src/localization/uk.json ================================================ { "LANGUAGE": "Українська", "GENERIC_OK": "Гаразд", "GENERIC_CANCEL": "Скасувати", "GENERIC_SAVE": "Зберегти", "GENERIC_CLEAR": "Очистити", "GENERIC_OFF": "Вимкнуто", "GENERIC_ON": "Увімкнуто", "GENERIC_QUIT": "Вийти", "GENERIC_CLOSE": "Закрити", "GENERIC_SETTINGS": "Налаштування", "GENERIC_INSTALL": "Встановити", "GENERIC_DISMISS": "Відхилити", "GENERIC_DISPLAY_SINGLE": "Дисплей", "GENERIC_ALL_DISPLAYS": "Всі дисплеї", "GENERIC_REFRESH_DISPLAYS": "Оновити дисплеї", "GENERIC_MINIMUM": "Мін", "GENERIC_MAXIMUM": "Макс", "GENERIC_NO_DISPLAYS": "Дисплеї не виявлено. Будь ласка, під'єднайте дисплей до комп'ютера.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Сумісних дисплеїв не знайдено. Будь ласка, перевірте чи увімкнений \"DDC/CI\" на ваших дисплеях.", "GENERIC_NO_DISPLAYS_SHORT": "Сумісних дисплеїв не виявлено.", "GENERIC_SECONDS": "секунд", "GENERIC_MINUTES": "хвилин", "PANEL_TITLE": "Регулювання яскравості", "PANEL_UPDATE_AVAILABLE": "Доступна нова версія", "PANEL_BUTTON_LINK_LEVELS": "Об'єднати рівні", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Вимкнути дисплеї", "PANEL_LABEL_BRIGHTNESS": "Яскравість", "PANEL_LABEL_CONTRAST": "Контрастність", "PANEL_LABEL_OFF_ON": "Стан живлення", "PANEL_LABEL_COLOR_TEMPERATURE": "Колірна температура", "PANEL_LABEL_VOLUME": "Гучність", "PANEL_LABEL_TURN_OFF": "Вимкнути", "INTRO_TITLE": "Привіт, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Схоже, що значок Twinkle Tray в панелі завдань прихований, тому ви повинні перемістити його в легкодоступне місце. Інструкцію дивіться нижче.", "SETTINGS_TITLE": "Налаштування Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Загальні", "SETTINGS_SIDEBAR_MONITORS": "Налаштування монітора", "SETTINGS_SIDEBAR_FEATURES": "Функції DDC/CI", "SETTINGS_SIDEBAR_TIME": "Регулювання за часом", "SETTINGS_SIDEBAR_HOTKEYS": "Гарячі клавіші та комбінації", "SETTINGS_SIDEBAR_UPDATES": "Оновлення", "SETTINGS_GENERAL_TITLE": "Загальні", "SETTINGS_GENERAL_STARTUP": "Запускати при увімкненні Windows", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Застосовувати яскравість при запуску", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Відновити останній відомий рівень яскравості для кожного дисплея при запуску Twinkle Tray.", "SETTINGS_GENERAL_THEME_TITLE": "Тема", "SETTINGS_GENERAL_THEME_SYSTEM": "Системні налаштування (типово)", "SETTINGS_GENERAL_THEME_DARK": "Темна", "SETTINGS_GENERAL_THEME_LIGHT": "Світла", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Мова", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Мова системи (типово)", "SETTINGS_GENERAL_RESET_TITLE": "Скинути налаштування", "SETTINGS_GENERAL_RESET_DESC": "Натисніть цю кнопку, щоб очистити конфігурацію.", "SETTINGS_GENERAL_RESET_BUTTON": "Скинути налаштування", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Акрилове розмиття", "SETTINGS_GENERAL_ACRYLIC_DESC": "Увімкнути або вимкнути розмиття за прозорим фоном в Twinkle Tray.", "SETTINGS_GENERAL_MICA_TITLE": "Розмиття Mica", "SETTINGS_GENERAL_MICA_DESC": "Увімкнути або вимкнути розмиття фону в Twinkle Tray.", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Аналітика", "SETTINGS_GENERAL_ANALYTICS_DESC": "Збір і відправка даних про використання, щоб покращити Twinkle Tray. Особисті дані не відправляються. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Більше інформації", "SETTINGS_GENERAL_SCROLL_TITLE": "Коліщатко на значку в панелі завдань", "SETTINGS_GENERAL_SCROLL_DESC": "Регулювання яскравості всіх дисплеїв одночасно, прокручуючи коліщатко на значку в панелі завдань. Це не працює з деякими трекпадами.", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Значок у треї", "SETTINGS_GENERAL_TROUBLESHOOTING": "Усунення несправностей", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Увімкнені методи виявлення монітора", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Якщо Twinkle Tray не реагує на натискання значка в треї або не виявляє ваші дисплеї, ви можете спробувати вимкнути певні методи виявлення монітора. Перезапустіть Twinkle Tray, щоб зміни набули чинності. {{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Вимкнути накладання", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Якщо накладання гарячих клавіш лотка Twinkle Tray заважає повноекранним застосункам, ви можете вимкнути його тут.", "SETTINGS_MONITORS_RATE_TITLE": "Частота оновлення яскравості", "SETTINGS_MONITORS_RATE_DESC": "Як часто яскравість оновлюватиметься на ваших дисплеях, коли ви регулюєте їхні значення. Збільште час, якщо ваші дисплеї мерехтять.", "SETTINGS_MONITORS_RATE_0": "Миттєво", "SETTINGS_MONITORS_RATE_1": "Швидко (250 мс)", "SETTINGS_MONITORS_RATE_2": "Нормально (500 мс)", "SETTINGS_MONITORS_RATE_3": "Повільно (1 секунда)", "SETTINGS_MONITORS_RATE_4": "Дуже повільно (2 секунди)", "SETTINGS_MONITORS_RENAME_TITLE": "Перейменування моніторів", "SETTINGS_MONITORS_RENAME_DESC": "Якщо ви хочете змінити назву для кожного монітора (наприклад, «Лівий монітор», «Середній монітор»), ви можете ввести її нижче. Якщо залишити поле порожнім, відновиться оригінальна назва.", "SETTINGS_MONITORS_ENTER_NAME": "Введіть ім'я", "SETTINGS_MONITORS_REORDER_TITLE": "Упорядкування моніторів", "SETTINGS_MONITORS_REORDER_DESC": "Змінити порядок показу моніторів у треї. Натисніть і перетягніть, щоб внести зміни.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Нормалізувати яскравість", "SETTINGS_MONITORS_NORMALIZE_DESC": "Монітори часто мають різні діапазони яскравості. Завдяки обмеженню мінімальної/максимальної яскравості для кожного дисплея рівні яскравості між дисплеями є набагато узгодженішими.", "SETTINGS_MONITORS_DETAILS_NAME": "Ім'я", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Внутрішнє ім'я", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Метод з'вязку", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Поточна яскравість", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Максимальна яскравість", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Нормалізація яскравості", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Приховати неактивний внутрішній дисплей", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Сховати повзунок яскравості на панелі, коли кришка закрита або вбудований дисплей вимкнено в Windows.", "SETTINGS_FEATURES_DESCRIPTION": "Увімкнути або вимкнути специфічні можливості DDC/CI на панелі яскравості. Хоча б одна можливість повинна бути увімкнена для вашого монітора, щоб показуватися в панелі яскравості. Не всі дисплеї (наприклад, ноутбуки/планшети) підтримують ці можливості.", "SETTINGS_FEATURES_UNSUPPORTED": "Цей монітор не підтримує функції DDC/CI.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Перевірити поточні значення", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Завжди отримувати найновіші значення з монітора, відкриваючи панель яскравості. Увімкніть цей параметр, якщо яскравість (або інші VCP-коди, наприклад, контрастність) часто змінюються за межами панелі Twinkle Tray.", "SETTINGS_TIME_TITLE": "Регулювання за часом доби", "SETTINGS_TIME_DESC": "Автоматично встановлювати монітори на певний рівень яскравості в потрібний час. Усі монітори будуть налаштовані на однакові нормалізовані рівні.", "SETTINGS_TIME_ADD": "Додати час", "SETTINGS_TIME_REMOVE": "Видалити час", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Встановити яскравість для окремих дисплеїв", "SETTINGS_TIME_INDIVIDUAL_DESC": "Налаштувати яскравість для кожного дисплея окремо, а не для всіх одночасно.", "SETTINGS_TIME_STARTUP_TITLE": "Перевіряти під час запуску застосунку", "SETTINGS_TIME_STARTUP_DESC": "Регулювання яскравості відповідно до актуального часу на моменту запуску Twinkle Tray.", "SETTINGS_TIME_IDLE_TITLE": "Виявлення простою", "SETTINGS_TIME_IDLE_DESC": "Якщо введення не було виявлено протягом певного періоду часу, яскравість усіх дисплеїв буде зменшено.", "SETTINGS_HOTKEYS_TITLE": "Гарячі клавіші", "SETTINGS_HOTKEYS_DESC": "Налаштування гарячих клавіш для регулювання яскравості одного або всіх дисплеїв.", "SETTINGS_HOTKEYS_ADD": "Додати гарячу клавішу", "SETTINGS_HOTKEYS_REMOVE": "Видалити гарячу клавішу", "SETTINGS_HOTKEYS_INCREASE": "Збільшити яскравість", "SETTINGS_HOTKEYS_DECREASE": "Зменшити яскравість", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Натисніть клавіші тут", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Регулювання рівня яскравості", "SETTINGS_HOTKEYS_LEVEL_DESC": "Наскільки потрібно регулювати яскравість під час використання гарячих клавіш.", "SETTINGS_HOTKEYS_TOD_TITLE": "Дія кнопки «Вимкнути дисплеї»", "SETTINGS_HOTKEYS_TOD_DESC": "Налаштувати сигнал, який надсилається під час використання гарячої клавіші або значка «Вимкнути дисплеї». Програмний сигнал показуватиме чорний екран, доки Windows не розпізнає введення (наприклад, мишу чи клавіатуру). Апаратний сигнал вимкне живлення моніторів.", "SETTINGS_HOTKEYS_TOD_NONE": "Нічого (сховати значок)", "SETTINGS_HOTKEYS_TOD_SOFT": "Програмний сигнал (типово)", "SETTINGS_HOTKEYS_TOD_HARD": "Апаратний* сигнал (лише DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "Апаратний* та програмний сигнал", "SETTINGS_HOTKEYS_TOD_NOTE": "*Примітка. Не всі монітори DDC/CI підтримують цю функцію.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Гарячі клавіші вимикають об'єднання рівнів", "SETTINGS_HOTKEYS_BREAK_DESC": "Якщо використовується гаряча клавіша для одного дисплея та активне об'єднання рівнів, ця функція буде деактивована.", "SETTINGS_UPDATES_TITLE": "Оновлення", "SETTINGS_UPDATES_VERSION": "Версія Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Автоматично перевіряти наявність нових версій", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Коли буде нова версія, інформація буде показана на панелі яскравості.", "SETTINGS_UPDATES_MS_STORE": "Щоб перевірити наявність нових версій, відвідайте Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Доступна нова версія Twinkle Tray!", "SETTINGS_UPDATES_NONE_AVAILABLE": "В актуальному стані. Поточна версія містить такі зміни:", "SETTINGS_UPDATES_DOWNLOADING": "Завантаження оновлення…", "SETTINGS_UPDATES_DOWNLOAD": "Завантажити та встановити {{1}}", "GENERIC_PAUSE_TOD": "Налаштування часу паузи", "GENERIC_PAUSE_IDLE": "Виявлення простою під час паузи", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Приховати дисплеї", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Якщо ви бажаєте приховати певні дисплеї у спливному вікні, ви можете вимкнути їх тут.", "SETTINGS_TIME_ANIMATE_TITLE": "Анімація в проміжках часу", "SETTINGS_TIME_ANIMATE_DESC": "Значення яскравості будуть анімовані між поточною та наступною запланованою подією. Може збільшити використання процесора. Ручні налаштування яскравості будуть швидко перезаписані, поки ця функція активна.", "SETTINGS_TIME_TRANSITON_DESC": "Як швидко повинна змінюватися яскравість при активації регулювання в залежності від часу доби.", "GENERIC_DDC_WARNING": "Функції DDC/CI можуть призвести до того, що монітор перестане реагувати. Використовуйте на свій ризик.", "GENERIC_SPEED_INSTANT": "Миттєво", "GENERIC_SPEED_SLOW": "Повільно", "GENERIC_SPEED_VERY_SLOW": "Дуже повільно", "GENERIC_SPEED_NORMAL": "Нормально", "GENERIC_SPEED_FAST": "Швидко", "GENERIC_SPEED_VERY_FAST": "Дуже швидко", "SETTINGS_TIME_TRANSITON_TITLE": "Швидкість переходу яскравості", "SETTINGS_UPDATES_CHANNEL": "Оновлення каналу", "SETTINGS_UPDATES_BRANCH_STABLE": "Стабільний (типово)", "SETTINGS_UPDATES_BRANCH_BETA": "Бета", "SETTINGS_FEATURES_POWER_OFF": "Вимкнути", "GENERIC_DELETE": "Видалити", "GENERIC_DEFAULT": "Типово", "GENERIC_OPTIONAL": "Додатково", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "Найбільш сумісні", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "Примусово", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "Застарілий метод виявлення DDC/CI", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Використовувати старий метод виявлення DDC/CI дисплеїв v1.15.5.", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Автозастосування яскравості", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "Вимкнути автозастосування до певних моніторів", "SETTINGS_FEATURES_ADD_VCP": "VCP-код", "SETTINGS_FEATURES_POWER_TITLE": "Сигнал про стан живлення", "SETTINGS_FEATURES_POWER_DESC": "Під час надсилання команди DDC/CI для вимкнення дисплея буде надіслано такі значення.", "SETTINGS_FEATURES_POWER_COMPAT": "Найбільш сумісні", "SETTINGS_FEATURES_POWER_STANDBY": "Режим очікування", "SETTINGS_FEATURES_ADD": "Додати функцію", "SETTINGS_FEATURES_ADD_EXISTS": "Ця функція вже активна.", "SETTINGS_HOTKEY_VALUE": "Значення", "SETTINGS_GENERAL_REPORT_TITLE": "Створити звіт", "SETTINGS_GENERAL_REPORT_DESC": "Зберегти текстовий файл з інформацією про ваші монітори та налаштування для налагодження.", "SETTINGS_FEATURES_POWER_WARNING": "Параметр «Режим очікування», швидше за все, дозволяє вмикати/вимикати монітор з Twinkle Tray. Однак багато моніторів неправильно реагують на зміну стану живлення. Використовуйте на свій страх і ризик.", "SETTINGS_FEATURES_ADD_DESC": "Введіть VCP-код для функції, яку ви хочете додати до дисплея. Зверніть увагу, що Twinkle Tray не перевіряє, чи дійсно ваш дисплей підтримує цей VCP-код. Використовуйте на власний ризик.", "SETTINGS_TIME_SUN_TITLE": "Координати положення сонця", "SETTINGS_TIME_SUN_DESC": "Щоб використовувати «положення сонця» для коригування часу, введіть поточну широту і довготу, щоб можна було визначити правильний час.", "SETTINGS_TIME_LAT": "Широта", "SETTINGS_TIME_LONG": "Довгота", "SETTINGS_TIME_SUN_GET": "Отримати координати", "SETTINGS_TIME_IDLE_FS_TITLE": "Повноекранні застосунки блокують виявлення простою", "SETTINGS_TIME_IDLE_FS_DESC": "Повноекранні застосунки блокують виявлення простою. Це стосується лише сфокусованого вікна.", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "Кількість для прокрутки", "SETTINGS_HOTKEY_TARGET": "Ціль дії", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Введіть число", "SETTINGS_HOTKEY_VALUES": "Значення", "SETTINGS_HOTKEY_ADD_VALUE": "Додати значення", "SETTINGS_HOTKEY_ACTION": "Дія", "SETTINGS_HOTKEY_ACTION_OFFSET": "Налаштувати значення", "SETTINGS_PROFILES_ADD": "Новий профіль", "SETTINGS_PROFILES_APP_DESC": "Якщо ви хочете, щоб цей профіль активувався автоматично при фокусуванні певного застосунку, введіть повний або частковий шлях до EXE-файлу нижче.", "SETTINGS_PROFILES_OVERLAY_TITLE": "Перевизначити тип накладання", "SETTINGS_PROFILES_OVERLAY_DESC": "Змінює поведінку накладання гарячих клавіш, коли вказаний застосунок сфокусований. Ця функція не працює, якщо профіль активовано вручну.", "SETTINGS_GENERAL_OVERLAY_TITLE": "Типова поведінка накладання", "PANEL_LABEL_TURN_ON": "Увімкнути", "SETTINGS_GENERAL_OVERLAY_DESC": "Наскільки сильно буде намагатися показуватися накладання яскравості гарячих клавіш поверх інших застосунків. Вам не потрібно налаштовувати цей параметр.", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "Накладення показуватиметься над більшістю вікон, але не буде примусово встановлюватися над програмами, позначеними як «завжди зверху».", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "Завжди намагатися показувати накладання поверх інших вікон. Це може спричинити проблеми з ексклюзивними повноекранними іграми та іншими повноекранними застосунками. Це також може спричинити спрацьовування античиту у деяких іграх.", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "Якщо ваш монітор дивно реагує після вимкнення/ввімкнення та/або від'єднання/під'єднання обладнання, вимкнення цієї функції може допомогти.", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "Вимкнути автозастосування відомої яскравості після всіх подій апаратного забезпечення/живлення для певних моніторів. Це стосується і функції виявлення простою.", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP-код (Напр. 0x12)", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Всі VCP-коди, про які повідомляє цей дисплей", "SETTINGS_FEATURES_VCP_LIST_DESC": "Нижче наведено список доступних кодів VCP, про які цей дисплей повідомляє Windows. Twinkle Tray не підтверджує функціональність або стабільність цих кодів. Використовуйте їх на власний ризик.", "SETTINGS_FEATURES_VCP_EXPECTED": "Очікувані значення", "SETTINGS_HOTKEY_OFF_WARN": "Ця дія використовуватиме параметр, вибраний у розділі «Вимкнути дисплеї». Якщо ви хочете вимкнути певні дисплеї, скористайтеся дією «Встановити» або «Цикл» гарячих клавіш.", "SETTINGS_HOTKEY_ACTION_SET": "Встановити значення", "SETTINGS_PROFILES_NAME": "Назва профілю", "SETTINGS_PROFILES_APP_PATH": "Шлях до застосунку", "SETTINGS_HOTKEY_ACTION_CYCLE": "Циклічний список значень", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "Встановити яскравість, коли активовано", "SETTINGS_PROFILES_TITLE": "Профілі", "SETTINGS_PROFILES_DESC": "Автоматично налаштовуйте яскравість або поведінку накладання ярликів залежно від застосунку, на якому сфокусовано увагу. Ви також можете додавати профілі до контекстного меню в системному треї, щоб швидко змінювати яскравість відповідно до попередньо визначених профілів.", "SETTINGS_PROFILES_SHOW_MENU": "Показати в контекстному меню правою кнопкою миші", "SETTINGS_PROFILES_TRIGGER_TITLE": "Налаштування тригера застосунку", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "Медіа блокує виявлення простою", "SETTINGS_TIME_IDLE_MEDIA_DESC": "Виявлення простою буде вимкнено під час відтворення будь-якого медіафайлу. Це стосується як відео, так і аудіо. Це стосується лише тих випадків, коли Windows повідомляє, що відтворюється мультимедійний файл.", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "Зворотнє прокручування", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "При прокручуванні на значку в системному лотку напрямок прокрутки стане протилежний.", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "Вимкнути на екрані блокування", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "Не отримувати доступ до моніторів, коли сеанс користувача заблоковано, щоб уникнути конфліктів у багатоосібних середовищах.", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "Налаштування дисплея HDR", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "Увімкнути повзунки яскравості SDR для певних моніторів. Для цього на моніторах має бути ввімкнено HDR у Windows.", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR замінює основний повзунок", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "Керувати яскравістю SDR за допомогою головного повзунка яскравості, коли HDR активний.", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Яскравість SDR", "GENERIC_NOT_SUPPORTED": "Не підтримується", "GENERIC_SUPPORTED": "Підтримується", "GENERIC_UNSUPPORTED": "Без підтримки", "GENERIC_ACTIVE": "Активно", "GENERIC_DETECTING_DISPLAYS": "Виявлення екранів…", "PANEL_LABEL_INPUTS": "Входи", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Стиль інтерфейсу Windows", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "Виявлення оновлень теми", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "Визначає зміни акценту / шпалер / тем у Windows для оновлення значка в лотку та ефекту Mica. Вимкнення цього може допомогти, якщо сторонній застосунок часто змінює тему, що підвищує використання процесора.", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "Визначення стану живлення монітора", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "Визначає зміни стану живлення моніторів. Вимкнення цієї функції може допомогти, якщо ви стикаєтеся з помилками при вимиканні / вмиканні моніторів або в режимі очікування. Для набуття чинності потрібне перезавантаження.", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_TIME_USE_SUN_POSITION": "Використовувати положення сонця", "SETTINGS_HOTKEY_ADD_ACTION": "Додати дію", "GENERIC_CALIBRATION_POINT": "Точка калібрування", "GENERIC_SLIDER_INDICATOR_TYPE": "Тип індикатора повзунка", "GENERIC_ICON": "Значок", "GENERIC_TEXT": "Текст", "GENERIC_SLIDER_ICON": "Значок повзунка", "GENERIC_SLIDER_TEXT": "Текст повзунка", "GENERIC_SLIDER_NAME": "Уведіть назву повзунка", "SETTINGS_MONITORS_CALIBRATION_DESC": "Для кожного монітора можна додати окремі точки калібрування, щоб компенсувати різницю в кривих яскравості. Вхідне значення — це рівень яскравості, вказаний на повзунку, тоді як вихідне значення — це фактичний рівень яскравості, застосований до монітора.", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "Прив’язано до яскравості", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "Зупинитися після цього рівня яскравості", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "Якщо ваш монітор використовує нестандартний код VCP для яскравості (наприклад, 0x13 або 0x6B), або якщо хочете перепризначити повзунок яскравості на інший код VCP, ви можете ввести цей код нижче.", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "Залиште порожнім для типового значення (0x10). Знайдіть підтримувані коди у списку нижче." } ================================================ FILE: src/localization/vi.json ================================================ { "LANGUAGE": "Tiếng Việt", "GENERIC_OK": "Đồng ý", "GENERIC_CANCEL": "Huỷ", "GENERIC_SAVE": "Lưu", "GENERIC_CLEAR": "Xoá", "GENERIC_OFF": "Tắt", "GENERIC_ON": "Bật", "GENERIC_QUIT": "Thoát", "GENERIC_CLOSE": "Đóng", "GENERIC_SETTINGS": "Thiết lập", "GENERIC_INSTALL": "Cài đặt", "GENERIC_DISMISS": "Bỏ qua", "GENERIC_DISPLAY_SINGLE": "Màn hình", "GENERIC_ALL_DISPLAYS": "Tất cả màn hình", "GENERIC_MINIMUM": "Tối thiểu", "GENERIC_MAXIMUM": "Tối đa", "GENERIC_NO_DISPLAYS": "Không phát hiện thấy màn hình. Vui lòng kết nối màn hình tới PC của bạn.", "GENERIC_NO_COMPATIBLE_DISPLAYS": "Không phát hiện thấy màn hình. Vui lòng kiểm tra \"DDC/CI\" màn hình của bạn đã được kích hoạt chưa.", "GENERIC_NO_DISPLAYS_SHORT": "Không phát hiện thấy màn hình tương thích.", "PANEL_TITLE": "Điều chỉnh độ sáng", "PANEL_UPDATE_AVAILABLE": "Đã có phiên bản mới", "PANEL_BUTTON_LINK_LEVELS": "Liên kết", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "Tắt màn hình", "INTRO_TITLE": "Xin chào, Twinkle Tray!", "INTRO_INSTRUCTIONS": "Biểu tượng Twinkle Tray đã bị ẩn, vì vậy bạn nên di chuyển nó đến nơi có thể dễ dàng truy cập. Xem bên dưới để được hướng dẫn.", "SETTINGS_TITLE": "Thiết lập Twinkle Tray", "SETTINGS_SIDEBAR_GENERAL": "Cài đặt chung", "SETTINGS_SIDEBAR_MONITORS": "Thiết lập màn hình", "SETTINGS_SIDEBAR_TIME": "Điều chỉnh thời gian", "SETTINGS_SIDEBAR_HOTKEYS": "Phím tắt & Lối tắt", "SETTINGS_SIDEBAR_UPDATES": "Cập nhật", "SETTINGS_GENERAL_TITLE": "Cài đặt chung", "SETTINGS_GENERAL_STARTUP": "Khởi động cùng hệ thống", "SETTINGS_GENERAL_THEME_TITLE": "Giao diện", "SETTINGS_GENERAL_THEME_SYSTEM": "Giao diện hệ thống (mặc định)", "SETTINGS_GENERAL_THEME_DARK": "Tối", "SETTINGS_GENERAL_THEME_LIGHT": "Sáng", "SETTINGS_GENERAL_LANGUAGE_TITLE": "Ngôn ngữ", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "Ngôn ngữ hệ thống (mặc định)", "SETTINGS_GENERAL_RESET_TITLE": "Khôi phục cài đặt gốc", "SETTINGS_GENERAL_RESET_DESC": "Lựa chọn nếu bạn muốn khôi phục về cài đặt gốc.", "SETTINGS_GENERAL_RESET_BUTTON": "Cài đặt lại", "SETTINGS_GENERAL_ANALYTICS_TITLE": "Phân tích", "SETTINGS_GENERAL_ANALYTICS_DESC": "Gửi dữ liệu sử dụng để giúp cải thiện Twinkle Tray. Không có dữ liệu cá nhân nào được gửi đi. {{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "Tìm hiểu thêm", "SETTINGS_MONITORS_RATE_TITLE": "Tốc độ thay đổi độ sáng", "SETTINGS_MONITORS_RATE_DESC": "Sau bao lâu thì độ sáng sẽ được thay đổi trên màn hình của bạn khi điều chỉnh độ sáng. Tăng thời gian nếu màn hình của bạn đang nhấp nháy.", "SETTINGS_MONITORS_RATE_0": "Nhanh nhất", "SETTINGS_MONITORS_RATE_1": "Nhanh (250 ms)", "SETTINGS_MONITORS_RATE_2": "Bình thường (500 ms)", "SETTINGS_MONITORS_RATE_3": "Chậm (1 giây)", "SETTINGS_MONITORS_RATE_4": "Rất chậm (2 giây)", "SETTINGS_MONITORS_RENAME_TITLE": "Đổi tên màn hình", "SETTINGS_MONITORS_RENAME_DESC": "Nếu bạn muốn một tên khác nhau cho mỗi màn hình (ví dụ: \"Màn hình trái\", \"Màn hình giữa\"), bạn có thể nhập nó dưới đây. Nếu để trống, tên sẽ được đặt mặc định.", "SETTINGS_MONITORS_ENTER_NAME": "Nhập tên", "SETTINGS_MONITORS_REORDER_TITLE": "Sắp xếp màn hình", "SETTINGS_MONITORS_REORDER_DESC": "Thay đổi thứ tự mà màn hình được hiển thị. Nhấn và kéo để thay đổi.", "SETTINGS_MONITORS_NORMALIZE_TITLE": "Giới hạn độ sáng", "SETTINGS_MONITORS_NORMALIZE_DESC": "Mỗi màn hình sẽ có phạm vi độ sáng khác nhau. Bằng cách giới hạn độ sáng tối thiểu / tối đa cho mỗi màn hình giúp cho độ sáng giữa các màn hình phù hợp với nhau. Màn hình tương tự sẽ sử dụng các thiết lập tương tự.", "SETTINGS_TIME_TITLE": "Thiết lập thời gian trong ngày", "SETTINGS_TIME_DESC": "Tự động thiết lập màn hình của bạn với độ sáng cụ thể tại thời điểm mong muốn.", "SETTINGS_TIME_ADD": "Thêm thời điểm", "SETTINGS_TIME_REMOVE": "Xoá thời điểm", "SETTINGS_TIME_INDIVIDUAL_TITLE": "Đặt độ sáng cho từng màn hình", "SETTINGS_TIME_INDIVIDUAL_DESC": "Cấu hình độ sáng cho từng màn hình thay vì tất cả màn hình.", "SETTINGS_TIME_STARTUP_TITLE": "Kiểm tra khi khởi động ứng dụng", "SETTINGS_TIME_STARTUP_DESC": "Điều chỉnh độ sáng để phù hợp với thời gian gần nhất khi Twinkle Tray chạy.", "SETTINGS_HOTKEYS_TITLE": "Phím tắt", "SETTINGS_HOTKEYS_DESC": "Cấu hình phím tắt để thiết lập độ sáng cho một hoặc nhiều màn hình.", "SETTINGS_HOTKEYS_ADD": "Thêm phím tắt", "SETTINGS_HOTKEYS_REMOVE": "Gỡ phím tắt", "SETTINGS_HOTKEYS_INCREASE": "Tăng độ sáng", "SETTINGS_HOTKEYS_DECREASE": "Giảm độ sáng", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "Nhấn phím tại đây", "SETTINGS_HOTKEYS_LEVEL_TITLE": "Mức độ điều chỉnh độ sáng", "SETTINGS_HOTKEYS_LEVEL_DESC": "Mức % độ sáng sẽ được điều chỉnh khi sử dụng phím tắt.", "SETTINGS_UPDATES_TITLE": "Cập nhật", "SETTINGS_UPDATES_VERSION": "Bạn có Twinkle Tray {{1}}.", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "Tự động kiểm tra phiên bản mới", "SETTINGS_UPDATES_AUTOMATIC_DESC": "Khi có một phiên bản mới, nó sẽ được hiển thị trong bảng điều khiển độ sáng.", "SETTINGS_UPDATES_MS_STORE": "Để kiểm tra các phiên bản mới, hãy truy cập vào Microsoft Store.", "SETTINGS_UPDATES_AVAILABLE": "Hiện có phiên bản mới của Twinkle Tray!", "SETTINGS_UPDATES_NONE_AVAILABLE": "Đã được cập nhật. Phiên bản hiện tại bao gồm các thay đổi sau:", "SETTINGS_UPDATES_DOWNLOADING": "Đang tải bản cập nhật…", "SETTINGS_UPDATES_DOWNLOAD": "Tải & cài đặt {{1}}", "PANEL_LABEL_COLOR_TEMPERATURE": "Nhiệt độ màu", "PANEL_LABEL_CONTRAST": "Độ tương phản", "PANEL_LABEL_BRIGHTNESS": "Độ sáng", "SETTINGS_MONITORS_FEATURES_DESCRIPTION": "Bật hoặc tắt các tính năng DDC / CI trong cài đặt độ sáng. Ít nhất một tính năng phải được bật để màn hình của bạn hiển thị trong menu điều chỉnh độ sáng. Không phải tất cả các màn hình đều hỗ trợ các tính năng này, chẳng hạn như màn hình máy tính xách tay / máy tính bảng.", "SETTINGS_MONITORS_FEATURES_TITLE": "Tính năng DDC/CI", "PANEL_LABEL_OFF_ON": "Trạng thái nguồn", "SETTINGS_SIDEBAR_FEATURES": "Tính năng DDC/CI", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "Tên nội bộ", "SETTINGS_HOTKEYS_TOD_NONE": "Không (ẩn icon)", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "Áp dụng độ sáng khi khởi động", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Khôi phục độ sáng trước đó cho mỗi màn hình khi khởi động Twinkle Tray.", "GENERIC_REFRESH_DISPLAYS": "Làm mới màn hình", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "Độ sáng hiện tại", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "Khi gập laptop hoặc màn hình bên trong đã bị tắt trong Windows, ẩn thanh trượt độ sáng trong bảng điều khiển.", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "Kiểm tra giá trị hiện tại", "PANEL_LABEL_TURN_OFF": "Tắt nguồn màn hình", "GENERIC_MINUTES": "phút", "GENERIC_SECONDS": "Giây", "SETTINGS_GENERAL_ACRYLIC_TITLE": "Hiệu ứng mờ", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "Biểu tượng", "SETTINGS_MONITORS_DETAILS_NAME": "Tên", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "Độ sáng tối đa", "SETTINGS_TIME_IDLE_DESC": "Khi không có đầu vào nào được phát hiện trong một khoảng thời gian, độ sáng của tất cả các màn hình sẽ bị giảm.", "SETTINGS_TIME_IDLE_TITLE": "Phát hiện không hoạt động", "SETTINGS_FEATURES_UNSUPPORTED": "Màn hình này không hỗ trợ các tính năng DDC/CI.", "PANEL_LABEL_VOLUME": "Âm lượng", "SETTINGS_GENERAL_MICA_DESC": "Bật hoặc tắt tính năng làm mờ nền trong Twinkle Tray.", "SETTINGS_GENERAL_SCROLL_DESC": "Điều chỉnh độ sáng của tất cả các màn hình cùng một lúc bằng cách cuộn qua biểu tượng khay hệ thống. Điều này không hoạt động với một số bàn di chuột.", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "Nếu Twinkle Tray không có phản ứng gì cả khi nhấp vào khay biểu tượng hoặc không thể phát hiện được màn hình hiển thị của bạn, bạn có thể thử tạm dừng một số phương pháp phát hiện màn hình. Khởi chạy Twinkle Tray để các thay đổi có hiệu lực. {{1}}", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "Ẩn hiển thị nội bộ không hoạt động", "SETTINGS_FEATURES_DESCRIPTION": "Bật hoặc tắt các tính năng cụ thể DDC/CI trong cài đặt độ sáng màn. Ít nhất một tính năng phải được bật để màn hình của bạn hiển thị trong menu điều chỉnh độ sáng màn. Không phải tất cả các màn hình đều hỗ trợ các tính năng này, chẳng hạn như màn hình máy tính xách tay/máy tính bảng.", "SETTINGS_GENERAL_ACRYLIC_DESC": "Bật hoặc tắt tính năng làm mờ phía sau nền trong suốt trong Twinkle Tray.", "SETTINGS_GENERAL_SCROLL_TITLE": "Phím tắt cuộn biểu tượng khay", "SETTINGS_GENERAL_MICA_TITLE": "Mica Blur", "SETTINGS_HOTKEYS_TOD_SOFT": "Tín hiệu phần mềm (mặc định)", "SETTINGS_HOTKEYS_TOD_BOTH": "Tín hiệu phần cứng & phần mềm", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "Phương thức giao tiếp", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "Chuẩn hóa độ sáng", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "Luôn nhận được mức độ sáng mới nhất từ màn hình khi mở trang độ sáng. Bật tính năng này nếu độ sáng thường xuyên thay đổi từ bên ngoài Khay lấp lánh (ví dụ: một ứng dụng khác).", "SETTINGS_HOTKEYS_TOD_TITLE": "Tắt Hiển thị hành động", "SETTINGS_HOTKEYS_TOD_DESC": "Tùy chỉnh tín hiệu được gửi khi sử dụng phím nóng Turn Off Display hoặc biểu tượng. Tín hiệu phần mềm sẽ hiển thị màn hình đen cho đến khi Windows phát hiện đầu vào (ví dụ: chuột hoặc bàn phím). Tín hiệu phần cứng sẽ tắt nguồn màn hình.", "SETTINGS_HOTKEYS_TOD_HARD": "Tín hiệu phần cứng* (chỉ DDC/CI)", "SETTINGS_HOTKEYS_TOD_NOTE": "* Lưu ý: Không phải tất cả màn hình DDC/CI đều hỗ trợ tính năng này.", "SETTINGS_HOTKEYS_BREAK_TITLE": "Phím nóng phá vỡ các cấp độ được liên kết", "SETTINGS_HOTKEYS_BREAK_DESC": "Khi sử dụng phím nóng cho một màn hình duy nhất và \"các cấp được liên kết\" đang hoạt động, nó sẽ bị vô hiệu hóa.", "SETTINGS_UPDATES_CHANNEL": "Kênh cập nhật", "GENERIC_PAUSE_TOD": "Tạm dừng điều chỉnh thời gian", "GENERIC_PAUSE_IDLE": "Tạm dừng phát hiện nhàn rỗi", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "Vô hiệu hóa lớp phủ", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "Nếu lớp phủ phím nóng của Twinkle Tray can thiệp vào các ứng dụng toàn màn hình, bạn có thể tắt nó tại đây.", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "Ẩn các màn hình", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "Nếu bạn muốn ẩn các màn hình cụ thể khỏi hộp thả xuống, bạn có thể tắt chúng tại đây.", "SETTINGS_TIME_TRANSITON_DESC": "Độ sáng sẽ chuyển đổi nhanh như thế nào khi điều chỉnh thời gian trong ngày được kích hoạt.", "SETTINGS_TIME_ANIMATE_TITLE": "Sinh động giữa các thời điểm", "SETTINGS_TIME_ANIMATE_DESC": "Các giá trị độ sáng sẽ được làm động giữa sự kiện hiện tại và sự kiện được lên lịch tiếp theo. Có thể tăng mức sử dụng CPU. Các điều chỉnh độ sáng thủ công sẽ nhanh chóng bị ghi đè khi tính năng này đang hoạt động.", "GENERIC_SPEED_INSTANT": "Ngay lập tức", "GENERIC_SPEED_SLOW": "Chậm", "GENERIC_SPEED_VERY_SLOW": "Rất chậm", "GENERIC_SPEED_NORMAL": "Bình thường", "GENERIC_SPEED_FAST": "Nhanh", "GENERIC_SPEED_VERY_FAST": "Rất nhanh", "GENERIC_DDC_WARNING": "Các tính năng DDC/CI như kiểm soát trạng thái nguồn có thể khiến màn hình của bạn không phản hồi. Tự chịu trách nhiệm khi sử dụng .", "SETTINGS_GENERAL_TROUBLESHOOTING": "Xử lý sự cố", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "Vô hiệu hóa các phương pháp phát hiện màn hình", "SETTINGS_TIME_TRANSITON_TITLE": "Tốc độ chuyển đổi độ sáng", "SETTINGS_UPDATES_BRANCH_STABLE": "Ổn định (mặc định)", "SETTINGS_UPDATES_BRANCH_BETA": "Thử nghiệm", "SETTINGS_FEATURES_POWER_OFF": "Tắt nguồn màn hình", "GENERIC_DELETE": "Xóa", "PANEL_LABEL_TURN_ON": "Bật nguồn", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "Tự động áp dụng độ sáng", "SETTINGS_FEATURES_ADD": "Thêm tính năng", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "Mã VCP (ví dụ 0x12)", "SETTINGS_TIME_LAT": "Vĩ độ", "SETTINGS_HOTKEY_VALUE": "Giá trị", "GENERIC_DEFAULT": "Mặc định", "SETTINGS_TIME_LONG": "Kinh độ", "SETTINGS_GENERAL_REPORT_TITLE": "Tạo báo cáo", "SETTINGS_HOTKEY_ACTION": "Hành động", "SETTINGS_FEATURES_VCP_LIST_TITLE": "Tất cả mã VCP được báo bởi màn hình này", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "Nhập một số", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "Sử dụng phương pháp v1.15.5 cũ để phát hiện màn hình DDC/CI.", "SETTINGS_FEATURES_POWER_DESC": "Khi gửi lệnh DDC/CI để tắt màn hình, (các) giá trị sau đây sẽ được gửi.", "SETTINGS_FEATURES_ADD_VCP": "Mã VCP", "SETTINGS_FEATURES_ADD_EXISTS": "Tính năng này đã được bật.", "SETTINGS_HOTKEY_ADD_VALUE": "Thêm giá trị", "SETTINGS_HOTKEY_ACTION_OFFSET": "Chỉnh giá trị", "SETTINGS_HOTKEY_VALUES": "Các giá trị", "SETTINGS_HOTKEY_ACTION_SET": "Đặt giá trị", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "Độ sáng" } ================================================ FILE: src/localization/zh-Hant.json ================================================ { "LANGUAGE": "繁體中文", "GENERIC_OK": "確認", "GENERIC_CANCEL": "取消", "GENERIC_SAVE": "儲存", "GENERIC_CLEAR": "清除", "GENERIC_DELETE": "刪除", "GENERIC_OFF": "關閉", "GENERIC_ON": "開啟", "GENERIC_QUIT": "退出", "GENERIC_CLOSE": "關閉", "GENERIC_SETTINGS": "設定", "GENERIC_INSTALL": "安裝", "GENERIC_DISMISS": "忽略", "GENERIC_DEFAULT": "預設", "GENERIC_OPTIONAL": "可選的", "GENERIC_DISPLAY_SINGLE": "顯示器", "GENERIC_ALL_DISPLAYS": "所有顯示器", "GENERIC_REFRESH_DISPLAYS": "重新整理顯示器清單", "GENERIC_MINIMUM": "最小值", "GENERIC_MAXIMUM": "最大值", "GENERIC_NO_DISPLAYS": "未偵測到顯示器,請將其接上電腦。", "GENERIC_NO_COMPATIBLE_DISPLAYS": "未偵測到相容的顯示器。請確認顯示器已啟用「DDC/CI」功能。", "GENERIC_NO_DISPLAYS_SHORT": "未偵測到相容的顯示器。", "GENERIC_NOT_SUPPORTED": "不支持", "GENERIC_SUPPORTED": "支持", "GENERIC_UNSUPPORTED": "不支持", "GENERIC_ACTIVE": "已激活", "GENERIC_SECONDS": "秒", "GENERIC_MINUTES": "分鐘", "GENERIC_DDC_WARNING": "部分DDC/CI功能可能導致您的顯示器沒有回應。請自行承擔使用風險。", "GENERIC_SPEED_INSTANT": "即時", "GENERIC_SPEED_SLOW": "慢", "GENERIC_SPEED_VERY_SLOW": "很慢", "GENERIC_SPEED_NORMAL": "正常", "GENERIC_SPEED_FAST": "快", "GENERIC_SPEED_VERY_FAST": "飛快", "GENERIC_PAUSE_TOD": "暫停時間調整", "GENERIC_PAUSE_IDLE": "暫停間隔檢測", "GENERIC_DETECTING_DISPLAYS": "正在檢測顯示器...", "PANEL_TITLE": "調整亮度", "PANEL_UPDATE_AVAILABLE": "新版本已可供使用", "PANEL_BUTTON_LINK_LEVELS": "同步調整", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "關閉顯示器", "PANEL_LABEL_BRIGHTNESS": "亮度", "PANEL_LABEL_CONTRAST": "對比度", "PANEL_LABEL_INPUTS": "輸入", "PANEL_LABEL_OFF_ON": "電源狀態", "PANEL_LABEL_COLOR_TEMPERATURE": "色溫", "PANEL_LABEL_VOLUME": "音量", "PANEL_LABEL_TURN_OFF": "關閉", "PANEL_LABEL_TURN_ON": "開啟", "INTRO_TITLE": "歡迎使用 Twinkle Tray!", "INTRO_INSTRUCTIONS": "Twinkle Tray 的圖示可能被隱藏了,您應該將其移動至能夠快速觸及的地方。請參閱下方的教學。", "SETTINGS_TITLE": "Twinkle Tray 設定", "SETTINGS_SIDEBAR_GENERAL": "一般", "SETTINGS_SIDEBAR_MONITORS": "顯示器設定", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI 功能", "SETTINGS_SIDEBAR_TIME": "定時調整", "SETTINGS_SIDEBAR_HOTKEYS": "快捷鍵", "SETTINGS_SIDEBAR_UPDATES": "更新", "SETTINGS_GENERAL_TITLE": "一般", "SETTINGS_GENERAL_STARTUP": "在登入時啟動", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "在登入時套用亮度設定", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "Twinkle Tray 啟動時,還原上次套用的亮度。", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "鎖定螢幕時停用", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "當用戶會話鎖定時,停止訪問顯示器,以避免在多用戶環境中發生衝突。", "SETTINGS_GENERAL_THEME_TITLE": "佈景主題", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Windows UI樣式", "SETTINGS_GENERAL_THEME_SYSTEM": "跟隨系統設定(預設)", "SETTINGS_GENERAL_THEME_DARK": "暗色", "SETTINGS_GENERAL_THEME_LIGHT": "亮色", "SETTINGS_GENERAL_LANGUAGE_TITLE": "語言", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "系統語言(預設)", "SETTINGS_GENERAL_RESET_TITLE": "重置設定值", "SETTINGS_GENERAL_RESET_DESC": "按下此按鈕以清除設定值。", "SETTINGS_GENERAL_RESET_BUTTON": "重置設定值", "SETTINGS_GENERAL_ACRYLIC_TITLE": "壓克力模糊效果", "SETTINGS_GENERAL_ACRYLIC_DESC": "設定 Twinkle Tray 是否採用模糊的透明背景。", "SETTINGS_GENERAL_MICA_TITLE": "Mica 模糊效果", "SETTINGS_GENERAL_MICA_DESC": "設定 Twinkle Tray 是否採用 Mica 模糊的背景。", "SETTINGS_GENERAL_ANALYTICS_TITLE": "資料分析", "SETTINGS_GENERAL_ANALYTICS_DESC": "傳回使用資料以協助改善 Twinkle Tray。不會包含個人資訊。{{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "了解更多", "SETTINGS_GENERAL_SCROLL_TITLE": "工具列圖示快捷捲動方式", "SETTINGS_GENERAL_SCROLL_DESC": "藉由在工具列的圖示上捲動,一次調整所有顯示器的亮度。在一些觸控板上可能無效。", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "工具列圖示", "SETTINGS_GENERAL_TROUBLESHOOTING": "疑難排解", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "已啟用的顯示器檢測方法", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "如果 Twinkle Tray 在點擊系統匣圖示時沒有回應,或是無法偵測您的顯示器,您可以嘗試停用顯示器偵測方式。重新啟動 Twinkle Tray 以套用變更。{{1}}", "SETTINGS_GENERAL_OVERLAY_TITLE": "預設重疊行為", "SETTINGS_GENERAL_OVERLAY_DESC": "設定亮度按鍵快顯視窗於其他應用程式上的重疊等級。您通常不需要調整這項設定。", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "停用重疊視窗", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "如果 Twinkle Tray 的快捷鍵重疊視窗與全螢幕應用程式互相干擾,您可以在此停用。", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "最為相容", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "重疊視窗會強制覆蓋於幾乎所有的視窗上面,但不會顯示在指定為「永遠在最上層」的應用程式上。", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "強制開啟", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "永遠嘗試讓快顯視窗顯示於所有的視窗上。這可能會導致使用全螢幕的遊戲或程式出現問題。部分遊戲的反作弊系統可能也會被觸發。", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "傳統DDC/CI檢測方式", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "使用舊版 v1.15.5 的方式來檢測 DDC/CI 螢幕。", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "自動設定亮度", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "若您的螢幕在關閉/或是連接/中斷連接後反應變得很奇怪,關閉此選項可能會有幫助。", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "於指定螢幕上不自動套用設定", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "於指定的顯示器上在所有的硬體/電源事件發生後關閉自動亮度套用。這包括待機檢測的功能。", "SETTINGS_GENERAL_REPORT_TITLE": "生成報告", "SETTINGS_GENERAL_REPORT_DESC": "儲存有關您螢幕的設定與資訊至文字檔以供偵錯。", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "主題更新檢測", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "檢測來自 Windows 的強調色 / 壁紙 / 主題變化,用於更新託盤圖標和 Mica 效果。若有第三方軟件頻繁更改主題、導致 CPU 佔用升高,可以關閉此功能。", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "顯示器電源狀態檢測", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "用於檢測顯示器電源狀態的變化。如果在顯示器開關機或進入空閒狀態時遇到錯誤,關閉此功能可能有所幫助。更改此設置需要重啓後生效。", "SETTINGS_MONITORS_RATE_TITLE": "亮度更新頻率", "SETTINGS_MONITORS_RATE_DESC": "調整螢幕亮度時送出設定值的頻率。如果螢幕發生閃爍,請加大間隔時間。", "SETTINGS_MONITORS_RATE_0": "飛快", "SETTINGS_MONITORS_RATE_1": "快速(250 毫秒)", "SETTINGS_MONITORS_RATE_2": "正常(500 毫秒)", "SETTINGS_MONITORS_RATE_3": "慢(1 秒)", "SETTINGS_MONITORS_RATE_4": "很慢(2 秒)", "SETTINGS_MONITORS_RENAME_TITLE": "重新命名顯示器", "SETTINGS_MONITORS_RENAME_DESC": "您可以在下方輸入,幫每部顯示器取名字(如:左側顯示器、中間顯示器)。將欄位留空以使用原本名稱。", "SETTINGS_MONITORS_ENTER_NAME": "輸入名稱", "SETTINGS_MONITORS_REORDER_TITLE": "重新排序顯示器", "SETTINGS_MONITORS_REORDER_DESC": "按住並拖動,以變更顯示器在工具列的顯示順序。", "SETTINGS_MONITORS_NORMALIZE_TITLE": "亮度正規化", "SETTINGS_MONITORS_NORMALIZE_DESC": "每部顯示器通常有不同的亮度區間。藉由對顯示器限制最低、最高亮度值,讓不同顯示器間的亮度更加一致。同型的顯示器將使用一樣的設定值。", "SETTINGS_MONITORS_DETAILS_NAME": "命名", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "內部名稱", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "通訊方式", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "目前亮度", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "最大亮度", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "亮度標準化", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "隱藏未啟用的內部顯示器", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "當螢幕被蓋上或內部顯示器被停用,在面板中隱藏該亮度控制。", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "隱藏顯示器", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "如果您想要從彈出視窗中隱藏指定的顯示器,您可以在此設定。", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR 顯示設定", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "為特定顯示器啟用 SDR 亮度滑桿。顯示器必須在 Windows 中啟用 HDR 才能使用此功能。", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR 取代主要滑桿", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "在 HDR 啟用時,仍可從主亮度滑桿控制 SDR 亮度。", "SETTINGS_FEATURES_DESCRIPTION": "切換亮度面板中的特定 DDC/CI 功能。須至少啟用一項功能,您的顯示器才會出現在亮度面板。非所有顯示器都支援這些功能(如筆電或平板電腦的螢幕)。", "SETTINGS_FEATURES_UNSUPPORTED": "此顯示器不支援 DDC/CI 功能。", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "讀取目前亮度", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "於每次亮度控制面板開啟時取得最新的亮度值。若您的亮度(或是其他如對比度的設定)經常性地於控制面板以外的地方被更改,請開啟此選項。", "SETTINGS_FEATURES_POWER_TITLE": "電源狀態訊號", "SETTINGS_FEATURES_POWER_DESC": "當使用 DDC/CI 指令來關閉顯示器時,以下的參數將會被送出。", "SETTINGS_FEATURES_POWER_STANDBY": "待命", "SETTINGS_FEATURES_POWER_OFF": "關閉", "SETTINGS_FEATURES_POWER_COMPAT": "最相容的", "SETTINGS_FEATURES_POWER_WARNING": "「待命」選項更適合於面板中控制顯示器的開/關。然而,很多顯示器對於更改電源狀態的指令無法正確響應。請自行承擔使用風險。", "SETTINGS_FEATURES_ADD": "增加功能", "SETTINGS_FEATURES_ADD_DESC": "輸入您想為您的顯示器加入的 VCP 功能代碼。請注意 Twinkle Tray 並不會驗證此 VCP 代碼是否能於您的顯示器上運作。請自行承擔使用風險。", "SETTINGS_FEATURES_ADD_VCP": "VCP 功能代碼", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP 功能代碼 (例如:0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "此功能已開啟。", "SETTINGS_FEATURES_VCP_LIST_TITLE": "所有由該顯示器回報的 VCP 功能代碼", "SETTINGS_FEATURES_VCP_LIST_DESC": "以下列表為由 Windows 提供此螢幕的可用 VCP 功能代碼。 Twinkle Tray並不會驗證這些 VCP 功能代碼的可用性或穩定性。 請自行承擔使用風險。", "SETTINGS_FEATURES_VCP_EXPECTED": "預期值", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR 亮度", "SETTINGS_TIME_TITLE": "定時調整", "SETTINGS_TIME_DESC": "在指定的時間點自動將顯示器設為給定的亮度。所有顯示器都會被調為相同、正規化的亮度。", "SETTINGS_TIME_ADD": "新增時間", "SETTINGS_TIME_REMOVE": "移除時間", "SETTINGS_TIME_INDIVIDUAL_TITLE": "設定個別顯示器的亮度", "SETTINGS_TIME_INDIVIDUAL_DESC": "個別設定每部顯示器的亮度,而不是統一調整。", "SETTINGS_TIME_TRANSITON_TITLE": "亮度轉換速度", "SETTINGS_TIME_TRANSITON_DESC": "定時調整啟用後,亮度該以何種速度轉換。", "SETTINGS_TIME_STARTUP_TITLE": "在應用程式啟動時檢查", "SETTINGS_TIME_STARTUP_DESC": "在 Twinkle Tray 啟動時將亮度調整至最相近的時間設定。", "SETTINGS_TIME_IDLE_TITLE": "閒置感應", "SETTINGS_TIME_IDLE_DESC": "若電腦有一段時間是沒有活動的狀態,則所有顯示器的亮度將會被降低。", "SETTINGS_TIME_ANIMATE_TITLE": "時間之間的動畫", "SETTINGS_TIME_ANIMATE_DESC": "亮度值將在目前和下一個預定事件之間進行動畫處理。可能會增加CPU的使用率。當此功能啟動時,手動亮度調整將很快被覆蓋。", "SETTINGS_TIME_SUN_TITLE": "太陽位置座標", "SETTINGS_TIME_SUN_DESC": "輸入您目前的經緯度,讓「太陽位置」功能使用正確的時間。", "SETTINGS_TIME_USE_SUN_POSITION": "使用太陽位置", "SETTINGS_TIME_LAT": "緯度", "SETTINGS_TIME_LONG": "經度", "SETTINGS_TIME_SUN_GET": "取得座標", "SETTINGS_TIME_IDLE_FS_TITLE": "全屏模式下禁用閒置檢測", "SETTINGS_TIME_IDLE_FS_DESC": "全屏模式下禁用閒置檢測。此設定僅對當前焦點窗口生效。", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "媒體播放時禁用閒置檢測", "SETTINGS_TIME_IDLE_MEDIA_DESC": "在播放任何媒體時,閒置檢測將被禁用。這包括視頻和音頻。這僅適用於 Windows 報告媒體正在播放時。", "SETTINGS_HOTKEYS_TITLE": "快捷鍵", "SETTINGS_HOTKEYS_DESC": "設定快捷鍵以調整顯示器亮度。", "SETTINGS_HOTKEYS_ADD": "新增快捷鍵", "SETTINGS_HOTKEYS_REMOVE": "移除快捷鍵", "SETTINGS_HOTKEYS_INCREASE": "增加亮度", "SETTINGS_HOTKEYS_DECREASE": "降低亮度", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "在此按下快捷鍵", "SETTINGS_HOTKEYS_LEVEL_TITLE": "亮度調整級距", "SETTINGS_HOTKEYS_LEVEL_DESC": "使用快捷鍵調整亮度時的跨距。", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "滾動數量", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "反轉滾動", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "在系統託盤圖標上滾動時,滾動方向將反轉。", "SETTINGS_HOTKEYS_TOD_TITLE": "關閉顯示器", "SETTINGS_HOTKEYS_TOD_DESC": "自訂使用快捷鍵或圖示時,送出的「關閉螢幕」訊號類型。軟體訊號會顯示黑畫面,直到偵測滑鼠或鍵盤的動作;硬體訊號將直接關閉顯示器。", "SETTINGS_HOTKEYS_TOD_NONE": "無(隱藏圖示)", "SETTINGS_HOTKEYS_TOD_SOFT": "軟體訊號 (預設值)", "SETTINGS_HOTKEYS_TOD_HARD": "硬體*訊號(僅限 DDC/CI)", "SETTINGS_HOTKEYS_TOD_BOTH": "硬體* 和軟體訊號", "SETTINGS_HOTKEYS_TOD_NOTE": "*注意:並非所有 DDC/CI 顯示器都支援此功能。", "SETTINGS_HOTKEYS_BREAK_TITLE": "快捷鍵會無視同步亮度", "SETTINGS_HOTKEYS_BREAK_DESC": "使用快捷鍵時,同步亮度將被關閉。", "SETTINGS_HOTKEY_OFF_WARN": "此操作將使用在「關閉顯示器」下選擇的選項。如果您希望改為關閉特定顯示器,請改用「設定」或「循環」快捷鍵操作。", "SETTINGS_HOTKEY_TARGET": "行爲目標", "SETTINGS_HOTKEY_VALUE": "數值列表", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "輸入一個數字", "SETTINGS_HOTKEY_VALUES": "數值列表", "SETTINGS_HOTKEY_ADD_VALUE": "添加數值", "SETTINGS_HOTKEY_ADD_ACTION": "添加行爲", "SETTINGS_HOTKEY_ACTION": "行爲", "SETTINGS_HOTKEY_ACTION_SET": "設定數值", "SETTINGS_HOTKEY_ACTION_OFFSET": "調整數值", "SETTINGS_HOTKEY_ACTION_CYCLE": "數值循環列表", "SETTINGS_PROFILES_TITLE": "配置文件", "SETTINGS_PROFILES_DESC": "根據當前焦點應用自動調整亮度或快捷鍵提示行爲。你還可以在系統託盤右鍵菜單中添加配置文件,快速將亮度切換到預設的配置。", "SETTINGS_PROFILES_ADD": "新的配置文件", "SETTINGS_PROFILES_NAME": "配置文件名稱", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "設置激活時亮度", "SETTINGS_PROFILES_SHOW_MENU": "在右鍵託盤菜單中顯示", "SETTINGS_PROFILES_TRIGGER_TITLE": "應用程式觸發設定", "SETTINGS_PROFILES_APP_PATH": "應用程式路徑", "SETTINGS_PROFILES_APP_DESC": "如果希望在特定應用獲得焦點時自動激活此配置文件,請在下方輸入該 EXE 的完整路徑或部分路徑。", "SETTINGS_PROFILES_OVERLAY_TITLE": "覆蓋提示顯示行爲", "SETTINGS_PROFILES_OVERLAY_DESC": "當指定應用處於焦點時,改變快捷鍵提示的顯示行爲。此功能在手動激活配置文件時不起作用。", "SETTINGS_UPDATES_TITLE": "更新", "SETTINGS_UPDATES_VERSION": "您有 Twinkle Tray {{1}}。", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "自動檢查新版本", "SETTINGS_UPDATES_AUTOMATIC_DESC": "有新版本時,將顯示在亮度調節的面板上。", "SETTINGS_UPDATES_MS_STORE": "欲檢查新版本,請前往 Microsoft Store。", "SETTINGS_UPDATES_AVAILABLE": "新版的 Twinkle Tray 推出了!", "SETTINGS_UPDATES_NONE_AVAILABLE": "已處於最新版本,此版本的更動如下:", "SETTINGS_UPDATES_DOWNLOADING": "下載更新中…", "SETTINGS_UPDATES_DOWNLOAD": "下載並安裝 {{1}}", "SETTINGS_UPDATES_CHANNEL": "更新渠道", "SETTINGS_UPDATES_BRANCH_STABLE": "稳定(默认)", "SETTINGS_UPDATES_BRANCH_BETA": "β" } ================================================ FILE: src/localization/zh_Hans.json ================================================ { "LANGUAGE": "简体中文", "GENERIC_OK": "确定", "GENERIC_CANCEL": "取消", "GENERIC_SAVE": "保存", "GENERIC_CLEAR": "清除", "GENERIC_OFF": "关闭", "GENERIC_ON": "启用", "GENERIC_QUIT": "退出", "GENERIC_CLOSE": "关闭", "GENERIC_SETTINGS": "设置", "GENERIC_INSTALL": "安装", "GENERIC_DISMISS": "忽略", "GENERIC_DISPLAY_SINGLE": "显示器", "GENERIC_ALL_DISPLAYS": "所有显示器", "GENERIC_REFRESH_DISPLAYS": "刷新显示器列表", "GENERIC_MINIMUM": "最小值", "GENERIC_MAXIMUM": "最大值", "GENERIC_NO_DISPLAYS": "未检测到显示器,请将显示器连接到您的电脑。", "GENERIC_NO_COMPATIBLE_DISPLAYS": "找不到兼容的显示器,请检查您的显示器是否已启用“DDC/CI”。", "GENERIC_NO_DISPLAYS_SHORT": "未检测到兼容的显示器。", "GENERIC_SECONDS": "秒", "GENERIC_MINUTES": "分", "GENERIC_DDC_WARNING": "DDC/CI 功能可能会导致显示器无响应。请自行承担使用风险。", "GENERIC_SPEED_INSTANT": "立刻", "GENERIC_SPEED_SLOW": "慢", "GENERIC_SPEED_VERY_SLOW": "非常慢", "GENERIC_SPEED_NORMAL": "正常", "GENERIC_SPEED_FAST": "快", "GENERIC_SPEED_VERY_FAST": "非常快", "PANEL_TITLE": "调整亮度", "PANEL_UPDATE_AVAILABLE": "有新版本可用", "PANEL_BUTTON_LINK_LEVELS": "同步调整", "PANEL_BUTTON_TURN_OFF_DISPLAYS": "关闭显示器", "PANEL_LABEL_BRIGHTNESS": "亮度", "PANEL_LABEL_CONTRAST": "对比度", "PANEL_LABEL_OFF_ON": "电源状态", "PANEL_LABEL_COLOR_TEMPERATURE": "色温", "PANEL_LABEL_VOLUME": "音量", "PANEL_LABEL_TURN_OFF": "关机", "INTRO_TITLE": "欢迎使用 Twinkle Tray!", "INTRO_INSTRUCTIONS": "Twinkle Tray 的托盘图标可能被收起,所以您或许应将其移动到方便点击的位置。请参阅下面的说明。", "SETTINGS_TITLE": "Twinkle Tray 设置", "SETTINGS_SIDEBAR_GENERAL": "通用", "SETTINGS_SIDEBAR_MONITORS": "显示器设置", "SETTINGS_SIDEBAR_FEATURES": "DDC/CI 功能", "SETTINGS_SIDEBAR_TIME": "定时调整", "SETTINGS_SIDEBAR_HOTKEYS": "快捷键", "SETTINGS_SIDEBAR_UPDATES": "更新", "SETTINGS_GENERAL_TITLE": "通用", "SETTINGS_GENERAL_STARTUP": "开机时启动", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_TITLE": "启动时调整亮度", "SETTINGS_GENERAL_BRIGHTNESS_STARTUP_DESC": "在 Twinkle Tray 启动时,恢复到上次关闭时所应用的亮度。", "SETTINGS_GENERAL_THEME_TITLE": "主题", "SETTINGS_GENERAL_THEME_SYSTEM": "跟随系统(默认)", "SETTINGS_GENERAL_THEME_DARK": "深色", "SETTINGS_GENERAL_THEME_LIGHT": "浅色", "SETTINGS_GENERAL_LANGUAGE_TITLE": "语言", "SETTINGS_GENERAL_LANGUAGE_SYSTEM": "跟随系统(默认)", "SETTINGS_GENERAL_RESET_TITLE": "重置设置", "SETTINGS_GENERAL_RESET_DESC": "点此按钮以清除您的应用设置。", "SETTINGS_GENERAL_RESET_BUTTON": "重置设置", "SETTINGS_GENERAL_ACRYLIC_TITLE": "亚克力(Acrylic)模糊", "SETTINGS_GENERAL_ACRYLIC_DESC": "在 Twinkle Tray 中启用或禁用透明背景模糊效果。", "SETTINGS_GENERAL_MICA_TITLE": "云母模糊", "SETTINGS_GENERAL_MICA_DESC": "在 Twinkle Tray 中打开或关闭背景后方的模糊效果。", "SETTINGS_GENERAL_ANALYTICS_TITLE": "分析", "SETTINGS_GENERAL_ANALYTICS_DESC": "发送使用数据以帮助改进 Twinkle Tray 。不会发送个人信息。{{1}}", "SETTINGS_GENERAL_ANALYTICS_LINK": "了解更多", "SETTINGS_GENERAL_SCROLL_TITLE": "托盘图标的鼠标滚轮快捷操作", "SETTINGS_GENERAL_SCROLL_DESC": "通过在系统托盘图标使用鼠标滚轮,一次调整所有显示器的亮度。可能不兼容某些触控板。", "SETTINGS_GENERAL_TRAY_ICON_TITLE": "托盘图标", "SETTINGS_GENERAL_TROUBLESHOOTING": "疑难解答", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_TITLE": "已启用的显示器检测模式", "SETTINGS_GENERAL_DIS_MONITOR_FEATURES_DESC": "如果 Twinkle Tray 在点击托盘图标时没有反应,或者没有检测到你的显示器,你可以尝试禁用某些显示器检测方法。重新启动 Twinkle Tray 以使改变生效。{{1}}", "SETTINGS_GENERAL_DIS_OVERLAY_TITLE": "禁用快捷键提示", "SETTINGS_GENERAL_DIS_OVERLAY_DESC": "如果 Twinkle Tray 的亮度快捷键提示在全屏应用中造成干扰,可以在此将其关闭。", "SETTINGS_MONITORS_RATE_TITLE": "亮度更新速度", "SETTINGS_MONITORS_RATE_DESC": "调整显示器的亮度值时,显示器亮度的更新速度。如果显示器闪烁,请延长亮度更新时间。", "SETTINGS_MONITORS_RATE_0": "非常快", "SETTINGS_MONITORS_RATE_1": "快(250ms)", "SETTINGS_MONITORS_RATE_2": "一般(500ms)", "SETTINGS_MONITORS_RATE_3": "慢(1s)", "SETTINGS_MONITORS_RATE_4": "非常慢(2s)", "SETTINGS_MONITORS_RENAME_TITLE": "重命名显示器", "SETTINGS_MONITORS_RENAME_DESC": "如果您希望每个显示器使用不同的名称(例如“左显示器”、“中显示器”),可以在下面输入。不填写将恢复原始的名称。", "SETTINGS_MONITORS_ENTER_NAME": "输入名称", "SETTINGS_MONITORS_REORDER_TITLE": "调整显示器的顺序", "SETTINGS_MONITORS_REORDER_DESC": "更改显示器在托盘中的显示顺序。单击并拖动以进行更改。", "SETTINGS_MONITORS_NORMALIZE_TITLE": "平衡亮度", "SETTINGS_MONITORS_NORMALIZE_DESC": "显示器通常有不同的亮度范围。通过限制每个显示器的最小/最大亮度,使显示器之间的亮度更加一致。", "SETTINGS_MONITORS_DETAILS_NAME": "名称", "SETTINGS_MONITORS_DETAILS_INTERNAL_NAME": "内部名称", "SETTINGS_MONITORS_DETAILS_COMMUNICATION": "通信方式", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS": "当前亮度", "SETTINGS_MONITORS_DETAILS_MAX_BRIGHTNESS": "最大亮度", "SETTINGS_MONITORS_DETAILS_BRIGHTNESS_NORMALIZATION": "统一亮度区间", "SETTINGS_MONITORS_HIDE_INTERNAL_TITLE": "隐藏不活动的内部显示器", "SETTINGS_MONITORS_HIDE_INTERNAL_DESC": "如果显示器被合上,或者在 Windows 中禁用了内建屏幕(自带显示器),那么该显示器的亮度滑块将被隐藏。", "SETTINGS_MONITORS_HIDE_DISPLAYS_TITLE": "隐藏显示器", "SETTINGS_MONITORS_HIDE_DISPLAYS_DESC": "如果您想从弹出窗口中隐藏特定的显示器,您可以在此处将其关闭。", "SETTINGS_FEATURES_DESCRIPTION": "启用或禁用亮度设置面板中特定的 DDC/CI 功能。 至少启用了一个或多个功能的显示器才将显示在亮度设置面板中。 并非所有显示器都支持这些功能,例如笔记本电脑、平板电脑等。", "SETTINGS_FEATURES_UNSUPPORTED": "此显示器不支持 DDC/CI 功能。", "SETTINGS_FEATURES_CUR_BRIGHTNESS_TITLE": "检查当前值", "SETTINGS_FEATURES_CUR_BRIGHTNESS_DESC": "打开亮度面板时,总是从显示器上获取最新的值。如果亮度(或其他 VCP 代码,例如对比度)经常从 Twinkle Tray 外部更改,请启用此功能。", "SETTINGS_TIME_TITLE": "按时间调整", "SETTINGS_TIME_DESC": "按时间自动调整你的显示器亮度。所有显示器都将会同时调整到一个相同的正常的值。", "SETTINGS_TIME_ADD": "添加时间点", "SETTINGS_TIME_REMOVE": "移除时间点", "SETTINGS_TIME_INDIVIDUAL_TITLE": "设置每个显示器的亮度", "SETTINGS_TIME_INDIVIDUAL_DESC": "为每个显示器设置单独的亮度,而不是同时为所有显示器设置相同亮度。", "SETTINGS_TIME_TRANSITON_TITLE": "亮度调整速度", "SETTINGS_TIME_TRANSITON_DESC": "当按照所设定的时间激活亮度调整时,亮度变化的速度。", "SETTINGS_TIME_STARTUP_TITLE": "应用启动时检测", "SETTINGS_TIME_STARTUP_DESC": "当 Twinkle Tray 启动时,调整亮度以匹配最近的时间段设置。", "SETTINGS_TIME_IDLE_TITLE": "闲置检测", "SETTINGS_TIME_IDLE_DESC": "如果一段时间里没有检测到输入,就调低全部显示器的亮度。", "SETTINGS_HOTKEYS_TITLE": "快捷键", "SETTINGS_HOTKEYS_DESC": "设置快捷键以调整一个或所有显示器的亮度。", "SETTINGS_HOTKEYS_ADD": "添加快捷键", "SETTINGS_HOTKEYS_REMOVE": "移除快捷键", "SETTINGS_HOTKEYS_INCREASE": "提高亮度", "SETTINGS_HOTKEYS_DECREASE": "降低亮度", "SETTINGS_HOTKEYS_PRESS_KEYS_HINT": "在此处输入快捷键", "SETTINGS_HOTKEYS_LEVEL_TITLE": "亮度级别调整", "SETTINGS_HOTKEYS_LEVEL_DESC": "修改每次按下快捷键时调整亮度的数值。", "SETTINGS_HOTKEYS_TOD_TITLE": "关闭显示器功能的行为", "SETTINGS_HOTKEYS_TOD_DESC": "修改“关闭显示器”按钮或快捷键的行为。软件信号将会使显示器暂时熄灭,当Windows检测到输入操作(例如键盘或鼠标)时会自动点亮。硬件信号将直接关闭显示器的电源。", "SETTINGS_HOTKEYS_TOD_NONE": "无(隐藏图标)", "SETTINGS_HOTKEYS_TOD_SOFT": "软件信号(默认)", "SETTINGS_HOTKEYS_TOD_HARD": "硬件*信号(仅限部分支持 DDC/CI 的显示器)", "SETTINGS_HOTKEYS_TOD_BOTH": "硬件*和软件信号", "SETTINGS_HOTKEYS_TOD_NOTE": "*注意:不是所有支持 DDC/CI 的显示器都支持该功能。", "SETTINGS_HOTKEYS_BREAK_TITLE": "使用快捷键时分开调整各屏幕亮度", "SETTINGS_HOTKEYS_BREAK_DESC": "当使用快捷键对某一个屏幕进行亮度调节,并且“同步调整”功能打开时,此功能将被禁用。", "SETTINGS_UPDATES_TITLE": "更新", "SETTINGS_UPDATES_VERSION": "正在使用 Twinkle Tray {{1}} 。", "SETTINGS_UPDATES_AUTOMATIC_TITLE": "自动检查更新", "SETTINGS_UPDATES_AUTOMATIC_DESC": "当有新版本时,将显示在亮度设置面板中。", "SETTINGS_UPDATES_MS_STORE": "要检查新版本,请访问 Microsoft应用商店。", "SETTINGS_UPDATES_AVAILABLE": "Twinkle Tray 有新版本可用!", "SETTINGS_UPDATES_NONE_AVAILABLE": "已是最新版。目前的版本包括以下更新:", "SETTINGS_UPDATES_DOWNLOADING": "正在下载更新…", "SETTINGS_UPDATES_DOWNLOAD": "下载并安装 {{1}}", "GENERIC_PAUSE_IDLE": "暂停闲置检测", "SETTINGS_TIME_ANIMATE_TITLE": "平滑过渡", "SETTINGS_TIME_ANIMATE_DESC": "亮度将在当前时间和下一个预定事件之间平滑过渡。这可能会增加 CPU 使用率。启用此功能时,手动调节亮度会很快被覆盖。", "SETTINGS_UPDATES_CHANNEL": "更新频道", "GENERIC_PAUSE_TOD": "调整暂停时间", "SETTINGS_UPDATES_BRANCH_STABLE": "稳定版(默认)", "SETTINGS_UPDATES_BRANCH_BETA": "测试版", "SETTINGS_FEATURES_POWER_OFF": "关机", "GENERIC_DELETE": "删除", "GENERIC_OPTIONAL": "可选", "SETTINGS_GENERAL_AUTOBRIGHT_TITLE": "自动应用亮度", "SETTINGS_GENERAL_REPORT_TITLE": "生成报告", "SETTINGS_FEATURES_POWER_COMPAT": "最适配", "SETTINGS_FEATURES_ADD": "添加功能", "GENERIC_DEFAULT": "默认", "PANEL_LABEL_TURN_ON": "接通电源", "SETTINGS_GENERAL_ON_OVERLAY_TITLE": "最大兼容", "SETTINGS_GENERAL_ON_OVERLAY_DESC": "该提示通常会显示在大多数窗口上方,但不会强行显示在被设为“始终置顶”的应用之上。", "SETTINGS_GENERAL_FORCE_OVERLAY_TITLE": "强制显示", "SETTINGS_GENERAL_OVERLAY_TITLE": "默认亮度提示行为", "SETTINGS_GENERAL_OVERLAY_DESC": "控制亮度快捷键提示在其他应用上方显示的优先级。通常无需更改此设置。", "SETTINGS_GENERAL_LEGACY_DDC_TITLE": "老旧的 DDC/CI 检测方式", "SETTINGS_GENERAL_LEGACY_DDC_DESC": "使用旧的 v1.15.5 方式检测 DDC/CI 显示器。", "SETTINGS_GENERAL_AUTOBRIGHT_DESC": "如果您的显示器在关闭/打开或断开/连接硬件后响应异常,禁用此功能可能会有所帮助。", "SETTINGS_GENERAL_SKIP_APPLY_DESC": "在特定显示器的所有硬件/电源事件发生后禁用自动应用已知亮度。这包括空闲检测功能。", "SETTINGS_TIME_SUN_TITLE": "太阳位置坐标", "SETTINGS_HOTKEYS_SCROLL_AMOUNT": "滚动幅度", "SETTINGS_HOTKEY_TARGET": "行为目标", "SETTINGS_PROFILES_SHOW_MENU": "在右键托盘菜单中显示", "SETTINGS_PROFILES_TRIGGER_TITLE": "应用程序触发器设置", "SETTINGS_PROFILES_APP_PATH": "添加路径", "SETTINGS_GENERAL_REPORT_DESC": "保存一个文本文件,其中包含有关显示器和设置的信息,以便调试。", "SETTINGS_FEATURES_POWER_TITLE": "电源状态信号", "SETTINGS_FEATURES_POWER_DESC": "当发送 DDC/CI 命令来关闭显示器时,将发送以下值。", "SETTINGS_FEATURES_POWER_STANDBY": "待机", "SETTINGS_FEATURES_ADD_DESC": "输入要添加到显示屏的功能的 VCP 代码。请注意,Twinkle Tray 无法验证您的显示屏是否支持该 VCP 代码。请自行承担使用风险。", "SETTINGS_FEATURES_ADD_VCP": "VCP 代码", "SETTINGS_FEATURES_ADD_PLACEHOLDER": "VCP 代码(例如 0x12)", "SETTINGS_FEATURES_ADD_EXISTS": "该功能已激活。", "SETTINGS_FEATURES_VCP_LIST_TITLE": "该显示器报告的所有 VCP 代码", "SETTINGS_FEATURES_VCP_LIST_DESC": "以下是该显示器向 Windows 报告的可用 VCP 代码列表。Twinkle Tray 并未验证这些 VCP 代码的功能性或稳定性。请自行承担使用风险。", "SETTINGS_FEATURES_VCP_EXPECTED": "预期值", "SETTINGS_TIME_LAT": "纬度", "SETTINGS_TIME_LONG": "经度", "SETTINGS_TIME_SUN_GET": "获取坐标", "SETTINGS_TIME_IDLE_FS_TITLE": "全屏模式下禁用闲置检测", "SETTINGS_HOTKEY_VALUE": "数值", "SETTINGS_GENERAL_SKIP_APPLY_TITLE": "跳过自动应用于特定显示器", "SETTINGS_GENERAL_FORCE_OVERLAY_DESC": "始终尝试将亮度提示显示在其他窗口之上。这可能会影响独占全屏的游戏或其他全屏应用,某些游戏的反作弊系统也可能因此被触发。", "SETTINGS_FEATURES_POWER_WARNING": "“待机” 选项更有可能允许从 Twinkle Tray 切换显示器的开关。不过,许多显示器对电源状态的改变反应不灵敏。请自行承担使用风险。", "SETTINGS_TIME_SUN_DESC": "要使用 “太阳位置” 进行时间调整,请输入当前的经纬度,以便确定正确的时间。", "SETTINGS_TIME_IDLE_FS_DESC": "全屏模式下禁用闲置检测。此设置仅对当前焦点窗口生效。", "SETTINGS_PROFILES_APP_DESC": "如果希望在特定应用获得焦点时自动激活此配置文件,请在下方输入该 EXE 的完整路径或部分路径。", "SETTINGS_TIME_IDLE_MEDIA_TITLE": "媒体播放时禁用闲置检测", "SETTINGS_TIME_IDLE_MEDIA_DESC": "在播放任何媒体时,闲置检测将被禁用。这包括视频和音频。这仅适用于 Windows 报告媒体正在播放时。", "SETTINGS_HOTKEY_OFF_WARN": "该行为将使用在 “关闭显示器操作 ”下选择的选项。如果要关闭特定显示器,请使用 “设置 ”或 “循环 ”快捷键操作。", "SETTINGS_HOTKEY_VALUE_PLACEHOLDER": "输入一个数字", "SETTINGS_HOTKEY_VALUES": "数值列表", "SETTINGS_HOTKEY_ADD_VALUE": "添加数值", "SETTINGS_HOTKEY_ACTION": "行为", "SETTINGS_HOTKEY_ACTION_SET": "设置数值", "SETTINGS_HOTKEY_ACTION_OFFSET": "调节数值", "SETTINGS_HOTKEY_ACTION_CYCLE": "循环数值列表", "SETTINGS_PROFILES_TITLE": "配置文件", "SETTINGS_PROFILES_ADD": "新的配置文件", "SETTINGS_PROFILES_NAME": "配置文件名", "SETTINGS_PROFILES_BRIGHTNESS_TOGGLE": "设置激活时的亮度", "SETTINGS_PROFILES_DESC": "根据当前焦点应用自动调整亮度或快捷键提示行为。你还可以在系统托盘右键菜单中添加配置文件,快速将亮度切换到预设的配置。", "SETTINGS_PROFILES_OVERLAY_TITLE": "覆盖提示显示行为", "SETTINGS_PROFILES_OVERLAY_DESC": "当指定应用处于焦点时,改变快捷键提示的显示行为。此功能在手动激活配置文件时不起作用。", "SETTINGS_HOTKEYS_INVERT_SCROLL_DESC": "在系统托盘图标上滚动时,滚动方向将反转。", "SETTINGS_HOTKEYS_INVERT_SCROLL_TITLE": "反转滚动", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_TITLE": "锁定屏幕时禁用", "SETTINGS_MONITORS_HDR_DISPLAYS_TITLE": "HDR 显示设置", "SETTINGS_MONITORS_HDR_DISPLAYS_DESC": "为特定显示器启用 SDR 亮度滑块。要使此功能生效,显示器必须在系统中启用 HDR 功能。", "SETTINGS_MONITORS_SDR_SLIDER_TITLE": "SDR 替换主滑块", "SETTINGS_MONITORS_SDR_SLIDER_DESCRIPTION": "在HDR模式激活时,通过主亮度滑块控制SDR亮度。", "SETTINGS_FEATURES_SDR_BRIGHTNESS": "SDR 亮度", "SETTINGS_GENERAL_DISABLE_ON_LOCK_SCREEN_DESC": "当用户会话锁定时,不访问显示器,以避免在多用户环境中发生冲突。", "GENERIC_NOT_SUPPORTED": "不支持", "GENERIC_SUPPORTED": "支持", "GENERIC_UNSUPPORTED": "不支持", "GENERIC_ACTIVE": "已激活", "GENERIC_DETECTING_DISPLAYS": "正在检测显示器…", "PANEL_LABEL_INPUTS": "输入", "SETTINGS_GENERAL_WINDOWS_UI_STYLE_TITLE": "Windows UI 样式", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_TITLE": "主题更新检测", "SETTINGS_GENERAL_SKIP_THEME_CHANGES_DESC": "检测来自 Windows 的强调色 / 壁纸 / 主题变化,用于更新托盘图标和 Mica 效果。若有第三方软件频繁更改主题、导致 CPU 占用升高,可以关闭此功能。", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_DESC": "用于检测显示器电源状态的变化。如果在显示器开关机或进入空闲状态时遇到错误,关闭此功能可能有所帮助。更改此设置需要重启后生效。", "SETTINGS_GENERAL_SKIP_POWER_EVENTS_TITLE": "显示器电源状态检测", "SETTINGS_TIME_USE_SUN_POSITION": "使用太阳位置", "SETTINGS_HOTKEY_ADD_ACTION": "添加行为", "SETTINGS_MONITORS_DETAILS_HDR": "HDR", "GENERIC_CALIBRATION_POINT": "校准点", "GENERIC_ICON": "图标", "GENERIC_TEXT": "文字", "GENERIC_SLIDER_ICON": "滑块图标", "GENERIC_SLIDER_TEXT": "滑块文字", "GENERIC_SLIDER_NAME": "输入滑块名称", "SETTINGS_MONITORS_CALIBRATION_DESC": "每台显示器可以添加单独的校准点来补偿亮度曲线的差异。输入值是滑块上指示的亮度级别,而输出值是实际应用于显示器的亮度级别。", "SETTINGS_FEATURES_LINKED_TO_BRIGHTNESS": "与亮度绑定", "SETTINGS_FEATURES_STOP_ON_BRIGHTNESS": "停止于此亮度级别", "SETTINGS_FEATURES_BRIGHTNESS_VCP_INFO": "如果您的显示器使用非标准的 VCP 亮度代码(例如 0x13 或 0x6B),或者您希望将亮度滑块重新映射到不同的 VCP 代码,您可以在下方输入该代码。", "SETTINGS_FEATURES_BRIGHTNESS_VCP_DESC": "留空为默认值(0x10)。在下方列表中查找支持的代码。", "GENERIC_SLIDER_INDICATOR_TYPE": "滑块指示器类型" } ================================================ FILE: src/modules/acrylic/.gitignore ================================================ node_modules *.log* build .vscode/ipch .history ================================================ FILE: src/modules/acrylic/acrylic.cc ================================================ #include #include enum AccentState { ACCENT_DISABLED = 0, ACCENT_ENABLE_GRADIENT = 1, ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, ACCENT_ENABLE_BLURBEHIND = 3, ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, ACCENT_ENABLE_HOSTBACKDROP = 5, // RS5 1809 ACCENT_INVALID_STATE = 6 }; enum WindowCompositionAttribute { WCA_ACCENT_POLICY = 19 }; struct AccentPolicy { AccentState accentState; int accentFlags; int gradientColor; int animationId; }; struct WindowCompositionAttributeData { WindowCompositionAttribute attribute; PVOID pData; ULONG dataSize; }; typedef BOOL(WINAPI *pSetWindowCompositionAttribute)(HWND, WindowCompositionAttributeData*); const HINSTANCE hModule = LoadLibrary(TEXT("user32.dll")); void setAcrylic(const Napi::CallbackInfo &info) { Napi::Env env = info.Env(); try { if (info.Length() == 0) { Napi::TypeError::New(env, "WINDOW_NOT_GIVEN").ThrowAsJavaScriptException(); return; } if (info.Length() != 6) { Napi::TypeError::New(env, "PARAMETER_ERROR").ThrowAsJavaScriptException(); return; } if (!info[0].IsNumber()) { Napi::TypeError::New(env, "UNKNOWN").ThrowAsJavaScriptException(); return; } HWND hWnd = (HWND) info[0].As().Int64Value(); int isRS4OrGreater = info[1].As().Int32Value(); int redValue = info[2].As().Int32Value(); int greenValue = info[3].As().Int32Value(); int blueValue = info[4].As().Int32Value(); int alphaValue = info[5].As().Int32Value(); if (hModule) { const pSetWindowCompositionAttribute SetWindowCompositionAttribute = (pSetWindowCompositionAttribute) GetProcAddress( hModule, "SetWindowCompositionAttribute"); if (SetWindowCompositionAttribute) { int gradientColor = (alphaValue<<24) + (blueValue<<16) + (greenValue<<8) + (redValue); AccentState blurType = isRS4OrGreater == 1 ? ACCENT_ENABLE_ACRYLICBLURBEHIND : ACCENT_ENABLE_BLURBEHIND; AccentPolicy policy = {blurType, 2, gradientColor, 0}; WindowCompositionAttributeData data = {WCA_ACCENT_POLICY, &policy, sizeof(AccentPolicy)}; SetWindowCompositionAttribute(hWnd, &data); } else { Napi::Error::New(env, "FAIL_LOAD_DLL").ThrowAsJavaScriptException(); return; } FreeLibrary(hModule); } else { Napi::Error::New(env, "FAIL_LOAD_DLL").ThrowAsJavaScriptException(); return; } } catch (const char *ex) { Napi::Error::New(env, "UNKNOWN").ThrowAsJavaScriptException(); } } void disableAcrylic(const Napi::CallbackInfo &info) { Napi::Env env = info.Env(); try { if (info.Length() != 1) { Napi::TypeError::New(env, "WINDOW_NOT_GIVEN").ThrowAsJavaScriptException(); return; } if (!info[0].IsNumber()) { Napi::TypeError::New(env, "UNKNOWN").ThrowAsJavaScriptException(); return; } HWND hWnd = (HWND) info[0].As().Int64Value(); if (hModule) { const pSetWindowCompositionAttribute SetWindowCompositionAttribute = (pSetWindowCompositionAttribute) GetProcAddress( hModule, "SetWindowCompositionAttribute"); if (SetWindowCompositionAttribute) { AccentPolicy policy = {ACCENT_DISABLED, 0, 0, 0}; WindowCompositionAttributeData data = {WCA_ACCENT_POLICY, &policy, sizeof(AccentPolicy)}; SetWindowCompositionAttribute(hWnd, &data); } else { Napi::Error::New(env, "FAIL_LOAD_DLL").ThrowAsJavaScriptException(); return; } FreeLibrary(hModule); } else { Napi::Error::New(env, "FAIL_LOAD_DLL").ThrowAsJavaScriptException(); return; } } catch (const char *ex) { Napi::Error::New(env, "UNKNOWN").ThrowAsJavaScriptException(); } } Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set(Napi::String::New(env, "setAcrylic"), Napi::Function::New(env, setAcrylic)); exports.Set(Napi::String::New(env, "disableAcrylic"), Napi::Function::New(env, disableAcrylic)); return exports; } NODE_API_MODULE(acrylic, Init) ================================================ FILE: src/modules/acrylic/binding.gyp ================================================ { "targets": [ { "target_name": "acrylic", "cflags!": [ "-fno-exceptions" ], "cflags_cc!": [ "-fno-exceptions" ], "conditions": [ ["OS=='win'", { "sources": [ "acrylic.cc" ] }], ], "include_dirs": [ " Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: src/modules/node-active-window/README.md ================================================ # Node Active Window [![NPM](https://img.shields.io/npm/v/@paymoapp/active-window)](https://www.npmjs.com/package/@paymoapp/active-window) [![Typescript](https://img.shields.io/npm/types/@paymoapp/active-window)](https://www.npmjs.com/package/@paymoapp/active-window) [![N-API](https://raw.githubusercontent.com/nodejs/abi-stable-node/doc/assets/Node-API%20v6%20Badge.svg)](https://github.com/nodejs/node-addon-api) [![License](https://img.shields.io/github/license/paymoapp/node-active-window)](https://www.gnu.org/licenses/gpl-3.0.txt) NodeJS library using native modules to get the active window and some metadata (including the application icon) on Windows, MacOS and Linux. ### Table of Contents - [Getting started](#getting-started) - [Installation](#installation) - [Native addon](#native-addon) - [Example](#example) - [API](#api) - [Data structures](#data-structures) - [Functions](#functions) - [Native libraries](#native-libraries) - [Linux (`module/linux`)](#linux-modulelinux) - [Data structures](#data-structures-1) - [Public functions](#public-functions) - [Example](#example-1) - [Building](#building) - [Windows (`module/windows`)](#windows-modulewindows) - [Data structures](#data-structures-2) - [Public functions](#public-functions-1) - [Example](#example-2) - [Building](#building-1) - [MacOS (`module/macos`)](#macos-modulemacos) - [Data structures](#data-structures-3) - [Public functions](#public-functions-2) - [Example](#example-3) - [Building](#building-2) ## Getting started #### Installation ```bash npm install --save @paymoapp/active-window ``` #### Native addon This project uses NodeJS Native Addons to function, so you can use this library in any NodeJS or Electron project, there won't be any problem with bundling and code signing. The project uses [prebuild](https://github.com/prebuild/prebuild) to supply prebuilt libraries. The project uses Node-API version 6, you can check [this table](https://nodejs.org/api/n-api.html#node-api-version-matrix) to see which node versions are supported. If there's a compliant prebuilt binary, it will be downloaded during installation, or it will be built. You can also rebuild it anytime by running `npm run build:gyp`. The library has native addons for all the three major operating systems: Windows, MacOS and Linux. For Linux, only the X11 windowing system is supported. #### Example You can run a demo application by calling `npm run demo`. You can browse it's source code for a detailed example using the watch API in `demo/index.ts`. ```ts import ActiveWindow from '@paymoapp/active-window'; ActiveWindow.initialize(); if (!ActiveWindow.requestPermissions()) { console.log('Error: You need to grant screen recording permission in System Preferences > Security & Privacy > Privacy > Screen Recording'); process.exit(0); } const activeWin = ActiveWindow.getActiveWindow(); console.log('Window title:', activeWin.title); console.log('Application:', activeWin.application); console.log('Application path:', activeWin.path); console.log('Application PID:', activeWin.pid); console.log('Application icon:', activeWin.icon); ``` ## API #### Data structures ###### 🗃    WindowInfo ```ts interface WindowInfo { title: string; application: string; path: string; pid: number; icon: string; windows?: { isUWPApp: boolean; uwpPackage: string; }; } ``` This is the only object you will receive when interacting with this library. It contains information about the currently active window: - `title` - The title of the current window - `application` - The name of the application. On Windows you should use the `uwpPackage` parameter instead if `isUWPApp` is set to true - `path` - The path to the application's executable - `pid` - Process identifier of the application - `icon` - Base64 encoded string representing the application icon - `windows` - Object containing Windows platform specific information, undefined on other platforms - `windows.isUWPApp` - Set to `true` if the active window is owned by an [Universal Windows Platform](https://docs.microsoft.com/en-us/windows/uwp/get-started/universal-application-platform-guide) application - `windows.uwpPackage` - Contains the package family name of the UWP application None of the parameters are nullable, even if their value couldn't be fetched, they will be either be set to an empty string (for the string values), -1 (for the numeric values) or false (for the boolean values). #### Functions ###### 𝑓    getActiveWindow ```ts interface IActiveWindow { getActiveWindow(): WindowInfo // ... } ``` Requests the current foreground window in a synchronous way. It will throw an error if the current window couldn't be fetched (for example there're no focused windows at the moment). ###### 𝑓    subscribe ```ts interface IActiveWindow { subscribe(callback: (windowInfo: WindowInfo | null) => void): number; // ... } ``` Subscribe to changes of the active window. The supplied callback will be called with `null` if there're no focused windows at the moment. The function returns a number representing the ID of the watch. You should store this value to remove the event listener later on. ###### 𝑓    unsubscribe ```ts interface IActiveWindow { unsubscribe(watchId: number): void; // ... } ``` Remove the event listener associated with the supplied watch ID. Use this to unsubscribe from the active window changed events. ###### 𝑓    initialize ```ts interface IActiveWindow { initialize(opts?: { osxRunLoop: boolean }): void; // ... } ``` On some platforms (Linux) the library needs some initialization to be done. You must call this function before doing anything with the library regardless of the current platform. If you're not using this library in a GUI application there might be no runloop running for the main thread. In this case you should set the `osxRunLoop` property to true if you want to use subscriptions. ###### 𝑓    requestPermissions ```ts interface IActiveWindow { requestPermissions(): boolean; // ... } ``` On the MacOS platform you need to request screen recording permission to fetch the title of the current window. The function will return `true` if the permission is granted and `false` if the permission is denied. This is a non-blocking function, so you will only get the momentary status. You can call this function regardless of the current platform. On unsupported platforms it will simply return `true`. When the function is called, the user will be presented with a system modal with instructions to grant the permission. You should include these instructions in your application as well, since this is a one-time modal. After the user grants the permission, it is required to relaunch the application for the changes to take effect. If the user fails to grant the required permissions, the `title` property of the returned `WindowInfo` will be an empty string. ## Native libraries You can import the each platform dependent library as a standalone C++ / Objective-C++ library. You can find the library itself in the module's `src` directory. The `napi` directory contains the Node-API bindings and the `demo` directory contains a small demo program that can be built using a Makefile. You can build the demo by navigating to the `module//demo` folder and executing `make`. You can run the demo using `make run` and clean the build artifacts using `make clean`. The demo has 4 running modes: - _default_: `make run` - in this mode the library is used to fetch the current window details, then there's a 3 second delay after which the current window is fetched again - _loop_: `make run MODE=loop` - in this mode the library is used the poll the current window in every 3 seconds until SIGINT (Ctrl+C) is received - _watch_: `make run MODE=watch` - in this mode the library is used to watch the current window and it's title. There's no polling involved in this mode - _benchmark_: `make run MODE=benchmark` - in this mode the library will fetch the current window details 100.000 times (or 10.000 times on windows) and it will print the total of the consumed CPU seconds while doing so ### Linux (`module/linux`) #### Data structures ###### 🗃    WindowInfo ```c++ struct WindowInfo { std::string title; // UTF8 encoded string of window title. Empty string if couldn't fetch std::string application; // UTF8 encoded string of application name. Empty string if couldn't fetch std::string path; // UTF8 encoded string of application path. Empty string if couldn't fetch int pid; // PID of process. -1 if couldn't fetch std::string icon; // base64 encoded PNG icon. Empty string if couldn't fetch } ``` ###### 🗃    watch_t ```c++ typedef unsigned int watch_t; ``` ###### 🗃    watch_callback ```c++ typedef std::function watch_callback; ``` #### Public functions ###### 𝑓    Constructor ```c++ ActiveWindow(unsigned int iconCacheSize = 0); ``` If you pass iconCacheSize > 0, then an LRU (least recently used) cache will be instantiated which will cache the fetched icons. This results in about 90% less CPU seconds consumed. You can use the benchmark mode of the demo to test it yourself. You should pass a cache size suitable for your application. A bigger cache results in a greater memory consumption, but it also reduces the CPU utilization if your user switches across a large set of applications. ###### 𝑓    getActiveWindow ```c++ WindowInfo* getActiveWindow(); ``` Returns pointer to WindowInfo containing the gathered information about the current window. The pointer can be `NULL` in the case of an error or if there is no active window (ex: all the windows are minified). You should free up the allocated WindowInfo object using `delete`. ###### 𝑓    buildAppCache ```c++ void buildAppCache(); ``` Gathers all the `.desktop` entries available on the system (starting from `~/.local/share/applications` through each `$XDG_DATA_DIRS/applications`) and resolves the icon path for them. This cache is used to get the icon for a given window. If this function is not called, then no icons will be resolved. ###### 𝑓    watchActiveWindow ```c++ watch_t watchActiveWindow(watch_callback cb); ``` Sets up a watch for the active window. If there's a change in the current active window, or the title of the active window, the callback will be fired with the current active window. You don't need to call `getActiveWindow()` in the callback, you can use the supplied parameter. This method will also start a background watch thread if it's not already running. Please note that the callbacks will be executed on this thread, so you should assure thread safety. You __MUST NOT__ free up the WindowInfo object received in the parameter. If you need to store the active window you __SHOULD__ make a copy of it, since the WindowInfo object will be freed after calling all the callbacks. You should save the returned watch ID to unsubscribe later. ###### 𝑓    unwatchActiveWindow ```c++ void unwatchActiveWindow(watch_t watch); ``` Removes the watch associated with the supplied watch ID. The background watch thread will not be closed, even if there're no more watches left. It will only be closed when the class's destructor is called. #### Example See `module/linux/demo/main.cpp` for an example. ```c++ #include #include "ActiveWindow.h" using namespace std; using namespace PaymoActiveWindow; int main() { ActiveWindow* activeWindow = new ActiveWindow(10); WindowInfo* windowInfo = activeWindow->getActiveWindow(); if (windowInfo == NULL) { cout<<"Could not get active window\n"; } else { cout<<"Title: "<title<<"\n"; cout<<"Application: "<application<<"\n"; cout<<"Executable path: "<path<<"\n"; cout<<"PID: "<pid<<"\n"; cout<<"Icon: "<icon<<"\n"; } delete windowInfo; delete activeWindow; return 0; } ``` #### Building See `module/linux/demo/Makefile` for a sample makefile. You need to check the `lib` target. You should use C++17 for building and you need to link the following libraries: - X11 (`-lX11`) - libx11-dev - PThread (`-lpthread`) - libpthread-stubs0-dev ### Windows (`module/windows`) #### Data structures ###### 🗃    WindowInfo ```c++ struct WindowInfo { std::wstring title = L""; // UTF16 encoded string of window title. Empty string if couldn't fetch std::wstring application = L""; // UTF16 encoded string of application. Empty string if couldn't fetch std::wstring path = L""; // UTF16 encoded string of executable path. Empty string if couldn't fetch unsigned int pid = 0; // Process PID bool isUWPApp = false; // if application is detected to be an Universal Windows Platform application std::wstring uwpPackage = L""; // UTF16 encoded string of the UWP package name. Empty string if couldn't fetch std::string icon = ""; // base64 encoded icon. Empty string if couldn't fetch }; ``` ###### 🗃    watch_t ```c++ typedef unsigned int watch_t; ``` ###### 🗃    watch_callback ```c++ typedef std::function watch_callback; ``` #### Public functions ###### 𝑓    Constructor ```c++ ActiveWindow(unsigned int iconCacheSize = 0); ``` If you pass iconCacheSize > 0, then an LRU (least recently used) cache will be instantiated which will cache the fetched icons. This results in about 90% less CPU seconds consumed. You can use the benchmark mode of the demo to test it yourself. You should pass a cache size suitable for your application. A bigger cache results in a greater memory consumption, but it also reduces the CPU utilization if your user switches across a large set of applications. ###### 𝑓    getActiveWindow ```c++ WindowInfo* getActiveWindow(); ``` Returns pointer to WindowInfo containing the gathered information about the current window. The pointer can be `NULL` in the case of an error or if there is no active window (ex: all the windows are minified or the desktop is selected). You should free up the allocated WindowInfo object using `delete`. ###### 𝑓    watchActiveWindow ```c++ watch_t watchActiveWindow(watch_callback cb); ``` Sets up a watch for the active window. If there's a change in the current active window, or the title of the active window, the callback will be fired with the current active window. You don't need to call `getActiveWindow()` in the callback, you can use the supplied parameter. This method will also start a background watch thread if it's not already running. Please note that the callbacks will be executed on this thread, so you should assure thread safety. You __MUST NOT__ free up the WindowInfo object received in the parameter. If you need to store the active window you __SHOULD__ make a copy of it, since the WindowInfo object will be freed after calling all the callbacks. You should save the returned watch ID to unsubscribe later. ###### 𝑓    unwatchActiveWindow ```c++ void unwatchActiveWindow(watch_t watch); ``` Removes the watch associated with the supplied watch ID. The background watch thread will not be closed, even if there're no more watches left. It will only be closed when the class's destructor is called. #### Example See `module/windows/demo/main.cpp` for an example. ```c++ #include #include "ActiveWindow.h" using namespace std; using namespace PaymoActiveWindow; int main() { ActiveWindow* activeWindow = new ActiveWindow(10); WindowInfo* windowInfo = activeWindow->getActiveWindow(); if (windowInfo == NULL) { cout<<"Could not get active window\n"; } else { wcout<title<<"\n"; wcout<application<<"\n"; wcout<path<<"\n"; cout<<"PID: "<pid<<"\n"; cout<<"Is UWP application: "<<(windowInfo->isUWPApp ? "Yes" : "No")<<"\n"; if (windowInfo->isUWPApp) { wcout<<"UWP package name: "<uwpPackage<<"\n"; } cout<<"Icon: "<icon<<"\n"; } delete windowInfo; delete activeWindow; return 0; } ``` #### Building See `module/windows/demo/Makefile` for a sample makefile. You need to check the `lib` target. This is not a GNU makefile, it should be used with Microsoft's NMAKE. To prepare your environment, you need run the `vcvarsall.bat` batch script. If you checked the _install windows build tools_ box during the installation of NodeJS, you should find this file in the following location: `C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat`. So to gain access to the `nmake`, `cl` and `link` commands, execute this: ```batch "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" x64 ``` You should use C++17 for building and you need to link the following libraries: - User32.lib - Shell32.lib - Version.lib - Shlwapi.lib - Gdi32.lib - Gdiplus.lib - Windowsapp.lib ### MacOS (`module/macos`) #### Data structures ###### 🗃    WindowInfo ```c++ struct WindowInfo { std::string title; // UTF8 encoded string of window title. Empty string if couldn't fetch std::string application; // UTF8 encoded string of application name std::string path; // UTF8 encoded string of application path int pid; // PID of process std::string icon; // base64 encoded PNG icon } ``` ###### 🗃    watch_t ```c++ typedef unsigned int watch_t; ``` ###### 🗃    watch_callback ```c++ typedef std::function watch_callback; ``` #### Public functions ###### 𝑓    Constructor ```c++ ActiveWindow(unsigned int iconCacheSize = 0); ``` If you pass iconCacheSize > 0, then an LRU (least recently used) cache will be instantiated which will cache the fetched icons. This results in about 40% less CPU seconds consumed. You can use the benchmark mode of the demo to test it yourself. You should pass a cache size suitable for your application. A bigger cache results in a greater memory consumption, but it also reduces the CPU utilization if your user switches across a large set of applications. ###### 𝑓    getActiveWindow ```c++ WindowInfo* getActiveWindow(); ``` Returns pointer to WindowInfo containing the gathered information about the current window. The pointer can be `NULL` in the case of an error or if there is no active window (ex: all the windows are minified). You should free up the allocated WindowInfo object using `delete`. ###### 𝑓    requestScreenCaptureAccess ```c++ bool requestScreenCaptureAccess(); ``` To access the title of the window the process requires the screen capture permission. To check it and request it you need to call this function. This function is non-blocking and will immediately return with the current status (false - permission denied, true - permission granted). The first time this function is called there will be a system popup instructing the user how he can grant this permission, but you should also include this information in your application, since it's a one-time popup that closes when you click outside of it. The application needs to be relaunched after granting the permission. ###### 𝑓    watchActiveWindow ```c++ watch_t watchActiveWindow(watch_callback cb); ``` Sets up a watch for the active window. If there's a change in the current active window, the callback will be fired with the current active window. You don't need to call `getActiveWindow()` in the callback, you can use the supplied parameter. This method will use the observer set up on the main thread to listen to the events, so the main thread has to have a running NSRunLoop. If you integrate this library into a desktop application, then this should already be resolved. Otherwise (for example when using a console application), you have to manually run the RunLoop or call the `runLoop()` helper function which will block for 0.1ms. If you want to use the watch function, you __MUST__ use this library on the main thread, since the NSWorkspace notifications are only serviced on that thread. The callbacks are also executed on the main thread, so you shouldn't do anything blocking in them. You should save the returned watch ID to unsubscribe later. ###### 𝑓    unwatchActiveWindow ```c++ void unwatchActiveWindow(watch_t watch); ``` Removes the watch associated with the supplied watch ID. ###### 𝑓    runLoop ```c++ void runLoop(); ``` A helper function which will run the thread's RunLoop for 0.1ms or until the first event is handled. This function should be called on the main thread. You should only use this function only if you don't have a running RunLoop on your main thread. #### Example See `module/macos/demo/main.mm` for an example. ```c++ #include #include "ActiveWindow.h" using namespace std; using namespace PaymoActiveWindow; int main() { ActiveWindow* activeWindow = new ActiveWindow(); WindowInfo* windowInfo = activeWindow->getActiveWindow(); if (windowInfo == NULL) { cout<<"Could not get active window\n"; } else { cout<<"Title: "<title<<"\n"; cout<<"Application: "<application<<"\n"; cout<<"Executable path: "<path<<"\n"; cout<<"PID: "<pid<<"\n"; cout<<"Icon: "<icon<<"\n"; } delete windowInfo; delete activeWindow; return 0; } ``` #### Building See `module/macos/demo/Makefile` for a sample makefile. You need to check the `lib` target. You should use C++17 for building and you need to link the following libraries: - `-lc++` - `-framework Foundation` - `-framework AppKit` - `-framework ApplicationServices` ================================================ FILE: src/modules/node-active-window/binding.gyp ================================================ { "targets": [ { "target_name": "PaymoActiveWindow", "conditions": [ ["OS=='win'", { "sources": [ "module/windows/napi/main.cpp", "module/windows/napi/module.cpp", "module/windows/src/ActiveWindow.cpp" ], "libraries": [ "User32.lib", "Shell32.lib", "Version.lib", "Shlwapi.lib", "Windowsapp.lib" ], "msvs_settings": { "VCCLCompilerTool": { "AdditionalOptions": [ "/std:c++17" ] } } }] ], "include_dirs": [ " { return Object.assign({ title: info.title, application: info.application, path: info.path, pid: info.pid, icon: info.icon }, (process.platform == 'win32' ? { windows: { isUWPApp: info['windows.isUWPApp'] || false, uwpPackage: info['windows.uwpPackage'] || '' } } : {})); }; const ActiveWindow = { getActiveWindow: () => { if (!addon) { throw new Error('Failed to load native addon'); } const info = addon.getActiveWindow(); return encodeWindowInfo(info); }, subscribe: (callback) => { if (!addon) { throw new Error('Failed to load native addon'); } const watchId = addon.subscribe(nativeWindowInfo => { callback(!nativeWindowInfo ? null : encodeWindowInfo(nativeWindowInfo)); }); return watchId; }, unsubscribe: (watchId) => { if (!addon) { throw new Error('Failed to load native addon'); } if (watchId < 0) { throw new Error('Watch ID must be a positive number'); } addon.unsubscribe(watchId); }, initialize: ({ osxRunLoop } = {}) => { if (!addon) { throw new Error('Failed to load native addon'); } if (addon.initialize) { addon.initialize(); } // set up runloop on MacOS if (process.platform == 'darwin' && osxRunLoop) { const interval = setInterval(() => { if (addon && addon.runLoop) { addon.runLoop(); } else { clearInterval(interval); } }, 100); } }, requestPermissions: () => { if (!addon) { throw new Error('Failed to load native addon'); } if (addon.requestPermissions) { return addon.requestPermissions(); } return true; } }; __exportStar(require("./types"), exports); exports.default = ActiveWindow; ================================================ FILE: src/modules/node-active-window/dist/types.d.ts ================================================ export interface NativeWindowInfo { title: string; application: string; path: string; pid: number; icon: string; 'windows.isUWPApp'?: boolean; 'windows.uwpPackage'?: string; } export interface WindowInfo { title: string; application: string; path: string; pid: number; icon: string; windows?: { isUWPApp: boolean; uwpPackage: string; }; } export interface Module { getActiveWindow(): T; subscribe(callback: (windowInfo: T | null) => void): number; unsubscribe(watchId: number): void; initialize?(): void; requestPermissions?(): boolean; runLoop?(): void; } export interface InitializeOptions { osxRunLoop?: boolean; } export interface IActiveWindow extends Omit, 'runLoop'> { initialize(opts?: InitializeOptions): void; requestPermissions(): boolean; } ================================================ FILE: src/modules/node-active-window/dist/types.js ================================================ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); ================================================ FILE: src/modules/node-active-window/module/windows/demo/Makefile ================================================ LIBDIR=..\src BUILDDIR=build CLFLAGS=/std:c++17 LIBS=User32.lib Shell32.lib Version.lib Shlwapi.lib Gdiplus.lib Gdi32.lib Windowsapp.lib all: create_dir demo demo: $(BUILDDIR)\demo.exe $(BUILDDIR)\demo.exe: $(BUILDDIR)\ActiveWindow.obj $(BUILDDIR)\IconCache.obj $(BUILDDIR)\base64.obj $(BUILDDIR)\GdiPlusUtils.obj $(BUILDDIR)\main.obj @echo Linking demo.exe link /out:$(BUILDDIR)\demo.exe $(BUILDDIR)\*.obj $(LIBS) $(BUILDDIR)\main.obj: main.cpp @echo Building main.cpp for demo cl /c /EHsc $(CLFLAGS) /Fo$(BUILDDIR)\ main.cpp $(BUILDDIR)\ActiveWindow.obj: $(LIBDIR)\ActiveWindow.cpp $(LIBDIR)\ActiveWindow.h @echo Building $(LIBDIR)\ActiveWindow.cpp cl /c /EHsc $(CLFLAGS) /Fo$(BUILDDIR)\ $(LIBDIR)\ActiveWindow.cpp $(BUILDDIR)\IconCache.obj: $(LIBDIR)\IconCache.cpp $(LIBDIR)\IconCache.h @echo Building $(LIBDIR)\IconCache.cpp cl /c /EHsc $(CLFLAGS) /Fo$(BUILDDIR)\ $(LIBDIR)\IconCache.cpp $(BUILDDIR)\GdiPlusUtils.obj: $(LIBDIR)\GdiPlusUtils.cpp $(LIBDIR)\GdiPlusUtils.h @echo Building $(LIBDIR)\GdiPlusUtils.cpp cl /c /EHsc $(CLFLAGS) /Fo$(BUILDDIR)\ $(LIBDIR)\GdiPlusUtils.cpp $(BUILDDIR)\base64.obj: $(LIBDIR)\base64\base64.cpp $(LIBDIR)\base64\base64.h @echo Building $(LIBDIR)\base64\base64.cpp cl /c /EHsc $(CLFLAGS) /Fo$(BUILDDIR)\ $(LIBDIR)\base64\base64.cpp create_dir: @if not exist $(BUILDDIR) mkdir $(BUILDDIR) clean: @if exist $(BUILDDIR) rmdir /s /q $(BUILDDIR) run: $(BUILDDIR)\demo.exe $(MODE) ================================================ FILE: src/modules/node-active-window/module/windows/demo/main.cpp ================================================ #include "../src/ActiveWindow.h" #include #include #include #include void printWindowInfo(PaymoActiveWindow::WindowInfo* inf) { std::wcout<title<application<path<pid<<"\""<isUWPApp ? "true" : "false")<uwpPackage<icon<getActiveWindow(); if (inf == NULL) { std::cout<<"Error: Could not get window info"<watchActiveWindow([](PaymoActiveWindow::WindowInfo* inf) { std::cout<<"[Notif] Active window has changed!\n"; if (inf == NULL) { std::cout<<"Empty"<unwatchActiveWindow(watchId); std::cout<<"Watch removed"<getActiveWindow(); delete inf; } double end = getCpuTime(); std::cout<<"Elapsed CPU seconds: "<<(end - start)< #include "module.h" Napi::Object InitAll(Napi::Env env, Napi::Object exports) { return module::Init(env, exports); } NODE_API_MODULE(NODE_GYP_MODULE_NAME, InitAll); ================================================ FILE: src/modules/node-active-window/module/windows/napi/module.cpp ================================================ #include "module.h" Napi::Object module::Init(Napi::Env env, Napi::Object exports) { env.SetInstanceData(new PaymoActiveWindow::ActiveWindow(0)); exports.Set("getActiveWindow", Napi::Function::New(env, module::getActiveWindow)); exports.Set("subscribe", Napi::Function::New(env, module::subscribe)); exports.Set("unsubscribe", Napi::Function::New(env, module::unsubscribe)); return exports; } Napi::Object module::getActiveWindow(const Napi::CallbackInfo& info) { PaymoActiveWindow::ActiveWindow* activeWindow = info.Env().GetInstanceData(); if (activeWindow == NULL) { Napi::Error::New(info.Env(), "ActiveWindow module not initialized").ThrowAsJavaScriptException(); return Napi::Object::Object(); } PaymoActiveWindow::WindowInfo* windowInfo = activeWindow->getActiveWindow(); if (windowInfo == NULL) { Napi::Error::New(info.Env(), "Failed to get active window").ThrowAsJavaScriptException(); return Napi::Object::Object(); } Napi::Object result = module::encodeWindowInfo(info.Env(), windowInfo); delete windowInfo; return result; } Napi::Number module::subscribe(const Napi::CallbackInfo& info) { PaymoActiveWindow::ActiveWindow* activeWindow = info.Env().GetInstanceData(); if (activeWindow == NULL) { Napi::Error::New(info.Env(), "ActiveWindow module not initialized").ThrowAsJavaScriptException(); return Napi::Number::New(info.Env(), -1); } if (info.Length() != 1) { Napi::TypeError::New(info.Env(), "Expected 1 argument").ThrowAsJavaScriptException(); return Napi::Number::New(info.Env(), -1); } if (!info[0].IsFunction()) { Napi::TypeError::New(info.Env(), "Expected first argument to be function").ThrowAsJavaScriptException(); return Napi::Number::New(info.Env(), -1); } Napi::ThreadSafeFunction tsfn = Napi::ThreadSafeFunction::New(info.Env(), info[0].As(), "Active Window Callback", 0, 2); auto mainThreadCallback = [](Napi::Env env, Napi::Function jsCallback, PaymoActiveWindow::WindowInfo* windowInfo) { if (windowInfo == NULL) { jsCallback.Call({ env.Null() }); } else { jsCallback.Call({ module::encodeWindowInfo(env, windowInfo) }); delete windowInfo; } }; PaymoActiveWindow::watch_t watchId = activeWindow->watchActiveWindow([tsfn, mainThreadCallback](PaymoActiveWindow::WindowInfo* windowInfo) { if (windowInfo == NULL) { tsfn.BlockingCall((PaymoActiveWindow::WindowInfo*)NULL, mainThreadCallback); return; } // clone window info PaymoActiveWindow::WindowInfo* arg = new PaymoActiveWindow::WindowInfo(); *arg = *windowInfo; tsfn.BlockingCall(arg, mainThreadCallback); }); return Napi::Number::New(info.Env(), watchId); } void module::unsubscribe(const Napi::CallbackInfo& info) { PaymoActiveWindow::ActiveWindow* activeWindow = info.Env().GetInstanceData(); if (activeWindow == NULL) { Napi::Error::New(info.Env(), "ActiveWindow module not initialized").ThrowAsJavaScriptException(); return; } if (info.Length() != 1) { Napi::TypeError::New(info.Env(), "Expected 1 argument").ThrowAsJavaScriptException(); return; } if (!info[0].IsNumber()) { Napi::TypeError::New(info.Env(), "Expected first argument to be number").ThrowAsJavaScriptException(); return; } PaymoActiveWindow::watch_t watchId = info[0].As().Uint32Value(); activeWindow->unwatchActiveWindow(watchId); } Napi::Object module::encodeWindowInfo(Napi::Env env, PaymoActiveWindow::WindowInfo* windowInfo) { Napi::Object result = Napi::Object::New(env); result.Set("title", Napi::String::New(env, std::u16string(windowInfo->title.begin(), windowInfo->title.end()))); result.Set("application", Napi::String::New(env, std::u16string(windowInfo->application.begin(), windowInfo->application.end()))); result.Set("path", Napi::String::New(env, std::u16string(windowInfo->path.begin(), windowInfo->path.end()))); result.Set("pid", Napi::Number::New(env, windowInfo->pid)); result.Set("windows.isUWPApp", Napi::Boolean::New(env, windowInfo->isUWPApp)); result.Set("windows.uwpPackage", Napi::String::New(env, std::u16string(windowInfo->uwpPackage.begin(), windowInfo->uwpPackage.end()))); result.Set("icon", Napi::String::New(env, windowInfo->icon)); return result; } ================================================ FILE: src/modules/node-active-window/module/windows/napi/module.h ================================================ #include #include #include "../src/ActiveWindow.h" #ifndef _PAYMO_MODULE_H #define _PAYMO_MODULE_H namespace module { Napi::Object Init(Napi::Env env, Napi::Object exports); Napi::Object getActiveWindow(const Napi::CallbackInfo& info); Napi::Number subscribe(const Napi::CallbackInfo& info); void unsubscribe(const Napi::CallbackInfo& info); // helpers Napi::Object encodeWindowInfo(Napi::Env env, PaymoActiveWindow::WindowInfo* windowInfo); } #endif ================================================ FILE: src/modules/node-active-window/module/windows/src/ActiveWindow.cpp ================================================ #include "ActiveWindow.h" namespace PaymoActiveWindow { std::mutex ActiveWindow::smutex; std::unordered_map ActiveWindow::winEventProcCbCtx; ActiveWindow::ActiveWindow(unsigned int iconCacheSize) { } ActiveWindow::~ActiveWindow() { // stop watch thread if (this->watchThread != NULL) { this->threadShouldExit.store(true, std::memory_order_relaxed); this->watchThread->join(); delete this->watchThread; this->watchThread = NULL; } // tear down COM CoUninitialize(); } WindowInfo* ActiveWindow::getActiveWindow() { HWND h = GetForegroundWindow(); if (h == NULL) { return NULL; } WindowInfo* info = new WindowInfo(); // get window title info->title = this->getWindowTitle(h); // get process pid DWORD pid; GetWindowThreadProcessId(h, &pid); info->pid = (unsigned int)pid; // get process handle HANDLE hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid); if (hProc == NULL) { delete info; return NULL; } // get app path info->path = this->getProcessPath(hProc); CloseHandle(hProc); // check if app is UWP app if (this->isUWPApp(info->path)) { info->isUWPApp = true; EnumChildWindowsCbParam* cbParam = new EnumChildWindowsCbParam(this); EnumChildWindows(h, EnumChildWindowsCb, (LPARAM)cbParam); if (!cbParam->ok) { delete cbParam; delete info; return NULL; } info->path = cbParam->path; // save handle of UWP process hProc = cbParam->hProc; delete cbParam; } // get app name info->application = this->getProcessName(info->path); if (info->application.size() == 0) { info->application = this->basename(info->path); } if (info->isUWPApp) { info->uwpPackage = this->getUWPPackage(hProc); // we need to close the handle of the UWP process CloseHandle(hProc); } return info; } watch_t ActiveWindow::watchActiveWindow(watch_callback cb) { watch_t watchId = this->nextWatchId++; this->mutex.lock(); this->watches[watchId] = cb; this->mutex.unlock(); // register hook if not registered if (this->watchThread == NULL) { this->threadShouldExit.store(false, std::memory_order_relaxed); this->watchThread = new std::thread(&ActiveWindow::runWatchThread, this); } return watchId; } void ActiveWindow::unwatchActiveWindow(watch_t watch) { this->mutex.lock(); this->watches.erase(watch); this->mutex.unlock(); } std::wstring ActiveWindow::getWindowTitle(HWND hWindow) { int len = GetWindowTextLengthW(hWindow); if(!len) { return L""; } std::vector buf(len + 1); if (!GetWindowTextW(hWindow, buf.data(), len + 1)) { return L""; } std::wstring title(buf.begin(), buf.begin() + len); return title; } std::wstring ActiveWindow::getProcessPath(HANDLE hProc) { std::vector buf(MAX_PATH); DWORD len = MAX_PATH; if (!QueryFullProcessImageNameW(hProc, 0, buf.data(), &len)) { return L""; } std::wstring name(buf.begin(), buf.begin() + len); return name; } std::wstring ActiveWindow::getProcessName(std::wstring path) { DWORD infoSize = GetFileVersionInfoSizeW(path.c_str(), NULL); if (!infoSize) { return L""; } LPBYTE data = new BYTE[infoSize]; if (!GetFileVersionInfoW(path.c_str(), 0, infoSize, data)) { delete data; return L""; } struct LANGCODEPAGE { WORD lang; WORD codePage; } *langData, active; active.lang = 0x0409; active.codePage = 0x04E4; UINT langDataLen = 0; if (VerQueryValueW(data, L"\\VarFileInfo\\Translation", (void**)&langData, &langDataLen)) { if (langDataLen) { active.lang = langData[0].lang; active.codePage = langData[0].codePage; } } // build path to query file description std::wstringstream localePath; std::ios_base::fmtflags flags(localePath.flags()); localePath< buf(len); if (GetPackageFamilyName(hProc, &len, buf.data()) != ERROR_SUCCESS) { return L""; } std::wstring package(buf.begin(), buf.begin() + len - 1); return package; } std::wstring ActiveWindow::basename(std::wstring path) { size_t lastSlash = path.find_last_of(L"\\"); if (lastSlash == std::string::npos) { return path; } return path.substr(lastSlash + 1); } bool ActiveWindow::isUWPApp(std::wstring path) { return this->basename(path) == L"ApplicationFrameHost.exe"; } std::wstring ActiveWindow::getUWPPackagePath(HANDLE hProc) { UINT32 pkgIdLen = 0; GetPackageId(hProc, &pkgIdLen, NULL); BYTE* pkgId = new BYTE[pkgIdLen]; GetPackageId(hProc, &pkgIdLen, pkgId); UINT32 len = 0; GetPackagePath((PACKAGE_ID*)pkgId, 0, &len, NULL); std::vector buf(len); if (GetPackagePath((PACKAGE_ID*)pkgId, 0, &len, buf.data()) != ERROR_SUCCESS) { delete pkgId; return L""; } std::wstring pkgPath(buf.begin(), buf.begin() + len - 1); delete pkgId; return pkgPath; } IAppxManifestProperties* ActiveWindow::getUWPPackageProperties(std::wstring pkgPath) { IAppxFactory* appxFactory = NULL; if (FAILED(CoCreateInstance(__uuidof(AppxFactory), NULL, CLSCTX_INPROC_SERVER, __uuidof(IAppxFactory), (LPVOID*)&appxFactory))) { return NULL; } IStream* manifestStream; std::wstring manifestPath = pkgPath + L"\\AppxManifest.xml"; if (FAILED(SHCreateStreamOnFileEx(manifestPath.c_str(), STGM_READ | STGM_SHARE_EXCLUSIVE, 0, FALSE, NULL, &manifestStream))) { appxFactory->Release(); return NULL; } IAppxManifestReader* manifestReader = NULL; if (FAILED(appxFactory->CreateManifestReader(manifestStream, &manifestReader))) { appxFactory->Release(); manifestStream->Release(); return NULL; } IAppxManifestProperties* properties = NULL; if (FAILED(manifestReader->GetProperties(&properties))) { appxFactory->Release(); manifestStream->Release(); manifestReader->Release(); return NULL; } appxFactory->Release(); manifestStream->Release(); manifestReader->Release(); return properties; } void ActiveWindow::runWatchThread() { HWINEVENTHOOK hHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_OBJECT_NAMECHANGE, NULL, WinEventProcCb, 0, 0, WINEVENT_OUTOFCONTEXT); // store context for callback ActiveWindow::smutex.lock(); ActiveWindow::winEventProcCbCtx[hHook] = this; ActiveWindow::smutex.unlock(); MSG msg; UINT_PTR timer = SetTimer(NULL, NULL, 500, nullptr); // run message loop at least every 500 ms for (;;) { BOOL getMsgRet = GetMessage(&msg, NULL, 0, 0); if (getMsgRet == -1) { continue; } if (msg.message = WM_TIMER) { // check if we should exit if (this->threadShouldExit.load(std::memory_order_relaxed)) { break; } } TranslateMessage(&msg); DispatchMessage(&msg); } // remove timer KillTimer(NULL, timer); // remove hook UnhookWinEvent(hHook); // remove context ActiveWindow::smutex.lock(); ActiveWindow::winEventProcCbCtx.erase(hHook); ActiveWindow::smutex.unlock(); } BOOL CALLBACK ActiveWindow::EnumChildWindowsCb(HWND hWindow, LPARAM param) { EnumChildWindowsCbParam* cbParam = (EnumChildWindowsCbParam*)param; DWORD pid; GetWindowThreadProcessId(hWindow, &pid); HANDLE hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid); if (hProc == NULL) { return true; } cbParam->path = cbParam->aw->getProcessPath(hProc); cbParam->hProc = hProc; UINT32 _len = 0; if (GetPackageFamilyName(cbParam->hProc, &_len, NULL) == APPMODEL_ERROR_NO_PACKAGE) { CloseHandle(hProc); return true; } cbParam->ok = true; return false; } VOID CALLBACK ActiveWindow::WinEventProcCb(HWINEVENTHOOK hHook, DWORD event, HWND hWindow, LONG idObject, LONG idChild, DWORD eventThread, DWORD eventTime) { if (event != EVENT_SYSTEM_FOREGROUND && event != EVENT_OBJECT_NAMECHANGE) { // not interested in these return; } HWND foregroundWindow = GetForegroundWindow(); if (event == EVENT_OBJECT_NAMECHANGE && hWindow != foregroundWindow) { // name changed, but not for current window return; } // get context ActiveWindow::smutex.lock(); ActiveWindow* aw = ActiveWindow::winEventProcCbCtx[hHook]; ActiveWindow::smutex.unlock(); WindowInfo* info = aw->getActiveWindow(); // notify every callback aw->mutex.lock(); for (std::unordered_map::iterator it = aw->watches.begin(); it != aw->watches.end(); it++) { try { it->second(info); } catch (...) { // doing nothing } } aw->mutex.unlock(); delete info; } } ================================================ FILE: src/modules/node-active-window/module/windows/src/ActiveWindow.h ================================================ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef _PAYMO_ACTIVEWINDOW_H #define _PAYMO_ACTIVEWINDOW_H namespace PaymoActiveWindow { struct WindowInfo { std::wstring title = L""; std::wstring application = L""; std::wstring path = L""; unsigned int pid = 0; bool isUWPApp = false; std::wstring uwpPackage = L""; std::string icon = ""; }; typedef unsigned int watch_t; typedef std::function watch_callback; class ActiveWindow { public: ActiveWindow(unsigned int iconCacheSize = 0); ~ActiveWindow(); WindowInfo* getActiveWindow(); watch_t watchActiveWindow(watch_callback cb); void unwatchActiveWindow(watch_t watch); private: ULONG_PTR gdiPlusToken; CLSID gdiPlusEncoder; watch_t nextWatchId = 1; std::thread* watchThread = NULL; std::mutex mutex; std::atomic threadShouldExit; std::unordered_map watches; static std::mutex smutex; static std::unordered_map winEventProcCbCtx; std::wstring getWindowTitle(HWND hWindow); std::wstring getProcessPath(HANDLE hProc); std::wstring getProcessName(std::wstring path); std::string getWindowIcon(std::wstring path); std::string getUWPIcon(HANDLE hProc); std::wstring getUWPPackage(HANDLE hProc); std::wstring basename(std::wstring path); bool isUWPApp(std::wstring path); HICON getHighResolutionIcon(std::wstring path); IStream* getPngFromIcon(HICON hIcon); std::wstring getUWPPackagePath(HANDLE hProc); IAppxManifestProperties* getUWPPackageProperties(std::wstring pkgPath); std::wstring getUWPLargestIconPath(std::wstring iconPath); std::string encodeImageStream(IStream* pngStream); void runWatchThread(); static BOOL CALLBACK EnumChildWindowsCb(HWND hWindow, LPARAM param); static VOID CALLBACK WinEventProcCb(HWINEVENTHOOK hHook, DWORD event, HWND hWindow, LONG idObject, LONG idChild, DWORD eventThread, DWORD eventTime); }; struct EnumChildWindowsCbParam { ActiveWindow* aw; std::wstring path = L""; HANDLE hProc; bool ok = false; EnumChildWindowsCbParam(ActiveWindow* aw) { this->aw = aw; } }; } #endif ================================================ FILE: src/modules/node-active-window/package.json ================================================ { "name": "@paymoapp/active-window", "version": "1.2.3", "description": "NodeJS library using native modules to get the active window and some metadata (including the application icon) on Windows, MacOS and Linux.", "main": "./dist/index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "postinstall": "npm run build", "build": "npm run build:gyp", "build:ts": "tsc --project tsconfig.build.json", "build:gyp": "node-gyp rebuild", "clean": "node-gyp clean && rimraf dist", "typecheck": "tsc --noEmit", "release": "standard-version", "release:pre": "standard-version --prerelease", "generate:readme-toc": "markdown-toc -i --bullets=\"-\" --maxdepth=4 README.md" }, "binary": { "napi_versions": [ 6 ] }, "files": [ "binding.gyp", "dist/", "module/" ], "repository": { "type": "git", "url": "https://github.com/paymoapp/node-active-window" }, "keywords": [ "node", "native", "active", "window" ], "author": "Paymo SRL", "license": "GPL-3.0", "devDependencies": { "@types/node": "^17.0.35", "@types/ws": "^8.5.3", "@typescript-eslint/eslint-plugin": "^5.26.0", "@typescript-eslint/parser": "^5.26.0", "eslint": "^8.16.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.0.0", "eslint-watch": "^8.0.0", "markdown-toc": "^1.2.0", "prettier": "^2.6.2", "rimraf": "^3.0.2", "standard-version": "^9.5.0", "ts-node": "^10.8.1", "typescript": "^4.6.4", "ws": "^8.7.0" }, "dependencies": { "node-addon-api": "^5.0.0" }, "standard-version": { "scripts": { "prerelease": "git fetch --all --tags" }, "types": [ { "type": "feat", "section": "Features" }, { "type": "fix", "section": "Bug Fixes" }, { "type": "imp", "section": "Improvements" }, { "type": "ci", "section": "Build/CI" }, { "type": "chore", "hidden": true }, { "type": "docs", "section": "Documentation" }, { "type": "refactor", "section": "Refactor" }, { "type": "test", "section": "Testing" } ] } } ================================================ FILE: src/modules/node-active-window/src/index.ts ================================================ import type { Module, NativeWindowInfo, WindowInfo, IActiveWindow, InitializeOptions } from './types'; const SUPPORTED_PLATFORMS = ['win32', 'linux', 'darwin']; let addon: Module | undefined; if (SUPPORTED_PLATFORMS.includes(process.platform)) { addon = require('../build/Release/PaymoActiveWindow.node'); // eslint-disable-line import/no-dynamic-require } else { throw new Error( `Unsupported platform. The supported platforms are: ${SUPPORTED_PLATFORMS.join( ',' )}` ); } const encodeWindowInfo = (info: NativeWindowInfo): WindowInfo => { return { title: info.title, application: info.application, path: info.path, pid: info.pid, icon: info.icon, ...(process.platform == 'win32' ? { windows: { isUWPApp: info['windows.isUWPApp'] || false, uwpPackage: info['windows.uwpPackage'] || '' } } : {}) }; }; const ActiveWindow: IActiveWindow = { getActiveWindow: (): WindowInfo => { if (!addon) { throw new Error('Failed to load native addon'); } const info = addon.getActiveWindow(); return encodeWindowInfo(info); }, subscribe: (callback: (windowInfo: WindowInfo | null) => void): number => { if (!addon) { throw new Error('Failed to load native addon'); } const watchId = addon.subscribe(nativeWindowInfo => { callback( !nativeWindowInfo ? null : encodeWindowInfo(nativeWindowInfo) ); }); return watchId; }, unsubscribe: (watchId: number): void => { if (!addon) { throw new Error('Failed to load native addon'); } if (watchId < 0) { throw new Error('Watch ID must be a positive number'); } addon.unsubscribe(watchId); }, initialize: ({ osxRunLoop }: InitializeOptions = {}): void => { if (!addon) { throw new Error('Failed to load native addon'); } if (addon.initialize) { addon.initialize(); } // set up runloop on MacOS if (process.platform == 'darwin' && osxRunLoop) { const interval = setInterval(() => { if (addon && addon.runLoop) { addon.runLoop(); } else { clearInterval(interval); } }, 100); } }, requestPermissions: (): boolean => { if (!addon) { throw new Error('Failed to load native addon'); } if (addon.requestPermissions) { return addon.requestPermissions(); } return true; } }; export * from './types'; export default ActiveWindow; ================================================ FILE: src/modules/node-active-window/src/types.ts ================================================ export interface NativeWindowInfo { title: string; application: string; path: string; pid: number; icon: string; 'windows.isUWPApp'?: boolean; 'windows.uwpPackage'?: string; } export interface WindowInfo { title: string; application: string; path: string; pid: number; icon: string; windows?: { isUWPApp: boolean; uwpPackage: string; }; } export interface Module { getActiveWindow(): T; subscribe(callback: (windowInfo: T | null) => void): number; unsubscribe(watchId: number): void; initialize?(): void; requestPermissions?(): boolean; runLoop?(): void; } export interface InitializeOptions { osxRunLoop?: boolean; } export interface IActiveWindow extends Omit, 'runLoop'> { initialize(opts?: InitializeOptions): void; requestPermissions(): boolean; } ================================================ FILE: src/modules/node-active-window/tsconfig.build.json ================================================ { "extends": "./tsconfig.json", "include": ["src"] } ================================================ FILE: src/modules/node-active-window/tsconfig.json ================================================ { "compilerOptions": { "target": "es6", "module": "commonjs", "lib": ["esnext", "DOM"], "allowJs": true, "rootDirs": ["src"], "outDir": "dist", "resolveJsonModule": true, "strict": true, "skipLibCheck": true, "allowSyntheticDefaultImports": true, "esModuleInterop": true, "moduleResolution": "node", "isolatedModules": true, "declaration": true, "typeRoots": ["./typings", "./node_modules/@types"] }, "include": ["src", "demo"] } ================================================ FILE: src/modules/node-ddcci/.clang-format ================================================ BasedOnStyle: Mozilla AlignOperands: true AlignTrailingComments: true BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Linux ColumnLimit: 80 ContinuationIndentWidth: 2 IndentWidth: 4 MaxEmptyLinesToKeep: 2 BreakStringLiterals: false ================================================ FILE: src/modules/node-ddcci/.gitignore ================================================ node_modules/ build/ ================================================ FILE: src/modules/node-ddcci/README.md ================================================ # node-ddcci ## Installation node-ddcci is currently only supported on Windows. ````bash npm install @hensm/ddcci ```` ## Usage ````js const ddcci = require("@hensm/ddcci"); for (const monitor of ddcci.getMonitorList()) { console.log(`${monitor} current brightness: ${ddcci.getBrightness(monitor)}`); ddcci.setBrightness(monitor, 25); } ```` ## Docs * ### `getMonitorList()` Gets a list of the current connected monitors. * #### Return value An array of `String` containing the monitor IDs. * ### `getBrightness(monitorId)` Queries a monitor's brightness level. * #### Parameters * **`monitorId`** `String`. ID of monitor for which to query the brightness. * #### Return value An `integer`, typically between 0-100, representing the current brightness. * ### `getMaxBrightness(monitorId)` Queries a monitor's maximum brightness level. * #### Parameters * **`monitorId`** `String`. ID of monitor for which to query the brightness. * #### Return value An `integer`, typically between 0-100, representing the maximum brightness. * ### `setBrightness(monitorId, level)` Sets a monitor's brightness level. * #### Parameters * **`monitorId`** `String`. ID of monitor for which to set the brightness. * **`level`** `integer`. Between 0-100 representing the new brightness level. * ### `getContrast(monitorId)` Queries a monitor's contrast level. * #### Parameters * **`monitorId`** `String`. ID of monitor for which to query the contrast. * #### Return value An `integer`, typically between 0-100, representing the current contrast. * ### `getMaxContrast(monitorId)` Queries a monitor's maximum contrast level. * #### Parameters * **`monitorId`** `String`. ID of monitor for which to query the contrast. * #### Return value An `integer`, typically between 0-100, representing the maximum contrast. * ### `setContrast(monitorId, level)` Sets a monitor's contrast level. * #### Parameters * **`monitorId`** `String`. ID of monitor for which to set the contrast. * **`level`** `integer`. Between 0-100 representing the new contrast level. * ### `_getVCP(monitorId, vcpCode)` Queries a monitor for a VCP code value. * #### Parameters * **`monitorId`** `String`. ID of monitor for which to query the VCP feature. * **`vcpCode`** `integer`. VCP code to query * #### Return value An `array` of two `integer` values in the format of `[currentValue, maxValue]`. * ### `_setVCP(monitorId, vcpCode, value)` Sets the value of a VCP code for a monitor. * #### Parameters * **`monitorId`** `String`. ID of monitor for which to set the VCP feature. * **`vcpCode`** `integer`. VCP code to set. * **`value`** `integer`. Value of the VCP code. * ### `_refresh()` Refreshes the monitor list. ================================================ FILE: src/modules/node-ddcci/binding.gyp ================================================ { "targets": [{ "target_name": "ddcci" , "sources": [ "./ddcci.cc" ] , "cflags_cc": [ "-std=c++17" ] , "include_dirs": [ " #include "HighLevelMonitorConfigurationAPI.h" #include "LowLevelMonitorConfigurationAPI.h" #include "PhysicalMonitorEnumerationAPI.h" #include "windows.h" #include "winuser.h" #include #include #include #include #include #include #include struct Monitor { HMONITOR handle; std::string monitorName; std::vector physicalHandles; }; struct MonitorHighLevel { DWORD capabilities = 0; DWORD capabilitiesOK = 0; DWORD supportedTemperatures = 0; DWORD brightness = 0; DWORD brightnessMin = 0; DWORD brightnessMax = 0; DWORD brightnessOK = 0; DWORD contrast = 0; DWORD contrastMin = 0; DWORD contrastMax = 0; DWORD contrastOK = 0; }; struct PhysicalMonitor { HANDLE handle; bool handleIsValid; bool ddcciSupported; std::string name; std::string fullName; std::string physicalName; std::string result; std::string deviceKey; std::string deviceID; MonitorHighLevel hlCapabilities; }; struct DisplayDevice { std::string adapterName; std::string deviceName; std::string deviceID; std::string deviceKey; }; struct DisplayMonitor { std::string adapterName; std::list handles; }; std::map handles; std::map physicalMonitorHandles; std::map capabilities; int logLevel = 0; // Info void p(std::string s) { if(logLevel >= 1) { std::cout << "[node-ddcci] " + s << std::endl; } } // Debug void d(std::string s) { if(logLevel >= 2) { std::cout << "[node-ddcci] " + s << std::endl; } } void clearMonitorData() { if (!handles.empty()) { for (auto const& handle : handles) { DestroyPhysicalMonitor(handle.second); } handles.clear(); } if (!physicalMonitorHandles.empty()) { for (auto const& physicalMonitor : physicalMonitorHandles) { DestroyPhysicalMonitor(physicalMonitor.second.handle); } physicalMonitorHandles.clear(); } if (!capabilities.empty()) { capabilities.clear(); } } void cleanMonitorHandles(std::map newHandles) { if (!handles.empty()) { for (auto const& handle : handles) { bool found = false; for (auto const& newHandle : newHandles) { if (handle.second == newHandle.second) { found = true; break; } } if (!found) { DestroyPhysicalMonitor(handle.second); handles.erase(handle.first); } } handles.clear(); } } std::string getLastErrorString() { DWORD errorCode = GetLastError(); if (!errorCode) { return std::string(); } LPSTR buf = NULL; DWORD size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, LANG_SYSTEM_DEFAULT, (LPSTR)&buf, 0, NULL); std::string message(buf, size); return message; } std::string getPhysicalMonitorName(HMONITOR handle) { MONITORINFOEX monitorInfo; monitorInfo.cbSize = sizeof(MONITORINFOEX); GetMonitorInfo(handle, &monitorInfo); std::string monitorName = static_cast(monitorInfo.szDevice); return monitorName; } std::map getAllDisplays(std::string keyType) { std::map out; DISPLAY_DEVICE adapterDev; adapterDev.cb = sizeof(DISPLAY_DEVICE); // Loop through adapters int adapterDevIndex = 0; while (EnumDisplayDevices(NULL, adapterDevIndex++, &adapterDev, 0)) { DISPLAY_DEVICE displayDev; displayDev.cb = sizeof(DISPLAY_DEVICE); // Check valid target if (!(adapterDev.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) { //continue; } // Loop through displays (with device ID) on each adapter int displayDevIndex = 0; while (EnumDisplayDevices(adapterDev.DeviceName, displayDevIndex++, &displayDev, EDD_GET_DEVICE_INTERFACE_NAME)) { // Check valid target if (!(displayDev.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) { continue; } std::string deviceName = static_cast(displayDev.DeviceName); DisplayDevice newDevice; newDevice.adapterName = static_cast(adapterDev.DeviceName); newDevice.deviceName = static_cast(displayDev.DeviceName); newDevice.deviceID = static_cast(displayDev.DeviceID); newDevice.deviceKey = newDevice.deviceID.substr(0, newDevice.deviceID.find("#{")); out.insert( { (keyType == "name" ? newDevice.deviceName : keyType == "adapter" ? newDevice.adapterName : newDevice.deviceKey), newDevice }); } } return out; } std::vector getAllHandles() { std::vector monitors; auto monitorEnumProc = [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL { auto monitors = reinterpret_cast*>(dwData); monitors->push_back({ hMonitor, {} }); return TRUE; }; EnumDisplayMonitors( NULL, NULL, monitorEnumProc, reinterpret_cast(&monitors)); // Get physical monitor handles for (auto& monitor : monitors) { DWORD numPhysicalMonitors; LPPHYSICAL_MONITOR physicalMonitors = NULL; if (!GetNumberOfPhysicalMonitorsFromHMONITOR(monitor.handle, &numPhysicalMonitors)) { throw std::runtime_error("Failed to get physical monitor count."); exit(EXIT_FAILURE); } physicalMonitors = new PHYSICAL_MONITOR[numPhysicalMonitors]; if (physicalMonitors == NULL) { throw std::runtime_error( "Failed to allocate physical monitor array"); } if (!GetPhysicalMonitorsFromHMONITOR( monitor.handle, numPhysicalMonitors, physicalMonitors)) { throw std::runtime_error("Failed to get physical monitors."); } for (DWORD i = 0; i <= numPhysicalMonitors; i++) { monitor.physicalHandles.push_back( physicalMonitors[i].hPhysicalMonitor); } monitor.monitorName = getPhysicalMonitorName(monitor.handle); delete[] physicalMonitors; } return monitors; } MonitorHighLevel getHighLevelCapabilities(HANDLE handle) { MonitorHighLevel monitor; if(handle == NULL) { d("No handle for capabilities data!"); return monitor; } // General capabilities // Note: Displays that don't support color temperature seem to respond poorly to this function /* monitor.capabilitiesOK = GetMonitorCapabilities(handle, &monitor.capabilities, &monitor.supportedTemperatures); d("== GetMonitorCapabilities: " + std::to_string(monitor.capabilitiesOK) + ": " + std::to_string(monitor.capabilities)); if(monitor.capabilitiesOK == 0) { d("== Error: " + getLastErrorString()); } */ // Brightness monitor.brightnessOK = GetMonitorBrightness(handle, &monitor.brightnessMin, &monitor.brightness, &monitor.brightnessMax); d("-- -- GetMonitorBrightness: " + std::to_string(monitor.brightnessOK) + ": " + std::to_string(monitor.brightness) + " (" + std::to_string(monitor.brightnessMin) + "-" + std::to_string(monitor.brightnessMax) + ")"); if(monitor.brightnessOK == 0) { d("-- -- Error: " + getLastErrorString()); } // Contrast monitor.contrastOK = GetMonitorContrast(handle, &monitor.contrastMin, &monitor.contrast, &monitor.contrastMax); d("-- -- GetMonitorContrast: " + std::to_string(monitor.contrastOK) + ": " + std::to_string(monitor.contrast) + " (" + std::to_string(monitor.contrastMin) + "-" + std::to_string(monitor.contrastMax) + ")"); if(monitor.contrastOK == 0) { d("-- -- Error: " + getLastErrorString()); } return monitor; } std::string getCapabilitiesString(HANDLE handle) { DWORD cchStringLength = 0; BOOL bSuccess = 0; std::string returnString = ""; if(handle == NULL) { d("No handle for capabilities string!"); return ""; } if(handle != NULL) { // Get the capabilities string length. // Checking the capabilities string is, apparently, very flaky. // So if it fails, we should try again. int attempt = 0; bSuccess = 0; while (bSuccess != 1 && attempt < 3) { if(attempt > 1) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } attempt++; bSuccess = GetCapabilitiesStringLength(handle, &cchStringLength); d("== cLength attempt #" + std::to_string(attempt) + ": " + std::to_string(bSuccess)); } if (bSuccess != 1) { d("Couldn't get capabilities length!"); return ""; // Does not respond to DDC/CI } } d("== cLength: " + std::to_string(cchStringLength)); // Allocate the string buffer. LPSTR szCapabilitiesString = (LPSTR)malloc(cchStringLength); if (szCapabilitiesString != NULL) { // Get the capabilities string. // We know it exists, so we'll try a few times if needed. int attempt = 0; bSuccess = 0; while (bSuccess != 1 && attempt < 5) { if(attempt > 1) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } attempt++; bSuccess = CapabilitiesRequestAndCapabilitiesReply( handle, szCapabilitiesString, cchStringLength); d("== cString attempt #" + std::to_string(attempt) + ": " + std::to_string(bSuccess)); } if (bSuccess != 1) { d("Couldn't get capabilities string!"); return ""; // Does not respond to DDC/CI } returnString = std::string(szCapabilitiesString); // Free the string buffer. free(szCapabilitiesString); } return returnString; } // Test if HANDLE has a working DDC/CI connection. // Returns "invalid", "ok", or a capabilities string. std::string getPhysicalHandleResults(HANDLE handle, std::string validationMethod) { if (validationMethod == "no-validation") return "ok"; BOOL bSuccess = 0; // Accurate method: Check capabilities string if (validationMethod == "accurate") { std::string result = getCapabilitiesString(handle); if(result == "") { return "invalid"; } return result; } // Fast method: Check common VCP codes DWORD currentValue; DWORD maxValue; // 0x02, New Control Value if (GetVCPFeatureAndVCPFeatureReply( handle, 0x02, NULL, ¤tValue, &maxValue)) { bSuccess = 1; return "ok"; } // 0xDF, VCP Version if (!bSuccess && GetVCPFeatureAndVCPFeatureReply( handle, 0xDF, NULL, ¤tValue, &maxValue)) { bSuccess = 1; return "ok"; } // 0x10, Brightness (usually) if (!bSuccess && GetVCPFeatureAndVCPFeatureReply( handle, 0x10, NULL, ¤tValue, &maxValue)) { bSuccess = 1; return "ok"; } if (bSuccess == 0) { return "invalid"; } return "ok"; } // Old method of detecting DDC/CI handles void populateHandlesMapLegacy() { clearMonitorData(); auto monitorEnumProc = [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL { auto monitors = reinterpret_cast*>(dwData); monitors->push_back({ hMonitor, {} }); return TRUE; }; std::vector monitors; EnumDisplayMonitors( NULL, NULL, monitorEnumProc, reinterpret_cast(&monitors)); // Get physical monitor handles for (auto& monitor : monitors) { DWORD numPhysicalMonitors; LPPHYSICAL_MONITOR physicalMonitors = NULL; if (!GetNumberOfPhysicalMonitorsFromHMONITOR(monitor.handle, &numPhysicalMonitors)) { throw std::runtime_error("Failed to get physical monitor count."); exit(EXIT_FAILURE); } physicalMonitors = new PHYSICAL_MONITOR[numPhysicalMonitors]; if (physicalMonitors == NULL) { throw std::runtime_error( "Failed to allocate physical monitor array"); } if (!GetPhysicalMonitorsFromHMONITOR( monitor.handle, numPhysicalMonitors, physicalMonitors)) { throw std::runtime_error("Failed to get physical monitors."); } for (DWORD i = 0; i <= numPhysicalMonitors; i++) { monitor.physicalHandles.push_back( physicalMonitors[(numPhysicalMonitors == 1 ? 0 : i)] .hPhysicalMonitor); } delete[] physicalMonitors; } DISPLAY_DEVICE adapterDev; adapterDev.cb = sizeof(DISPLAY_DEVICE); // Loop through adapters int adapterDevIndex = 0; while (EnumDisplayDevices(NULL, adapterDevIndex++, &adapterDev, 0)) { DISPLAY_DEVICE displayDev; displayDev.cb = sizeof(DISPLAY_DEVICE); // Loop through displays (with device ID) on each adapter int displayDevIndex = 0; while (EnumDisplayDevices(adapterDev.DeviceName, displayDevIndex++, &displayDev, EDD_GET_DEVICE_INTERFACE_NAME)) { // Check valid target if (!(displayDev.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) || displayDev.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) { continue; } for (auto const& monitor : monitors) { MONITORINFOEX monitorInfo; monitorInfo.cbSize = sizeof(MONITORINFOEX); GetMonitorInfo(monitor.handle, &monitorInfo); for (size_t i = 0; i < monitor.physicalHandles.size(); i++) { /** * Re-create DISPLAY_DEVICE.DeviceName with * MONITORINFOEX.szDevice and monitor index. */ std::string monitorName = static_cast(monitorInfo.szDevice) + "\\Monitor" + std::to_string(i); std::string deviceName = static_cast(displayDev.DeviceName); std::string deviceID = static_cast(displayDev.DeviceID); std::string deviceKey = deviceID.substr(0, deviceID.find("#{")); // Match and store against device ID if (monitorName == deviceName) { handles.insert({ static_cast(deviceKey), monitor.physicalHandles[i] }); break; } } } } } // Also update physicalMonitorHandles for use with getAllDisplays std::map displays = getAllDisplays("key"); for (auto const& handle : handles) { PhysicalMonitor newMonitor; newMonitor.handle = handle.second; newMonitor.ddcciSupported = true; auto it = displays.find(handle.first); if (it != displays.end()) { newMonitor.name = it->second.deviceName.substr( 0, it->second.deviceName.find("Monitor")); newMonitor.fullName = it->second.deviceName; newMonitor.deviceKey = it->second.deviceKey; newMonitor.deviceID = it->second.deviceID; } physicalMonitorHandles.insert({ handle.first, newMonitor }); } } void populateHandlesMapNormal(std::string validationMethod, bool usePreviousResults, bool checkHighLevel) { std::map newHandles; std::map newPhysicalHandles; d("Getting all display devices..."); std::map displays = getAllDisplays("name"); for (auto const& display : displays) { d("-- Display: " + display.first); d("-- -- deviceName: " + display.second.deviceName); d("-- -- deviceID: " + display.second.deviceID); d("-- -- deviceKey: " + display.second.deviceKey); } p("Testing all physicalMonitors..."); // Get physical monitor handles std::vector monitors = getAllHandles(); for (auto& monitor : monitors) { for (DWORD i = 0; i <= monitor.physicalHandles.size(); i++) { /** * Loop through physical monitors, check capabilities, * and only include ones that work. */ std::string fullMonitorName = monitor.monitorName + "\\" + "Monitor" + std::to_string(i); p("-- " + fullMonitorName); PhysicalMonitor newMonitor; newMonitor.handle = monitor.physicalHandles[i]; newMonitor.handleIsValid = (newMonitor.handle != NULL); newMonitor.name = monitor.monitorName; newMonitor.physicalName = fullMonitorName; newMonitor.ddcciSupported = false; // Match with DISPLAY_DEVICE list bool foundMatchingDisplay = false; int foundCount = 0; for (auto const& display : displays) { // Match with display number (e.g. "\\.\DISPLAY2") if(display.second.adapterName == monitor.monitorName) { /** * Match the physical monitor index with the index of found matching display numbers. * For example, if all DISPLAY_DEVICE includes: * - \\.\DISPLAY1\Monitor1 * - \\.\DISPLAY2\Monitor0 * - \\.\DISPLAY2\Monitor2 * * And the physical monitor name is \\.\DISPLAY2... * And we're on physical monitor index 1 ("i == 1")... * ...then we want \\.\DISPLAY2\Monitor2 because it is index 1 of the "\\.\DISPLAY2" DISPLAY_DEVICEs. */ if(foundCount == i) { newMonitor.deviceKey = display.second.deviceKey; newMonitor.deviceID = display.second.deviceID; newMonitor.fullName = display.second.deviceName; foundMatchingDisplay = true; p("-- -- Matched with: " + display.second.deviceKey); break; } foundCount++; } } if(!foundMatchingDisplay) { p("-- -- Couldn't find match. Skipping."); break; } // Check if monitor was previously tested and supported if(usePreviousResults) { for (auto const& previousDisplay : physicalMonitorHandles) { if(previousDisplay.second.fullName == newMonitor.fullName && previousDisplay.second.deviceID == newMonitor.deviceID && previousDisplay.second.ddcciSupported && previousDisplay.second.result != "invalid") { newMonitor.result = previousDisplay.second.result; newMonitor.ddcciSupported = previousDisplay.second.ddcciSupported; // Test old handle if it's valid if(previousDisplay.second.handle != NULL && previousDisplay.second.handleIsValid) { p("-- -- Testing old handle."); if("ok" == getPhysicalHandleResults(previousDisplay.second.handle, "fast")) { p("-- -- Using old handle."); newMonitor.handle = previousDisplay.second.handle; newMonitor.handleIsValid = previousDisplay.second.handleIsValid; newMonitor.hlCapabilities = previousDisplay.second.hlCapabilities; } } break; } } } // Test high level capabilities if((newMonitor.hlCapabilities.brightnessOK || newMonitor.hlCapabilities.contrastOK) == false) { if(checkHighLevel) { p("-- -- High Level: Checking..."); newMonitor.hlCapabilities = getHighLevelCapabilities(newMonitor.handle); } else { p("-- -- High Level: Skipped"); } } if(newMonitor.hlCapabilities.brightnessOK || newMonitor.hlCapabilities.contrastOK) { p("-- -- High Level: Supported"); } // Test DDC/CI bool saveCapabilities = false; if (newMonitor.ddcciSupported == false) { std::string result = "invalid"; if (capabilities.find(newMonitor.deviceKey) == capabilities.end()) { // Capabilities string not found, read it // If "accurate", check "fast" first if(validationMethod == "accurate") { result = getPhysicalHandleResults(newMonitor.handle, "fast"); } // Check results using requested method std::string validationMethodResult = getPhysicalHandleResults(newMonitor.handle, validationMethod); if(validationMethodResult != "invalid") { result = validationMethodResult; } saveCapabilities = true; } else { // Reuse capabilities string result = capabilities.find(newMonitor.deviceKey)->second; p("-- -- Using previous capabilities string."); } newMonitor.result = result; p("-- -- DDC/CI: " + result); if (result == "invalid") { newMonitor.ddcciSupported = false; } else { newMonitor.ddcciSupported = true; } } else { p("-- -- DDC/CI: previously OK"); } // Add to monitor list newPhysicalHandles.insert({ newMonitor.fullName, newMonitor }); newHandles.insert({ newMonitor.deviceKey, newMonitor.handle }); // Add to capabilities list if (saveCapabilities && validationMethod == "accurate" && newMonitor.result != "ok" && newMonitor.result != "invalid") { capabilities.insert( { newMonitor.deviceKey, newMonitor.result }); } } } cleanMonitorHandles(newHandles); handles = newHandles; physicalMonitorHandles = newPhysicalHandles; } void populateHandlesMap(std::string validationMethod, bool usePreviousResults, bool checkHighLevel) { try { if (validationMethod == "legacy") return populateHandlesMapLegacy(); if (validationMethod == "accurate" || validationMethod == "no-validation") return populateHandlesMapNormal(validationMethod, usePreviousResults, checkHighLevel); return populateHandlesMapNormal("fast", usePreviousResults, checkHighLevel); } catch (...) { } } Napi::Value refresh(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 2) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsString() || !info[1].IsBoolean() || !info[2].IsBoolean()) { throw Napi::TypeError::New(env, "Invalid arguments"); } try { populateHandlesMap(info[0].As().Utf8Value(), info[1].As().ToBoolean(), info[2].As().ToBoolean()); } catch (...) { throw Napi::Error::New(env, "Error refreshing DDC/CI displays!"); } return env.Undefined(); } void clearDisplayCache(const Napi::CallbackInfo& info) { if (!physicalMonitorHandles.empty()) { physicalMonitorHandles.clear(); } if (!capabilities.empty()) { capabilities.clear(); } } Napi::String getNAPICapabilitiesString(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 1) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsString()) { throw Napi::TypeError::New(env, "Invalid arguments"); } std::string monitorName = info[0].As().Utf8Value(); // Check if it's already saved in memory first. auto found = capabilities.find(monitorName); if (found != capabilities.end()) { return Napi::String::New(env, found->second); } // Find requested monitor. auto it = handles.find(monitorName); if (it == handles.end()) { throw Napi::Error::New(env, "Monitor not found"); } std::string returnString = getCapabilitiesString(it->second); if(returnString == "") { throw Napi::Error::New( env, "Monitor not responding."); // Does not respond to DDC/CI } return Napi::String::New(env, returnString); } Napi::Array getMonitorList(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); Napi::Array ret = Napi::Array::New(env, handles.size()); int i = 0; for (auto const& handle : handles) { ret.Set(i++, handle.first); } return ret; } Napi::Array getAllMonitors(const Napi::CallbackInfo& info) { napi_env env = info.Env(); Napi::Array monitors = Napi::Array::New(env); int i = 0; for (auto const& handle : physicalMonitorHandles) { Napi::Object monitor = Napi::Object::New(env); monitor.Set("ddcciSupported", Napi::Boolean::New(env, handle.second.ddcciSupported)); monitor.Set("hlBrightnessSupported", Napi::Boolean::New(env, handle.second.hlCapabilities.brightnessOK)); monitor.Set("hlContrastSupported", Napi::Boolean::New(env, handle.second.hlCapabilities.contrastOK)); monitor.Set("handleIsValid", Napi::Boolean::New(env, handle.second.handleIsValid)); monitor.Set("name", Napi::String::New(env, handle.second.name)); monitor.Set("fullName", Napi::String::New(env, handle.second.fullName)); monitor.Set("physicalName", Napi::String::New(env, handle.second.physicalName)); monitor.Set("result", Napi::String::New(env, handle.second.result)); monitor.Set("deviceKey", Napi::String::New(env, handle.second.deviceKey)); monitor.Set("deviceID", Napi::String::New(env, handle.second.deviceID)); monitors.Set(i++, monitor); } return monitors; } Napi::Value setVCP(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 3) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsString() || !info[1].IsNumber() || !info[2].IsNumber()) { throw Napi::TypeError::New(env, "Invalid arguments"); } std::string monitorName = info[0].As().Utf8Value(); BYTE vcpCode = static_cast(info[1].As().Int32Value()); DWORD newValue = static_cast(info[2].As().Int32Value()); auto it = handles.find(monitorName); if (it == handles.end()) { throw Napi::Error::New(env, "Monitor not found"); } if (!SetVCPFeature(it->second, vcpCode, newValue)) { throw Napi::Error::New(env, std::string("Failed to set VCP code value\n") + getLastErrorString()); } return env.Undefined(); } Napi::Value getVCP(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 2) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsString() || !info[1].IsNumber()) { throw Napi::TypeError::New(env, "Invalid arguments"); } std::string monitorName = info[0].As().Utf8Value(); BYTE vcpCode = static_cast(info[1].As().Int32Value()); auto it = handles.find(monitorName); if (it == handles.end()) { throw Napi::Error::New(env, "Monitor not found"); } DWORD currentValue; DWORD maxValue; if (!GetVCPFeatureAndVCPFeatureReply( it->second, vcpCode, NULL, ¤tValue, &maxValue)) { throw Napi::Error::New(env, std::string("Failed to get VCP code value\n") + getLastErrorString()); } Napi::Array ret = Napi::Array::New(env, 2); ret.Set((uint32_t)0, static_cast(currentValue)); ret.Set((uint32_t)1, static_cast(maxValue)); return ret; } Napi::Boolean saveCurrentSettings(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 1) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsString()) { throw Napi::TypeError::New(env, "Invalid arguments"); } std::string monitorName = info[0].As().Utf8Value(); auto it = handles.find(monitorName); if (it == handles.end()) { throw Napi::Error::New(env, "Monitor not found"); } BOOL bSuccess = 0; bSuccess = SaveCurrentSettings(it->second); return Napi::Boolean::New(env, bSuccess); } Napi::Value getHighLevelBrightness(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 1) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsString()) { throw Napi::TypeError::New(env, "Invalid arguments"); } std::string monitorName = info[0].As().Utf8Value(); auto it = handles.find(monitorName); if (it == handles.end()) { throw Napi::Error::New(env, "Monitor not found"); } DWORD minValue; DWORD currentValue; DWORD maxValue; if (!GetMonitorBrightness( it->second, &minValue, ¤tValue, &maxValue)) { throw Napi::Error::New(env, std::string("Failed to get high level brightness\n") + getLastErrorString()); } Napi::Array ret = Napi::Array::New(env, 3); ret.Set((uint32_t)0, static_cast(currentValue)); ret.Set((uint32_t)1, static_cast(maxValue)); ret.Set((uint32_t)2, static_cast(minValue)); return ret; } Napi::Value setHighLevelBrightness(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 2) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsString() || !info[1].IsNumber()) { throw Napi::TypeError::New(env, "Invalid arguments"); } std::string monitorName = info[0].As().Utf8Value(); DWORD newValue = static_cast(info[1].As().Int32Value()); auto it = handles.find(monitorName); if (it == handles.end()) { throw Napi::Error::New(env, "Monitor not found"); } if (!SetMonitorBrightness(it->second, newValue)) { throw Napi::Error::New(env, std::string("Failed to set high level brightness\n") + getLastErrorString()); } return env.Undefined(); } Napi::Value getHighLevelContrast(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 1) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsString()) { throw Napi::TypeError::New(env, "Invalid arguments"); } std::string monitorName = info[0].As().Utf8Value(); auto it = handles.find(monitorName); if (it == handles.end()) { throw Napi::Error::New(env, "Monitor not found"); } DWORD minValue; DWORD currentValue; DWORD maxValue; if (!GetMonitorContrast( it->second, &minValue, ¤tValue, &maxValue)) { throw Napi::Error::New(env, std::string("Failed to get high level contrast\n") + getLastErrorString()); } Napi::Array ret = Napi::Array::New(env, 3); ret.Set((uint32_t)0, static_cast(currentValue)); ret.Set((uint32_t)1, static_cast(maxValue)); ret.Set((uint32_t)2, static_cast(minValue)); return ret; } Napi::Value setHighLevelContrast(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 2) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsString() || !info[1].IsNumber()) { throw Napi::TypeError::New(env, "Invalid arguments"); } std::string monitorName = info[0].As().Utf8Value(); DWORD newValue = static_cast(info[1].As().Int32Value()); auto it = handles.find(monitorName); if (it == handles.end()) { throw Napi::Error::New(env, "Monitor not found"); } if (!SetMonitorContrast(it->second, newValue)) { throw Napi::Error::New(env, std::string("Failed to set high level contrast\n") + getLastErrorString()); } return env.Undefined(); } void setLogLevel(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); if (info.Length() < 1) { throw Napi::TypeError::New(env, "Not enough arguments"); } if (!info[0].IsNumber()) { throw Napi::TypeError::New(env, "Invalid arguments"); } logLevel = (int)info[0].ToNumber(); } Napi::Array getMonitorInputs(const Napi::CallbackInfo& info) { napi_env env = info.Env(); if (info.Length() < 1) { Napi::TypeError::New(env, "Monitor key required").ThrowAsJavaScriptException(); return Napi::Array::New(env); } std::string searchKey = info[0].As(); // Ищем монитор по разным ключам const PhysicalMonitor* foundMonitor = nullptr; for (auto const& pair : physicalMonitorHandles) { const PhysicalMonitor& monitor = pair.second; // Проверяем разные варианты ключей if (pair.first == searchKey || monitor.name == searchKey || monitor.fullName == searchKey || monitor.physicalName == searchKey || monitor.deviceKey == searchKey || monitor.deviceID == searchKey) { foundMonitor = &monitor; break; } } if (foundMonitor == nullptr) { Napi::Error::New(env, "Monitor not found. Search key: " + searchKey).ThrowAsJavaScriptException(); return Napi::Array::New(env); } const PhysicalMonitor& monitor = *foundMonitor; std::string result = monitor.result; Napi::Array resultArray = Napi::Array::New(env); try { // Ищем подстроку с информацией о входах (VCP code 60) size_t inputStart = result.find("60("); if (inputStart == std::string::npos) { return resultArray; } size_t inputEnd = result.find(")", inputStart); if (inputEnd == std::string::npos) { return resultArray; } // Извлекаем подстроку с кодами входов std::string inputsStr = result.substr(inputStart + 3, inputEnd - inputStart - 3); // Разбиваем на отдельные коды std::vector inputCodes; std::istringstream iss(inputsStr); std::string code; while (std::getline(iss, code, ' ')) { if (!code.empty()) { inputCodes.push_back(code); } } if (inputCodes.empty()) { return resultArray; } // Получаем текущий вход монитора DWORD currentInput = 0; DWORD inputs = 0; BOOL success = GetVCPFeatureAndVCPFeatureReply( monitor.handle, (BYTE)0x60, NULL, ¤tInput, &inputs ); DWORD currentInput1 = 0; DWORD inputs1 = 0; BOOL success1 = GetVCPFeatureAndVCPFeatureReply( monitor.handle, (BYTE)0xDC, NULL, ¤tInput1, &inputs1 ); std::cout << inputs1 << "," << currentInput1; // Преобразуем текущий вход в число unsigned int currentCodeValue = 0; if (success) { std::stringstream ss; ss << std::hex << currentInput; ss >> currentCodeValue; } // Создаем массив всех доступных входов (только коды) Napi::Array availableInputs = Napi::Array::New(env); int availableIndex = 0; for (const auto& code : inputCodes) { // Преобразуем hex строку в число unsigned int codeValue; std::stringstream ss; ss << std::hex << code; ss >> codeValue; availableInputs.Set(uint32_t(availableIndex++), Napi::Number::New(env, codeValue)); } // Возвращаем массив из двух элементов resultArray.Set(uint32_t(0), Napi::Number::New(env, currentCodeValue)); // Первый элемент - текущий вход (число) resultArray.Set(uint32_t(1), availableInputs); // Второй элемент - массив всех входов (числа) } catch (const std::exception& e) { Napi::Error::New(env, std::string("Error parsing monitor inputs: ") + e.what()).ThrowAsJavaScriptException(); } return resultArray; } Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set("getMonitorList", Napi::Function::New(env, getMonitorList, "getMonitorList")); exports.Set("getAllMonitors", Napi::Function::New(env, getAllMonitors, "getAllMonitors")); exports.Set( "clearDisplayCache", Napi::Function::New(env, clearDisplayCache, "clearDisplayCache")); exports.Set("refresh", Napi::Function::New(env, refresh, "refresh")); exports.Set("setVCP", Napi::Function::New(env, setVCP, "setVCP")); exports.Set("getVCP", Napi::Function::New(env, getVCP, "getVCP")); exports.Set( "getCapabilitiesString", Napi::Function::New(env, getNAPICapabilitiesString, "getCapabilitiesString")); exports.Set( "saveCurrentSettings", Napi::Function::New(env, saveCurrentSettings, "saveCurrentSettings")); exports.Set("getHighLevelBrightness", Napi::Function::New(env, getHighLevelBrightness, "getHighLevelBrightness")); exports.Set("setHighLevelBrightness", Napi::Function::New(env, setHighLevelBrightness, "setHighLevelBrightness")); exports.Set("getHighLevelContrast", Napi::Function::New(env, getHighLevelContrast, "getHighLevelContrast")); exports.Set("setHighLevelContrast", Napi::Function::New(env, setHighLevelContrast, "setHighLevelContrast")); exports.Set("setLogLevel", Napi::Function::New(env, setLogLevel, "setLogLevel")); exports.Set("getMonitorInputs", Napi::Function::New(env, getMonitorInputs, "getMonitorInputs")); getAllHandles(); // Returns bad handles the first time?? return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init) ================================================ FILE: src/modules/node-ddcci/index.d.ts ================================================ export function _getVCP (monitorId: string, code: number): number; export function _setVCP (monitorId: string, code: number, value: number): void; export function _getCapabilities (monitorId: string): string; export function _saveCurrentSettings (monitorId: string): boolean; export function _refresh (): void; export function getMonitorList (): string[]; export function getMonitorInputs (monitorFullName: string): object[] export function getVCP (monitorId: string, code: number): number; export function setVCP (monitorId: string, code: number, value: number): void; export function getBrightness (monitorId: string): number; export function getMaxBrightness (monitorId: string): number; export function setBrightness (monitorId: string): void; export function getContrast (monitorId: string): number; export function getMaxContrast (monitorId: string): number; export function setContrast (monitorId: string): void; export function getCapabilities (monitorId: string): object; export const vcp: { CODE_PAGE: 0x00; RESTORE_FACTORY_COLOR_DEFAULTS: 0x08; RESTORE_FACTORY_DEFAULTS: 0x04; RESTORE_FACTORY_GEOMETRY_DEFAULTS: 0x06; RESTORE_FACTORY_LUMINANCE_CONTRAST_DEFAULTS: 0x05; RESTORE_FACTORY_TV_DEFAULTS: 0x0a; SAVE_RESTORE_SETTINGS: 0xb0; SIX_AXIS_HUE_CONTROL_BLUE: 0x9f; SIX_AXIS_HUE_CONTROL_CYAN: 0x9e; SIX_AXIS_HUE_CONTROL_GREEN: 0x9d; SIX_AXIS_HUE_CONTROL_MAGENTA: 0xa0; SIX_AXIS_HUE_CONTROL_RED: 0x9b; SIX_AXIS_HUE_CONTROL_YELLOW: 0x9c; SIX_AXIS_SATURATION_CONTROL_BLUE: 0x5d; SIX_AXIS_SATURATION_CONTROL_CYAN: 0x5c; SIX_AXIS_SATURATION_CONTROL_GREEN: 0x5b; SIX_AXIS_SATURATION_CONTROL_MAGENTA: 0x5e; SIX_AXIS_SATURATION_CONTROL_RED: 0x59; SIX_AXIS_SATURATION_CONTROL_YELLOW: 0x5a; ADJUST_ZOOM: 0x7c; AUTO_COLOR_SETUP: 0x1f; AUTO_SETUP: 0x1e; AUTO_SETUP_ON_OFF: 0xa2; BACKLIGHT_CONTROL: 0x13; BACKLIGHT_LEVEL_BLUE: 0x71; BACKLIGHT_LEVEL_GREEN: 0x6f; BACKLIGHT_LEVEL_RED: 0x6d; BACKLIGHT_LEVEL_WHITE: 0x6b; BLOCK_LUT_OPERATION: 0x75; CLOCK: 0x0e; CLOCK_PHASE: 0x3e; COLOR_SATURATION: 0x8a; COLOR_TEMPERATURE_INCREMENT: 0x0b; COLOR_TEMPERATURE_REQUEST: 0x0c; CONTRAST: 0x12; DISPLAY_APPLICATION: 0xdc; FLESH_TONE_ENHANCEMENT: 0x11; FOCUS: 0x1c; GAMMA: 0x72; GRAY_SCALE_EXPANSION: 0x2e; HORIZONTAL_MOIRE: 0x56; HUE: 0x90; LUMINANCE: 0x10; LUT_SIZE: 0x73; SCREEN_ORIENTATION: 0xaa; SELECT_COLOR_PRESET: 0x14; SHARPNESS: 0x87; SINGLE_POINT_LUT_OPERATION: 0x74; STEREO_VIDEO_MODE: 0xd4; TV_BLACK_LEVEL_LUMINANCE: 0x92; TV_CONTRAST: 0x8e; TV_SHARPNESS: 0x8c; USER_COLOR_VISION_COMPENSATION: 0x17; VELOCITY_SCAN_MODULATION: 0x88; VERTICAL_MOIRE: 0x58; VIDEO_BLACK_LEVEL_BLUE: 0x70; VIDEO_BLACK_LEVEL_GREEN: 0x6e; VIDEO_BLACK_LEVEL_RED: 0x6c; VIDEO_GAIN_BLUE: 0x1a; VIDEO_GAIN_GREEN: 0x18; VIDEO_GAIN_RED: 0x16; WINDOW_BACKGROUND: 0x9a; WINDOW_CONTROL_ON_OFF: 0xa4; WINDOW_SELECT: 0xa5; WINDOW_SIZE: 0xa6; WINDOW_TRANSPARENCY: 0xa7; DISPLAY_CONTROLLER_ID: 0xc8; DISPLAY_FIRMWARE_LEVEL: 0xc9; DISPLAY_USAGE_TIME: 0xc6; HORIZONTAL_FREQUENCY: 0xac; IMAGE_MODE: 0xdb; OSD_BUTTON_LEVEL_CONTROL: 0xca; OSD_LANGUAGE: 0xcc; POWER_MODE: 0xd6; SOURCE_COLOR_CODING: 0xb5; SOURCE_TIMING_MODE: 0xb4; VERSION: 0xdf; VERTICAL_FREQUENCY: 0xae; BOTTOM_CORNER_FLARE: 0x4a; BOTTOM_CORNER_HOOK: 0x4c; DISPLAY_SCALING: 0x86; HORIZONTAL_CONVERGENCE_M_G: 0x29; HORIZONTAL_CONVERGENCE_R_B: 0x28; HORIZONTAL_KEYSTONE: 0x42; HORIZONTAL_LINEARITY: 0x2a; HORIZONTAL_LINEARITY_BALANCE: 0x2c; HORIZONTAL_MIRROR: 0x82; HORIZONTAL_PARALLELOGRAM: 0x40; HORIZONTAL_PINCUSHION: 0x24; HORIZONTAL_PINCUSHION_BALANCE: 0x26; HORIZONTAL_POSITION: 0x20; HORIZONTAL_SIZE: 0x22; ROTATION: 0x44; SCAN_MODE: 0xda; TOP_CORNER_FLARE: 0x46; TOP_CORNER_HOOK: 0x48; VERTICAL_CONVERGENCE_M_G: 0x39; VERTICAL_CONVERGENCE_R_B: 0x38; VERTICAL_KEYSTONE: 0x43; VERTICAL_LINEARITY: 0x3a; VERTICAL_LINEARITY_BALANCE: 0x3c; VERTICAL_MIRROR: 0x84; VERTICAL_PARALLELOGRAM: 0x41; VERTICAL_PINCUSHION: 0x34; VERTICAL_PINCUSHION_BALANCE: 0x36; VERTICAL_POSITION: 0x30; VERTICAL_SIZE: 0x32; WINDOW_POSITION_BR_X: 0x97; WINDOW_POSITION_BR_Y: 0x98; WINDOW_POSITION_TL_X: 0x95; WINDOW_POSITION_TL_Y: 0x96; ACTIVE_CONTROL: 0x52; AMBIENT_LIGHT_SENSOR: 0x66; APPLICATION_ENABLE_KEY: 0xc6; ASSET_TAG: 0xd2; AUXILIARY_DISPLAY_DATA: 0xcf; AUXILIARY_DISPLAY_SIZE: 0xce; AUXILIARY_POWER_OUTPUT: 0xd7; DEGAUSS: 0x01; DISPLAY_DESCRIPTOR_LENGTH: 0xc2; DISPLAY_IDENTIFICATION_DATA_OPERATION: 0x87; DISPLAY_TECHNOLOGY_TYPE: 0xb6; ENABLE_DISPLAY_OF_DISPLAY_DESCRIPTOR: 0xc4; FLAT_PANEL_SUB_PIXEL_LAYOUT: 0xb2; INPUT_SOURCE: 0x60; NEW_CONTROL_VALUE: 0x02; OUTPUT_SELECT: 0xd0; PERFORMANCE_PRESERVATION: 0x54; REMOTE_PROCEDURE_CALL: 0x76; SCRATCH_PAD: 0xde; SOFT_CONTROLS: 0x03; STATUS_INDICATORS: 0xcd; TRANSMIT_DISPLAY_DESCRIPTOR: 0xc3; TV_CHANNEL_UP_DOWN: 0x8b; AUDIO_BALANCE_L_R: 0x93; AUDIO_BASS: 0x91; AUDIO_JACK_CONNECTION_STATUS: 0x65; AUDIO_MICROPHONE_VOLUME: 0x64; AUDIO_MUTE: 0x8d; AUDIO_PROCESSOR_MODE: 0x94; AUDIO_SPEAKER_SELECT: 0x63; AUDIO_SPEAKER_VOLUME: 0x62; AUDIO_TREBLE: 0x8f; BODY_CRC_ERROR_COUNT: 0xbc; CLIENT_ID: 0xbd; HEADER_ERROR_COUNT: 0xbb; LINK_CONTROL: 0xbe; MONITOR_STATUS: 0xb7; MONITOR_X_ORIGIN: 0xb9; MONITOR_Y_ORIGIN: 0xba; PACKET_COUNT: 0xb8; }; ================================================ FILE: src/modules/node-ddcci/index.js ================================================ "use strict"; const ddcci = require("bindings")("ddcci"); const vcp = require("./vcp"); module.exports = { vcp , _getVCP: ddcci.getVCP , _setVCP: ddcci.setVCP , _saveCurrentSettings: ddcci.saveCurrentSettings , _getHighLevelBrightness: ddcci.getHighLevelBrightness , _setHighLevelBrightness: ddcci.setHighLevelBrightness , _getHighLevelContrast: ddcci.getHighLevelContrast , _setHighLevelContrast: ddcci.setHighLevelContrast , _getAllMonitors: ddcci.getAllMonitors , _clearDisplayCache: ddcci.clearDisplayCache , _setLogLevel: ddcci.setLogLevel , _parseCapabilitiesString: parseCapabilitiesString , _refresh: (method = "accurate", usePreviousResults = true, checkHighLevel = true) => ddcci.refresh(method, usePreviousResults, checkHighLevel) , getMonitorList: (method = "accurate", usePreviousResults = true, checkHighLevel = true) => { ddcci.refresh(method, usePreviousResults, checkHighLevel); return ddcci.getMonitorList(); } , getAllMonitors: (method = "accurate", usePreviousResults = true, checkHighLevel = true) => { ddcci.refresh(method, usePreviousResults, checkHighLevel); const monitors = ddcci.getAllMonitors(); for (const monitor of monitors) { if (monitor.result && monitor.result != "ok" && monitor.result != "invalid") { monitor.capabilities = parseCapabilitiesString(monitor.result); monitor.capabilitiesRaw = monitor.result; } delete monitor.result; } return monitors; } , getMonitorInputs: (monitorFullName) => { ddcci.refresh("accurate", true, true) return ddcci.getMonitorInputs(monitorFullName) } , getVCP: ddcci.getVCP , setVCP: ddcci.setVCP , getBrightness(monitorId) { return ddcci.getVCP(monitorId, vcp.LUMINANCE)[0]; } , getMaxBrightness(monitorId) { return ddcci.getVCP(monitorId, vcp.LUMINANCE)[1]; } , getContrast(monitorId) { return ddcci.getVCP(monitorId, vcp.CONTRAST)[0]; } , getMaxContrast(monitorId) { return ddcci.getVCP(monitorId, vcp.CONTRAST)[1]; } , setBrightness(monitorId, level) { if (level < 0) { throw RangeError("Brightness level not within valid range"); } ddcci.setVCP(monitorId, vcp.LUMINANCE, level); } , setContrast(monitorId, level) { if (level < 0) { throw RangeError("Contrast level not within valid range"); } ddcci.setVCP(monitorId, vcp.CONTRAST, level); } // Returns an array where keys are valid VCP codes and the keys are an array of accepted values. // If the array of accepted values is empty, the VCP code either accepts a range of values or no values. Use getVCP to determine the range, if any. , getCapabilities(monitorId) { let report = ddcci.getCapabilitiesString(monitorId); return parseCapabilitiesString(report); } , getCapabilitiesRaw(monitorId) { return ddcci.getCapabilitiesString(monitorId); } }; function parseCapabilitiesString(report = "") { const start = report.indexOf('vcp('); // Find where VCP list starts // Only run if VCP list found if (start > 0) { let layers = 1; let output = ""; let position = start + 4; // Iterate through report string after the start of the list until we hit the end. // We'll check for nested parenthesis to correctly find the end of the list. while (layers > 0 && position + 1 < report.length) { const char = report[position]; if (char === "(") { layers++; } else if (char === ")") { layers--; if (layers <= 0) break; } output += char; position++; } // Strip out unnecessary characters output = output.replaceAll('\0', '').replaceAll(' ', '').trim(); // Iterate through the above string, alternating between parsing VCP codes and accepted values as needed const codeList = {}; let pos = 0 while (pos < output.length) { const cur = output[pos] pos++ // Check for VCP codes if (cur !== "(") { let vcpCode = `${cur}${output[pos]}` const vcpValues = [] pos++ // Check for defined values if (output[pos] == "(") { pos++ let depth = 0 while ((output[pos] != ")" && depth == 0) && pos < output.length) { // Check for subdata // I don't know what to do with this, so we'll just read through and ignore it. if (output[pos] == "(") { pos++ depth++ while (depth > 0 && pos < output.length) { if (output[pos] == "(") { depth++ } else if (output[pos] == ")") { depth-- } pos++ } } else { // Push defined value to list vcpValues.push(parseInt(`0x${output[pos]}${output[pos + 1]}`)) pos += 2 } } pos++ } // Add VCP code with defined values (if found) codeList[`0x${vcpCode.toUpperCase()}`] = vcpValues } } return codeList } return false; } ================================================ FILE: src/modules/node-ddcci/package.json ================================================ { "name": "@hensm/ddcci", "version": "0.1.0", "description": "NodeJS DDC/CI library", "main": "index.js", "author": "Matt Hensman <@matt.tf>", "license": "MIT", "bugs": { "url": "https://github.com/hensm/node-ddcci/issues" }, "repository": "github:hensm/node-ddcci", "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^2.0.0" }, "types": "index.d.ts", "devDependencies": { "@babel/core": "^7.28.5" } } ================================================ FILE: src/modules/node-ddcci/vcp.js ================================================ /** * Full list of MCCS v2.2a VCP codes. */ module.exports = { // 8.1 - Preset Functions CODE_PAGE: 0x00 , RESTORE_FACTORY_COLOR_DEFAULTS: 0x08 , RESTORE_FACTORY_DEFAULTS: 0x04 , RESTORE_FACTORY_GEOMETRY_DEFAULTS: 0x06 , RESTORE_FACTORY_LUMINANCE_CONTRAST_DEFAULTS: 0x05 , RESTORE_FACTORY_TV_DEFAULTS: 0x0a , SAVE_RESTORE_SETTINGS: 0xb0 // 8.2 - Image Adjustment , SIX_AXIS_HUE_CONTROL_BLUE: 0x9f , SIX_AXIS_HUE_CONTROL_CYAN: 0x9e , SIX_AXIS_HUE_CONTROL_GREEN: 0x9d , SIX_AXIS_HUE_CONTROL_MAGENTA: 0xa0 , SIX_AXIS_HUE_CONTROL_RED: 0x9b , SIX_AXIS_HUE_CONTROL_YELLOW: 0x9c , SIX_AXIS_SATURATION_CONTROL_BLUE: 0x5d , SIX_AXIS_SATURATION_CONTROL_CYAN: 0x5c , SIX_AXIS_SATURATION_CONTROL_GREEN: 0x5b , SIX_AXIS_SATURATION_CONTROL_MAGENTA: 0x5e , SIX_AXIS_SATURATION_CONTROL_RED: 0x59 , SIX_AXIS_SATURATION_CONTROL_YELLOW: 0x5a , ADJUST_ZOOM: 0x7c , AUTO_COLOR_SETUP: 0x1f , AUTO_SETUP: 0x1e , AUTO_SETUP_ON_OFF: 0xa2 , BACKLIGHT_CONTROL: 0x13 , BACKLIGHT_LEVEL_BLUE: 0x71 , BACKLIGHT_LEVEL_GREEN: 0x6f , BACKLIGHT_LEVEL_RED: 0x6d , BACKLIGHT_LEVEL_WHITE: 0x6b , BLOCK_LUT_OPERATION: 0x75 , CLOCK: 0x0e , CLOCK_PHASE: 0x3e , COLOR_SATURATION: 0x8a , COLOR_TEMPERATURE_INCREMENT: 0x0b , COLOR_TEMPERATURE_REQUEST: 0x0c , CONTRAST: 0x12 , DISPLAY_APPLICATION: 0xdc , FLESH_TONE_ENHANCEMENT: 0x11 , FOCUS: 0x1c , GAMMA: 0x72 , GRAY_SCALE_EXPANSION: 0x2e , HORIZONTAL_MOIRE: 0x56 , HUE: 0x90 , LUMINANCE: 0x10 , LUT_SIZE: 0x73 , SCREEN_ORIENTATION: 0xaa , SELECT_COLOR_PRESET: 0x14 , SHARPNESS: 0x87 , SINGLE_POINT_LUT_OPERATION: 0x74 , STEREO_VIDEO_MODE: 0xd4 , TV_BLACK_LEVEL_LUMINANCE: 0x92 , TV_CONTRAST: 0x8e , TV_SHARPNESS: 0x8c , USER_COLOR_VISION_COMPENSATION: 0x17 , VELOCITY_SCAN_MODULATION: 0x88 , VERTICAL_MOIRE: 0x58 , VIDEO_BLACK_LEVEL_BLUE: 0x70 , VIDEO_BLACK_LEVEL_GREEN: 0x6e , VIDEO_BLACK_LEVEL_RED: 0x6c , VIDEO_GAIN_BLUE: 0x1a , VIDEO_GAIN_GREEN: 0x18 , VIDEO_GAIN_RED: 0x16 , WINDOW_BACKGROUND: 0x9a , WINDOW_CONTROL_ON_OFF: 0xa4 , WINDOW_SELECT: 0xa5 , WINDOW_SIZE: 0xa6 , WINDOW_TRANSPARENCY: 0xa7 // 8.3 - Display Control , DISPLAY_CONTROLLER_ID: 0xc8 , DISPLAY_FIRMWARE_LEVEL: 0xc9 , DISPLAY_USAGE_TIME: 0xc6 , HORIZONTAL_FREQUENCY: 0xac , IMAGE_MODE: 0xdb , OSD_BUTTON_LEVEL_CONTROL: 0xca , OSD_LANGUAGE: 0xcc , POWER_MODE: 0xd6 , SOURCE_COLOR_CODING: 0xb5 , SOURCE_TIMING_MODE: 0xb4 , VERSION: 0xdf , VERTICAL_FREQUENCY: 0xae // 8.4 - Geometry , BOTTOM_CORNER_FLARE: 0x4a , BOTTOM_CORNER_HOOK: 0x4c , DISPLAY_SCALING: 0x86 , HORIZONTAL_CONVERGENCE_M_G: 0x29 , HORIZONTAL_CONVERGENCE_R_B: 0x28 , HORIZONTAL_KEYSTONE: 0x42 , HORIZONTAL_LINEARITY: 0x2a , HORIZONTAL_LINEARITY_BALANCE: 0x2c , HORIZONTAL_MIRROR: 0x82 , HORIZONTAL_PARALLELOGRAM: 0x40 , HORIZONTAL_PINCUSHION: 0x24 , HORIZONTAL_PINCUSHION_BALANCE: 0x26 , HORIZONTAL_POSITION: 0x20 , HORIZONTAL_SIZE: 0x22 , ROTATION: 0x44 , SCAN_MODE: 0xda , TOP_CORNER_FLARE: 0x46 , TOP_CORNER_HOOK: 0x48 , VERTICAL_CONVERGENCE_M_G: 0x39 , VERTICAL_CONVERGENCE_R_B: 0x38 , VERTICAL_KEYSTONE: 0x43 , VERTICAL_LINEARITY: 0x3a , VERTICAL_LINEARITY_BALANCE: 0x3c , VERTICAL_MIRROR: 0x84 , VERTICAL_PARALLELOGRAM: 0x41 , VERTICAL_PINCUSHION: 0x34 , VERTICAL_PINCUSHION_BALANCE: 0x36 , VERTICAL_POSITION: 0x30 , VERTICAL_SIZE: 0x32 , WINDOW_POSITION_BR_X: 0x97 , WINDOW_POSITION_BR_Y: 0x98 , WINDOW_POSITION_TL_X: 0x95 , WINDOW_POSITION_TL_Y: 0x96 // 8.5 - Miscellaneous , ACTIVE_CONTROL: 0x52 , AMBIENT_LIGHT_SENSOR: 0x66 , APPLICATION_ENABLE_KEY: 0xc6 , ASSET_TAG: 0xd2 , AUXILIARY_DISPLAY_DATA: 0xcf , AUXILIARY_DISPLAY_SIZE: 0xce , AUXILIARY_POWER_OUTPUT: 0xd7 , DEGAUSS: 0x01 , DISPLAY_DESCRIPTOR_LENGTH: 0xc2 , DISPLAY_IDENTIFICATION_DATA_OPERATION: 0x87 , DISPLAY_TECHNOLOGY_TYPE: 0xb6 , ENABLE_DISPLAY_OF_DISPLAY_DESCRIPTOR: 0xc4 , FLAT_PANEL_SUB_PIXEL_LAYOUT: 0xb2 , INPUT_SOURCE: 0x60 , NEW_CONTROL_VALUE: 0x02 , OUTPUT_SELECT: 0xd0 , PERFORMANCE_PRESERVATION: 0x54 , REMOTE_PROCEDURE_CALL: 0x76 , SCRATCH_PAD: 0xde , SOFT_CONTROLS: 0x03 , STATUS_INDICATORS: 0xcd , TRANSMIT_DISPLAY_DESCRIPTOR: 0xc3 , TV_CHANNEL_UP_DOWN: 0x8b // 8.6 - Audio Function , AUDIO_BALANCE_L_R: 0x93 , AUDIO_BASS: 0x91 , AUDIO_JACK_CONNECTION_STATUS: 0x65 , AUDIO_MICROPHONE_VOLUME: 0x64 , AUDIO_MUTE: 0x8d , AUDIO_PROCESSOR_MODE: 0x94 , AUDIO_SPEAKER_SELECT: 0x63 , AUDIO_SPEAKER_VOLUME: 0x62 , AUDIO_TREBLE: 0x8f // 8.7 - DPVL Support , BODY_CRC_ERROR_COUNT: 0xbc , CLIENT_ID: 0xbd , HEADER_ERROR_COUNT: 0xbb , LINK_CONTROL: 0xbe , MONITOR_STATUS: 0xb7 , MONITOR_X_ORIGIN: 0xb9 , MONITOR_Y_ORIGIN: 0xba , PACKET_COUNT: 0xb8 }; ================================================ FILE: src/modules/tt-windows-utils/.gitignore ================================================ node_modules *.log* build .vscode/ipch .history ================================================ FILE: src/modules/tt-windows-utils/binding.gyp ================================================ { "targets": [ { "target_name": "windows_window_utils", "cflags!": [ ], "cflags_cc!": [ ], "sources": [ "windows_window_utils.cc" ], "include_dirs": [ " { WindowMaterial.setWindowMaterial(hwnd, materialType, cornersType, (darkModeSupported ? 1 : 0)) }, setWindowAttribute: WindowMaterial.setWindowAttribute, setWindowCorners: (hwnd, cornerType = 0) => { WindowMaterial.setWindowAttribute(hwnd, 33, cornerType) }, setDarkModeSupported: (hwnd, enabled = 1) => { WindowMaterial.setWindowAttribute(hwnd, 20, enabled) }, setTransitionSupported: (hwnd, enabled = 1) => { WindowMaterial.setWindowAttribute(hwnd, 3, enabled) } } } ================================================ FILE: src/modules/tt-windows-utils/package.json ================================================ { "name": "tt-windows-utils", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "npm run rebuild", "rebuild": "node-gyp rebuild", "install": "npm run rebuild" }, "keywords": [], "author": "xanderfrangos", "license": "MIT", "bugs": {}, "homepage": "", "dependencies": { "bindings": "1.5.0", "node-addon-api": "^7.0.0" }, "files": [ "index.js", "binding.gyp", "windows_media_status.cc", "windows_power_events.cc", "windows_window_utils.cc" ] } ================================================ FILE: src/modules/tt-windows-utils/windows_app_startup.cc ================================================ #include #pragma comment(lib, "windowsapp") #include #include #include using namespace winrt; typedef winrt::Windows::ApplicationModel::StartupTask StartupTask; StartupTask getStartupTask() { try { winrt::Windows::Foundation::IAsyncOperation< winrt::Windows::Foundation::Collections::IVectorView> package_async = StartupTask::GetForCurrentPackageAsync(); if (package_async.wait_for(std::chrono::seconds{1}) != winrt::Windows::Foundation::AsyncStatus::Completed) { return NULL; } winrt::Windows::Foundation::Collections::IVectorView tasks = package_async.get(); for (auto &&task : tasks) { if (tasks != NULL) { return task; } } } catch (...) { return NULL; } return NULL; } Napi::Boolean Enable(const Napi::CallbackInfo &info) { try { StartupTask task = getStartupTask(); if (task != NULL) { task.RequestEnableAsync(); } return Napi::Boolean::New(info.Env(), true); } catch (...) { return Napi::Boolean::New(info.Env(), false); } } Napi::Boolean Disable(const Napi::CallbackInfo &info) { try { Windows::ApplicationModel::StartupTask task = getStartupTask(); if (task != NULL) { task.Disable(); } return Napi::Boolean::New(info.Env(), true); } catch (...) { return Napi::Boolean::New(info.Env(), false); } } Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set(Napi::String::New(env, "enable"), Napi::Function::New(env, Enable)); exports.Set(Napi::String::New(env, "disable"), Napi::Function::New(env, Disable)); return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init); ================================================ FILE: src/modules/tt-windows-utils/windows_media_status.cc ================================================ #include #pragma comment(lib, "windowsapp") #include #include #include #include #include using namespace winrt; using namespace Windows::Media::Control; typedef GlobalSystemMediaTransportControlsSessionManager GSMTCSM; typedef GlobalSystemMediaTransportControlsSessionPlaybackStatus SessionPlaybackStatus; typedef GlobalSystemMediaTransportControlsSessionMediaProperties MediaProperties; typedef Windows::Media::MediaPlaybackType MediaPlaybackType; Napi::String getPlaybackStatus(const Napi::CallbackInfo &info) { std::string statusStr = "closed"; try { auto session_async = GSMTCSM::RequestAsync(); if (session_async.wait_for(std::chrono::seconds{1}) != winrt::Windows::Foundation::AsyncStatus::Completed) { return Napi::String::New(info.Env(), statusStr); } GSMTCSM manager = session_async.get(); GlobalSystemMediaTransportControlsSession session = manager.GetCurrentSession(); if (session == NULL) return Napi::String::New(info.Env(), statusStr); SessionPlaybackStatus status = session.GetPlaybackInfo().PlaybackStatus(); switch (status) { case SessionPlaybackStatus::Opened: statusStr = "opened"; break; case SessionPlaybackStatus::Changing: statusStr = "changing"; break; case SessionPlaybackStatus::Stopped: statusStr = "stopped"; break; case SessionPlaybackStatus::Playing: statusStr = "playing"; break; case SessionPlaybackStatus::Paused: statusStr = "paused"; break; } } catch (...) { } return Napi::String::New(info.Env(), statusStr); } Napi::Object getPlaybackInfo(const Napi::CallbackInfo &info) { Napi::Object obj = Napi::Object::New(info.Env()); try { auto session_async = GSMTCSM::RequestAsync(); if (session_async.wait_for(std::chrono::seconds{1}) != winrt::Windows::Foundation::AsyncStatus::Completed) { return obj; } GSMTCSM manager = session_async.get(); GlobalSystemMediaTransportControlsSession session = manager.GetCurrentSession(); if (session == NULL) return obj; MediaProperties playback = session.TryGetMediaPropertiesAsync().get(); if (playback == NULL) return obj; obj.Set(Napi::String::New(info.Env(), "title"), Napi::String::New(info.Env(), winrt::to_string(playback.Title().c_str()))); obj.Set(Napi::String::New(info.Env(), "subtitle"), Napi::String::New(info.Env(), winrt::to_string(playback.Subtitle().c_str()))); obj.Set(Napi::String::New(info.Env(), "artist"), Napi::String::New(info.Env(), winrt::to_string(playback.Artist().c_str()))); obj.Set(Napi::String::New(info.Env(), "album"), Napi::String::New(info.Env(), winrt::to_string(playback.AlbumTitle().c_str()))); obj.Set(Napi::String::New(info.Env(), "albumartist"), Napi::String::New( info.Env(), winrt::to_string(playback.AlbumArtist().c_str()))); obj.Set(Napi::String::New(info.Env(), "source"), Napi::String::New( info.Env(), winrt::to_string(session.SourceAppUserModelId().c_str()))); obj.Set(Napi::String::New(info.Env(), "tracks"), Napi::Number::New(info.Env(), playback.AlbumTrackCount())); obj.Set(Napi::String::New(info.Env(), "tracknumber"), Napi::Number::New(info.Env(), playback.TrackNumber())); std::string typeStr = "unknown"; MediaPlaybackType type = playback.PlaybackType().Value(); switch (type) { case MediaPlaybackType::Music: typeStr = "music"; break; case MediaPlaybackType::Video: typeStr = "video"; break; case MediaPlaybackType::Image: typeStr = "image"; break; } obj.Set(Napi::String::New(info.Env(), "type"), Napi::String::New(info.Env(), typeStr)); } catch (...) { } return obj; } Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set(Napi::String::New(env, "getPlaybackStatus"), Napi::Function::New(env, getPlaybackStatus)); exports.Set(Napi::String::New(env, "getPlaybackInfo"), Napi::Function::New(env, getPlaybackInfo)); return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init); ================================================ FILE: src/modules/tt-windows-utils/windows_power_events.cc ================================================ #include #include std::string GUIDToString(const GUID guid) { wchar_t source[40]; int length = StringFromGUID2(guid, source, 40); if (length == 0) return ""; char dest[40]; wcstombs(dest, source, 40); return std::string(dest); } Napi::Object GetPowerSetting(const Napi::CallbackInfo& info) { std::string name = ""; Napi::Env env = info.Env(); Napi::Object obj = Napi::Object::New(env); try { Napi::BigInt lParamInt = info[0].As(); bool lossless; int64_t lParamValue = lParamInt.Int64Value(&lossless); int64_t* lParamPtr = (int64_t*)lParamValue; LPARAM lParam = (LPARAM)lParamPtr; POWERBROADCAST_SETTING* setting = reinterpret_cast(lParam); std::string guid = GUIDToString(setting->PowerSetting); obj.Set(Napi::String::New(env, "guid"), Napi::String::New(env, guid)); if(IsEqualGUID(setting->PowerSetting, GUID_CONSOLE_DISPLAY_STATE)) { name = "GUID_CONSOLE_DISPLAY_STATE"; } else if(IsEqualGUID(setting->PowerSetting, GUID_MONITOR_POWER_ON)) { name = "GUID_MONITOR_POWER_ON"; } else if(IsEqualGUID(setting->PowerSetting, GUID_SESSION_DISPLAY_STATUS)) { name = "GUID_SESSION_DISPLAY_STATUS"; } else if(IsEqualGUID(setting->PowerSetting, GUID_SYSTEM_AWAYMODE)) { name = "GUID_SYSTEM_AWAYMODE"; } else if(IsEqualGUID(setting->PowerSetting, GUID_LIDSWITCH_STATE_CHANGE)) { name = "GUID_LIDSWITCH_STATE_CHANGE"; } else if(IsEqualGUID(setting->PowerSetting, GUID_SESSION_USER_PRESENCE)) { name = "GUID_SESSION_USER_PRESENCE"; } else if(IsEqualGUID(setting->PowerSetting, GUID_STANDBY_TIMEOUT)) { name = "GUID_STANDBY_TIMEOUT"; } else if(IsEqualGUID(setting->PowerSetting, GUID_VIDEO_ADAPTIVE_DISPLAY_BRIGHTNESS)) { name = "GUID_VIDEO_ADAPTIVE_DISPLAY_BRIGHTNESS"; } else if(IsEqualGUID(setting->PowerSetting, GUID_VIDEO_ADAPTIVE_PERCENT_INCREASE)) { name = "GUID_VIDEO_ADAPTIVE_PERCENT_INCREASE"; } else if(IsEqualGUID(setting->PowerSetting, GUID_VIDEO_ADAPTIVE_POWERDOWN)) { name = "GUID_VIDEO_ADAPTIVE_POWERDOWN"; } else if(IsEqualGUID(setting->PowerSetting, GUID_VIDEO_DIM_TIMEOUT)) { name = "GUID_VIDEO_DIM_TIMEOUT"; } else if(IsEqualGUID(setting->PowerSetting, GUID_SLEEP_IDLE_THRESHOLD)) { name = "GUID_SLEEP_IDLE_THRESHOLD"; } else if(IsEqualGUID(setting->PowerSetting, GUID_VIDEO_CURRENT_MONITOR_BRIGHTNESS)) { name = "GUID_VIDEO_CURRENT_MONITOR_BRIGHTNESS"; } else if(IsEqualGUID(setting->PowerSetting, GUID_VIDEO_POWERDOWN_TIMEOUT)) { name = "GUID_VIDEO_POWERDOWN_TIMEOUT"; } obj.Set(Napi::String::New(env, "name"), Napi::String::New(env, name)); DWORD data = *reinterpret_cast(setting->Data); obj.Set(Napi::String::New(env, "data"), Napi::Number::New(env, data)); } catch (...) { } return obj; } Napi::Boolean RegisterPowerSettingNotifications(const Napi::CallbackInfo& info) { try { Napi::Number hwnd = info[0].As(); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_CONSOLE_DISPLAY_STATE, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_MONITOR_POWER_ON, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_SESSION_DISPLAY_STATUS, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_SYSTEM_AWAYMODE, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_LIDSWITCH_STATE_CHANGE, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_SESSION_USER_PRESENCE, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_STANDBY_TIMEOUT, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_VIDEO_ADAPTIVE_DISPLAY_BRIGHTNESS, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_VIDEO_ADAPTIVE_PERCENT_INCREASE, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_VIDEO_ADAPTIVE_POWERDOWN, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_VIDEO_DIM_TIMEOUT, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_SLEEP_IDLE_THRESHOLD, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_VIDEO_CURRENT_MONITOR_BRIGHTNESS, 0); RegisterPowerSettingNotification(reinterpret_cast(hwnd.Int32Value()), &GUID_VIDEO_POWERDOWN_TIMEOUT, 0); } catch (...) { return Napi::Boolean::New(info.Env(), false); } return Napi::Boolean::New(info.Env(), true); } Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set(Napi::String::New(env, "registerPowerSettingNotifications"), Napi::Function::New(env, RegisterPowerSettingNotifications)); exports.Set(Napi::String::New(env, "getPowerSetting"), Napi::Function::New(env, GetPowerSetting)); return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init) ================================================ FILE: src/modules/tt-windows-utils/windows_window_material.cc ================================================ #include #include #include #pragma comment(lib, "dwmapi.lib") Napi::Boolean SetWindowMaterial(const Napi::CallbackInfo &info) { Napi::Number hwnd = info[0].As(); Napi::Number backdrop = info[1].As(); Napi::Number corners = info[2].As(); Napi::Number mode = info[3].As(); int backdropType = backdrop.Int32Value(); int darkMode = mode.Int32Value(); int borderType = corners.Int32Value(); DwmSetWindowAttribute((HWND) hwnd.Int32Value(), 20, &darkMode, sizeof(darkMode)); // DWMWA_USE_IMMERSIVE_DARK_MODE: 20 DwmSetWindowAttribute((HWND) hwnd.Int32Value(), 38, &backdropType, sizeof(backdropType)); // DWMWA_SYSTEMBACKDROP_TYPE: 38 DwmSetWindowAttribute((HWND) hwnd.Int32Value(), 33, &borderType, sizeof(borderType)); // DWMWA_WINDOW_CORNER_PREFERENCE: 33 return Napi::Boolean::New(info.Env(), true); } Napi::Boolean SetWindowAttribute(const Napi::CallbackInfo &info) { Napi::Number hwnd = info[0].As(); Napi::Number type = info[1].As(); Napi::Number value = info[2].As(); int intval = value.Int32Value(); DwmSetWindowAttribute((HWND) hwnd.Int32Value(), (DWORD) type.Int32Value(), &intval, sizeof(intval)); return Napi::Boolean::New(info.Env(), true); } Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set(Napi::String::New(env, "setWindowMaterial"), Napi::Function::New(env, SetWindowMaterial)); exports.Set(Napi::String::New(env, "setWindowAttribute"), Napi::Function::New(env, SetWindowAttribute)); return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init); ================================================ FILE: src/modules/tt-windows-utils/windows_window_utils.cc ================================================ #include #include Napi::Boolean SetWindowPosition(const Napi::CallbackInfo& info) { Napi::Number hwnd = info[0].As(); Napi::Number hwndAfter = info[1].As(); Napi::Number X = info[2].As(); Napi::Number Y = info[3].As(); Napi::Number width = info[4].As(); Napi::Number height = info[5].As(); Napi::Number flags = info[6].As(); boolean result = SetWindowPos(reinterpret_cast(hwnd.Int32Value()), reinterpret_cast(hwndAfter.Int32Value()), X, Y, width, height, flags); return Napi::Boolean::New(info.Env(), result); } Napi::Object RectToObj(Napi::Env env, RECT rect) { Napi::Object pos = Napi::Object::New(env); pos.Set(Napi::String::New(env, "top"), Napi::Number::New(env, rect.top)); pos.Set(Napi::String::New(env, "right"), Napi::Number::New(env, rect.right)); pos.Set(Napi::String::New(env, "bottom"), Napi::Number::New(env, rect.bottom)); pos.Set(Napi::String::New(env, "left"), Napi::Number::New(env, rect.left)); pos.Set(Napi::String::New(env, "width"), Napi::Number::New(env, rect.right - rect.left)); pos.Set(Napi::String::New(env, "height"), Napi::Number::New(env, rect.bottom - rect.top)); return pos; } Napi::Object GetWindowPosition(const Napi::CallbackInfo& info) { Napi::Number hwnd = info[0].As(); RECT rect; GetWindowRect(reinterpret_cast(hwnd.Int32Value()), &rect); return RectToObj(info.Env(), rect); } Napi::Object GetClientPosition(const Napi::CallbackInfo& info) { Napi::Number hwnd = info[0].As(); RECT rect; GetClientRect(reinterpret_cast(hwnd.Int32Value()), &rect); return RectToObj(info.Env(), rect); } Napi::Boolean GetWindowFullscreen(const Napi::CallbackInfo& info) { HWND hwnd = reinterpret_cast(info[0].As().Int32Value()); MONITORINFO monitorInfo = { 0 }; monitorInfo.cbSize = sizeof(MONITORINFO); GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), &monitorInfo); RECT rect; GetWindowRect(hwnd, &rect); bool fullscreen = rect.left == monitorInfo.rcMonitor.left && rect.right == monitorInfo.rcMonitor.right && rect.top == monitorInfo.rcMonitor.top && rect.bottom == monitorInfo.rcMonitor.bottom; return Napi::Boolean::New(info.Env(), fullscreen); } Napi::Number GetForegroundWin(const Napi::CallbackInfo& info) { HWND result = GetForegroundWindow(); return Napi::Number::New(info.Env(), (long) result); } Napi::Boolean SetForegroundWin(const Napi::CallbackInfo& info) { Napi::Number hwnd = info[0].As(); boolean result = SetForegroundWindow(reinterpret_cast(hwnd.Int32Value())); return Napi::Boolean::New(info.Env(), result); } Napi::Number GetWinLong(const Napi::CallbackInfo& info) { Napi::Number hwnd = info[0].As(); Napi::Number index = info[1].As(); LONG_PTR result = GetWindowLongPtr(reinterpret_cast(hwnd.Int32Value()), (int) index.Int32Value()); return Napi::Number::New(info.Env(), result); } Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set(Napi::String::New(env, "setWindowPos"), Napi::Function::New(env, SetWindowPosition)); exports.Set(Napi::String::New(env, "getWindowPos"), Napi::Function::New(env, GetWindowPosition)); exports.Set(Napi::String::New(env, "getClientPos"), Napi::Function::New(env, GetClientPosition)); exports.Set(Napi::String::New(env, "getForegroundWindow"), Napi::Function::New(env, GetForegroundWin)); exports.Set(Napi::String::New(env, "setForegroundWindow"), Napi::Function::New(env, SetForegroundWin)); exports.Set(Napi::String::New(env, "getWindowLong"), Napi::Function::New(env, GetWinLong)); exports.Set(Napi::String::New(env, "getWindowFullscreen"), Napi::Function::New(env, GetWindowFullscreen)); return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init) ================================================ FILE: src/modules/win32-displayconfig/.gitignore ================================================ # dependencies node_modules/ # production build/ dist/ # misc .cache .DS_Store .env.local .env.development.local .env.test.local .env.production.local npm-debug.log* yarn-debug.log* yarn-error.log* .idea .log logs/ *.pfx .env cache/ ================================================ FILE: src/modules/win32-displayconfig/CONTRIBUTORS ================================================ Daniel Sweet (@djsweet) ================================================ FILE: src/modules/win32-displayconfig/COPYRIGHT ================================================ Copyright 2020 individuals listed in the CONTRIBUTORS file of this distribution. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: src/modules/win32-displayconfig/README.md ================================================ # win32-displayconfig Simplified Node bindings to the Win32 [Display Device Reference API](https://docs.microsoft.com/en-us/windows/win32/api/_display/). ## Supported Windows Versions This module has currently only received testing on Windows 10 version 2004. Additional testing on other versions of Windows 10 and Windows 8.1 would be appreciated. We are not planning on supporting Windows 7 or Windows 8, as they are generally unsupported by Microsoft. However, patches to support Windows 7 or Windows 8 are welcome. ## Supported Node Versions This module requires N-API Version 4, [bounding the minimum supported Node versions](https://nodejs.org/api/n-api.html#n_api_n_api_version_matrix) to 8.16.0 (without any support for Node 9), Node 10.16.0, and Node 11.8.0. We are only actively testing on Node 10.21 and above. We'll note incompatibilities and accept patches for Node 8 if the need arises. ## Functionality - Querying display devices, at a low and higher - Observing display device layout and output changes - Querying the vertical refresh rate at a given display point - Saving and restoring layouts via the Display Device Reference API ## Examples ### Querying Low-Level Display Device Information The `queryDisplayConfig` function returns data somewhat similar to the outputs of the [`QueryDisplayConfig` function](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-querydisplayconfig) via the `pathArray` and `modeInfoArray` properties, and naming and manufacturer info via its `nameArray` properties. From [`scripts/dumpquery.js`](scripts/dumpquery.js): ```javascript const w32disp = require("win32-displayconfig"); const util = require("util"); w32disp.queryDisplayConfig().then((config) => { // The outputs of `pathArray` and `modeArray` refer to // both parsed values and raw buffer values. The raw buffers // are the exact structs returned by the Win32 API, and are // used to save and restore display positioning configuration. const pathArray = config.pathArray.map((pa) => pa.value); const modeArray = config.modeArray.map((ma) => ma.value); console.log( util.inspect( // However, the `nameArray` only refers to parsed values. { pathArray, modeArray, nameArray: config.nameArray }, { depth: 10 } ) ); }); ``` Which outputs: ``` { pathArray: [ { flags: 1, sourceInfo: { adapterId: { LowPart: 945385802, HighPart: 0 }, id: 0, statusFlags: 1, modeInfoIdx: 1 }, targetInfo: { adapterId: { LowPart: 945385802, HighPart: 0 }, id: 114948, statusFlags: 1, outputTechnology: 'dvi', rotation: 0, scaling: 'identity', refreshRate: { Numerator: 60000, Denominator: 1000 }, scanLineOrdering: 'progressive', targetAvailable: 1, modeInfoIdx: 0 } }, ... ], modeArray: [ { infoType: 'target', id: 114948, adapterId: { LowPart: 945385802, HighPart: 0 }, targetMode: { targetVideoSignalInfo: { pixelRate: { lowPart: 148500000, highPart: 0 }, hSyncFreq: { Numerator: 148500000, Denominator: 2200 }, vSyncFreq: { Numerator: 60000, Denominator: 1000 }, activeSize: { cx: 1920, cy: 1080 }, totalSize: { cx: 2200, cy: 1125 }, videoStandard: 255, scanlineOrdering: 'progressive' } } }, ... ], nameArray: [ { adapterId: { LowPart: 945385802, HighPart: 0 }, id: 114948, deviceFlags: 5, outputTechnology: 'dvi', edidManufactureId: 29188, edidProductCodeId: 147, connectorInstance: 2, monitorFriendlyDeviceName: 'Acer X233H', monitorDevicePath: '\\\\?\\DISPLAY#ACR0093#5&326e05e0&0&UID114948#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}' }, ... ] } ``` This is generally lower-level output than you want. Consider using `extractDisplayConfig` instead. ### Querying Higher-Level Display Device Information The `extractDisplayConfig` function reshapes the output of `queryDisplayConfig` to be more useful to application programmers. Information from the `pathArray`, `modeInfoArray`, and `nameArray` properties of the output of `queryDisplayConfig` are all joined according to their IDs. From [`scripts/dumpextract.js`](scripts/dumpextract.js): ```javascript const w32disp = require("win32-displayconfig"); const util = require("util"); w32disp.extractDisplayConfig().then((output) => { console.log(util.inspect(output, { depth: 10 })); }); ``` Which outputs: ``` [ { displayName: 'Acer X233H', devicePath: '\\\\?\\DISPLAY#ACR0093#5&326e05e0&0&UID114948#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}', sourceConfigId: { adapterId: { LowPart: 945385802, HighPart: 0 }, id: 1 }, targetConfigId: { adapterId: { LowPart: 945385802, HighPart: 0 }, id: 114948 }, inUse: false, outputTechnology: 'dvi', rotation: 0, scaling: 'preferred', sourceMode: { width: 1920, height: 1080, pixelFormat: 32, position: { x: 0, y: 0 } }, pathBuffer: , sourceModeBuffer: , targetVideoSignalInfo: { pixelRate: { lowPart: 148500000, highPart: 0 }, hSyncFreq: { Numerator: 148500000, Denominator: 2200 }, vSyncFreq: { Numerator: 60000, Denominator: 1000 }, activeSize: { cx: 1920, cy: 1080 }, totalSize: { cx: 2200, cy: 1125 }, videoStandard: 255, scanlineOrdering: 'progressive' }, targetModeBuffer: }, ... ] ``` Note that the low-level buffers are still present, but `sourceMode`, `targetVideoSignalInfo`, `devicePath`, and `displayName` have all been combined from multiple sources. Also note the `inUse` boolean, which is derived from comparing against low-level flags in the Display Device Reference API. You will likely see multiple outputs for a single display device in this output, with only one of them having `inUse: true`. The `inUse: false` entries correspond to alternative output modes available on the device. ### Observing Display Device Layout and Output Changes The display geometry can change at any time during the execution of your program, but sometimes you depend on knowledge of this geometry for the correct behavior. You can observe changes as they occur using the `addDisplayChangeListener` function: ```javascript const w32disp = require("win32-displayconfig"); const listener1 = (err, conf) => { if (err !== null) { // Report error console.error(err); } else { // conf is the same as the output of extractDisplayConfig // ... } }; w32disp.addDisplayChangeListener(listener1); // Or equivalently const listener2 = w32disp.addDisplayChangeListener((err, conf) => { if (err !== null) { console.error(err); } else { // ... } }); ``` Adding these change listeners keeps the event loop active, even when all other activities have been stopped, so for situations where graceful shutdown is required, remove all of the listeners using the `removeDisplayChangeListener` function: ```javascript w32disp.removeDisplayChangeListener(listener1); w32disp.removeDisplayChangeListener(listener2); // No more display config activities are present on the event loop, // so Node can now exit cleanly. ``` ### Querying the Vertical Refresh Rate at a Display Point Some operations need to only occur as quickly as the vertical refresh rate for smooth performance. For example, many Windows positioning APIs cannot perform well if they are invoked any faster than the frame rate of the GPU. This module provides a `VerticalRefreshRateContext` class to determine the refresh rate of the displays servicing a given display point. Note that not all displays will necessarily have the same refresh rate, and many displays can be servicing the same display point. When multiple displays are servicing the same display point, the result is the minimum vertical refresh rate. ```javascript const { VerticalRefreshRateContext } = require("win32-displayconfig"); const ctx = new VerticalRefreshRateContext(); async function refreshRateForPoint(x, y) { // Here, x is the vertical offset and y is the horizontal offset. // These offsets are relative to the upper left hand corner of the // primary display, so they are allowed and expected to become negative. // // The result is either a number indicating the vertical refresh rate in Hz, // or undefined if the given point is not present in the display bounds of // the current display configuration. return await ctx.findVerticalRefreshRateForDisplayPoint(x, y); } // ... // This context reacts to underlying display changes, as a trade-off between // performance and accuracy. It does so using the `addDisplayChangeListener` // capabilities, so it needs to be disposed of properly to clear the event // loop for graceful shutdown. // // Call this when you are finished with the context. A good place to do so // is in the code that handles gracefully exiting your program. ctx.close(); ``` See [`scripts/watchmouse.js`](scripts/watchmouse.js) for a working example, polling for the refresh rate based on the mouse cursor position. ### Saving and Restoring Device Layouts This module can save and restore display device layouts (although it cannot directly modify them yet; patches welcome!). You can use this to implement a display configuration profile system. Saving a profile is achieved with the `displayConfigForRestoration` function: ```javascript const w32disp = require("win32-displayconfig"); async function saveDisplayConfig() { const conf = await w32disp.displayConfigForRestoration(); // The type of conf is JSON-safe: you can store this on the disk, // transmit it over a network, etc. return JSON.stringify(conf); } ``` And restoring a profile is achieved with the `restoreDisplayConfig` function: ```javascript const w32disp = require("win32-displayconfig"); async function restoreDisplayConfig(serialized, persistent) { // If "persistent", then this display configuration will be saved in Windows // as the default display configuration. This means that restoring to defaults // or rebooting will result in this exact configuration. persistent = !!persistent; const conf = JSON.parse(serialized); // If portions of the configuration refer to displays that are not actually // present, we make a best effort to enable all of the displays that are both // present and enabled in this configuration, and disable all other displays. // // Otherwise, the display configuration is set exactly. await w32disp.restoreDisplayConfig(conf); } ``` ## Copyright This module is available under the terms of the MIT license. See the [`COPYRIGHT`](COPYRIGHT) file for more information. ================================================ FILE: src/modules/win32-displayconfig/binding.gyp ================================================ { "variables": { "openssl_fips" : "0" }, "targets": [ { "target_name": "win32_displayconfig", "cflags!": ["-fno-exceptions"], "cflags_cc!": ["-fno-exceptions"], "conditions": [ ["OS=='win'", { "sources": ["win32-displayconfig.cc"] }], ], "include_dirs": [ "; interface ConfigId { adapterId: AdapterId; id: number; } export interface ExtractedDisplayConfig { displayName: string; devicePath: string; sourceConfigId: ConfigId; targetConfigId: ConfigId; inUse: boolean; outputTechnology: string; rotation: number; scaling: string; sourceMode: SourceMode; targetVideoSignalInfo?: TargetVideoSignalInfo; pathBuffer: Buffer; sourceModeBuffer: Buffer; targetModeBuffer?: Buffer; } export function extractDisplayConfig(): Promise; export interface ToggleEnabledDisplayArgs { enablePaths: string[]; disablePaths: string[]; persistent: boolean; } export function toggleEnabledDisplays( args: ToggleEnabledDisplayArgs ): Promise; export interface DisplayResotrationConfigurationEntry { devicePath: string; pathBuffer: string; sourceModeBuffer: string; targetModeBuffer: string; } export function displayConfigForRestoration(): Promise< DisplayResotrationConfigurationEntry[] >; export interface RestoreDisplayConfigArgs { config: DisplayResotrationConfigurationEntry[]; persistent: boolean; } export function restoreDisplayConfig( args: RestoreDisplayConfigArgs ): Promise; export type DisplayChangeListener = { (err: Error): void; (err: null, conf: ExtractedDisplayConfig): void; }; export function addDisplayChangeListener( listener: DisplayChangeListener ): DisplayChangeListener; export function removeDisplayChangeListener( listener: DisplayChangeListener ): void; export class VerticalRefreshRateContext { findVerticalRefreshRateForDisplayPoint( x: number, y: number ): Promise; close(): void; } ================================================ FILE: src/modules/win32-displayconfig/index.js ================================================ /* * index.js: part of the "win32-displayconfig" Node package. * See the COPYRIGHT file at the top-level directory of this distribution. */ "use strict"; const addon = require("bindings")("./win32_displayconfig"); /** * Represents a numeric error code returned from the Win32 API. * * @member {number} code is the exact numeric code returned by the Win32 API. */ class Win32Error extends Error { constructor(code) { super(`Win32 error code ${code}`); this.code = code; } } module.exports.Win32Error = Win32Error; /** * @typedef AdapterId * @type {object} * @property {number} LowPart * @property {number} HighPart */ /** * @typedef DisplayConfigFractional * @type {object} * @property {number} Numerator * @property {number} Denominator */ /** * @typedef SourcePathInfo * @type {object} * @property {AdapterId} adapterId * @property {number} id * @property {number} statusFlags * @property {number} modeInfoIdx */ /** * @typedef TargetPathInfo * @type {object} * @property {AdapterId} adapterId * @property {number} id * @property {number} statusFlags * @property {string} outputTechnology * @property {number} rotation * @property {string} scaling * @property {DisplayConfigFractional} refreshRate * @property {string} scanlineOrdering * @property {number} targetAvailable * @property {number} modeInfoIdx */ /** * @typedef PathInfoValue * @type {object} * @property {number} flags * @property {SourcePathInfo} sourceInfo * @property {TargetPathInfo} targetInfo */ /** * @typedef PathInfo * @type {object} * @property {PathInfoValue} value * @property {Buffer} buffer */ /** * @typedef DisplayConfigPosition * @type {object} * @property {number} x * @property {number} y */ /** * @typedef SourceMode * @type {object} * @property {number} width * @property {number} height * @property {number} pixelFormat * @property {DisplayConfigPosition} position */ /** * @typedef SourceModeInfo * @type {object} * @property {AdapterId} adapterId * @property {number} id * @property {"source"} infoType * @property {SourceMode} sourceMode */ /** * @typedef PixelRate * @type {object} * @property {number} lowPart * @property {number} highPart */ /** * @typedef DisplayConfigSize * @type {object} * @property {number} cx * @property {number} cy */ /** * @typedef TargetVideoSignalInfo * @type {object} * @property {PixelRate} pixelRate * @property {DisplayConfigFractional} hSyncFreq * @property {DisplayConfigFractional} vSyncFreq * @property {DisplayConfigSize} activeSize * @property {DisplayConfigSize} totalSize * @property {number} videoStandard * @property {string} scanlineOrdering */ /** * @typedef TargetMode * @type {object} * @property {TargetVideoSignalInfo} targetVideoSignalInfo */ /** * @typedef TargetModeInfo * @type {object} * @property {AdapterId} adapterId * @property {number} id * @property {"target"} infoType * @property {TargetMode} targetMode */ /** * @typedef ModeInfoValue * @type {SourceModeInfo | TargetModeInfo} */ /** * @typedef ModeInfo * @type {object} * @property {ModeInfoValue} value * @property {Buffer} buffer */ /** * @typedef NameInfo * @type {object} * @property {AdapterId} adapterId * @property {number} id * @property {string} outputTechnology * @property {number} edidManufactureId * @property {number} edidProductCodeId * @property {number} connectorInstance * @property {string} monitorFriendlyDeviceName * @property {string} monitorDevicePath */ /** * @typedef QueryDisplayConfigResults * @type {object} * @property {PathInfo[]} pathArray * @property {ModeInfo[]} modeInfoArray * @property {NameInfo[]} nameArray */ /** * Retrieves low-level information from the Win32 API QueryDisplayConfig. * * The output of this function somewhat matches the "output" values of * QueryDisplayConfig, as documented at * https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-querydisplayconfig, * in the pathArray and modeInfoArray results. * * Additionally, this function uses the DisplayConfigGetDeviceInfo function over * all resolved displays to return the names, output technology, and manufacturer IDs * in the nameArray results. * * @returns {Promise} * A Promise, resolving to { pathArray: [...], modeInfoArray: [...], nameArray: [...] }, * or rejecting with a {@link Win32Error} if something goes wrong. */ module.exports.queryDisplayConfig = () => { return new Promise((resolve, reject) => { const ran = addon.win32_queryDisplayConfig((err, result) => { if (err !== null) { reject(new Win32Error(err)); } else { resolve(result); } }); if (!ran) { resolve(undefined); } }); }; /** * @typedef ConfigId * @type {object} * @property {AdapterId} adapterId * @property {number} id */ /** * @typedef ExtractedDisplayConfig * @type {object} * @property {string} displayName The "friendly name" of the relevant display * @property {string} devicePath The Windows NT device path of the relevant display * @property {ConfigId} sourceConfigId * @property {ConfigId} targetConfigId * @property {boolean} inUse Whether this configuration is currently being used * @property {string} outputTechnology * @property {number} rotation * @property {string} scaling * @property {SourceMode} sourceMode * @property {TargetVideoSignalInfo | undefined} targetVideoSignalInfo * @property {Buffer} pathBuffer A Buffer containing the exact DISPLAYCONFIG_PATH_INFO struct * returned by QueryDisplayConfig for this configuration * @property {Buffer} sourceModeBuffer A Buffer containing the exact DISPLAYCONFIG_MODE_INFO * source struct returned by QueryDisplayConfig for this configuration * @property {Buffer | undefined} targetModeBuffer A Buffer containing the exact DISPLAYCONFIG_MODE_INFO * target struct returned by QueryDisplayConfig for this configuration */ /** * Retrieves higher-level information from the Win32 API QueryDisplayConfig. * * Unlike {@link queryDisplayConfig}, this function pulls all relevant information * about a device/mode pairing into a single object. * * @returns {Promise} A Promise, resolving to display configuration information * or rejecting with a {@link Win32Error} if something goes wrong. */ module.exports.extractDisplayConfig = async () => { const config = await module.exports.queryDisplayConfig(); const ret = []; for (const { value, buffer: pathBuffer } of config.pathArray) { let inUse = value.flags & (1 === 1) ? true : false; const { sourceInfo, targetInfo } = value; const { modeInfoIdx: sourceModeIdx, adapterId: sourceAdapterId, id: sourceId, } = sourceInfo; const { adapterId, id, outputTechnology, rotation, scaling, modeInfoIdx: targetModeIdx, } = targetInfo; const sourceConfigId = { adapterId: sourceAdapterId, id: sourceId, }; const targetConfigId = { adapterId, id, }; const displayNameEntry = config.nameArray.find( (n) => n.adapterId.LowPart === adapterId.LowPart && n.adapterId.HighPart === adapterId.HighPart && n.id === id && n.outputTechnology && outputTechnology && n.monitorDevicePath.length > 0 ); if (displayNameEntry === undefined) { continue; } const sourceMode = config.modeArray[sourceModeIdx]; const targetMode = config.modeArray[targetModeIdx]; if (sourceMode === undefined) { continue; } if (targetMode === undefined) { // When we can't find the target mode, but _can_ // find the source mode, that just means the monitor is off. inUse = false; } const sourceModeValue = sourceMode.value; if (sourceModeValue.infoType !== "source") { continue; } const { monitorFriendlyDeviceName, monitorDevicePath } = displayNameEntry; const output = { displayName: monitorFriendlyDeviceName, devicePath: monitorDevicePath, sourceConfigId, targetConfigId, inUse, outputTechnology, rotation, scaling, sourceMode: sourceModeValue.sourceMode, pathBuffer, sourceModeBuffer: sourceMode.buffer, }; if (targetMode !== undefined) { const targetModeValue = targetMode.value; if (targetModeValue.infoType === "target") { output.targetVideoSignalInfo = targetModeValue.targetMode.targetVideoSignalInfo; output.targetModeBuffer = targetMode.buffer; } } ret.push(output); } return ret; }; async function win32_toggleEnabledDisplays(args) { return new Promise((resolve, reject) => { const ran = addon.win32_toggleEnabledDisplays(args, (_, errorCode) => { if (errorCode === 0) { resolve(); } else { reject(new Win32Error(errorCode)); } }); if (!ran) { resolve(); } }); } /** * @typedef ToggleEnabledDisplaysArgs * @type {object} * @property {string[]} enablePaths Exact Windows NT device paths of the displays to enable * @property {string[]} disablePaths Exact Windows NT device paths of the displays to disable * @property {boolean} persistent Whether to save this configuration as the default configuration */ /** * Toggles enabled/disabled state of the given displays. * * If "persistent", then this is saved between restarts. * * @param {ToggleEnabledDisplaysArgs} args */ module.exports.toggleEnabledDisplays = async (args) => { const { persistent, enable: enablePaths, disable: disablePaths } = args; const enable = []; const disable = []; const displayConfig = await module.exports.extractDisplayConfig(); for (const { devicePath, targetConfigId } of displayConfig) { if (Array.isArray(enablePaths) && enablePaths.indexOf(devicePath) >= 0) { enable.push(targetConfigId); } if (Array.isArray(disablePaths) && disablePaths.indexOf(devicePath) >= 0) { disable.push(targetConfigId); } } await win32_toggleEnabledDisplays({ enable, disable, persistent }); }; function setSubtract(left, right) { const ret = new Set(); for (const entry of left) { if (!right.has(entry)) { ret.add(entry); } } return Array.from(ret); } function devicePathLookupForEnabledDisplayConfig(conf) { const ret = {}; for (const entry of conf) { if (entry.inUse && entry.targetModeBuffer === undefined) { continue; } if (ret[entry.devicePath] !== undefined) { continue; } ret[entry.devicePath] = entry; } return ret; } /** * @typedef DisplayRestorationConfigurationEntry * @type {object} * @property {string} devicePath * @property {string} pathBuffer A Base-64 encoded binary blob representing * a DISPLAYCONFIG_PATH_INFO instance for the given devicePath * @property {string} sourceModeBuffer A Base-64 encoded binary blob representing * a DISPLAYCONFIG_MODE_INFO source instance for the given devicePath * @property {string} targetModeBuffer A Base-64 encoded binary blob representing * a DISPLAYCONFIG_MODE_INFO target instance for the given devicePath */ /** * Returns a display configuration suitable for restoration with {@link restoreDisplayConfig}. * * @returns {DisplayRestorationConfigurationEntry[]} */ module.exports.displayConfigForRestoration = async () => { const currentConfig = await module.exports.extractDisplayConfig(); const ret = []; for (const entry of currentConfig) { if (!entry.inUse || entry.targetModeBuffer === undefined) { continue; } const { devicePath, pathBuffer, sourceModeBuffer, targetModeBuffer, } = entry; ret.push({ devicePath, pathBuffer: pathBuffer.toString("base64"), sourceModeBuffer: sourceModeBuffer.toString("base64"), targetModeBuffer: targetModeBuffer.toString("base64"), }); } return ret; }; async function win32_restoreDisplayConfig(configs, persistent) { return new Promise((resolve, reject) => { const ran = addon.win32_restoreDisplayConfig( configs, (_, errorCode) => { if (errorCode === 0) { resolve(); } else { reject(new Win32Error(errorCode)); } }, persistent ); if (!ran) { resolve(); } }); } /** * @typedef RestoreDisplayConfigArgs * @type {object} * @property {DisplayRestorationConfigurationEntry[]} config * @property {boolean} persistent Whether to save this configuration as the default configuration */ /** * Restores a display configuration derived from {@link displayConfigForRestoration}. * * If the given configuration refers to enabled displays that are not currently attached, * this function simply enables the displays known to the given configuration and * disables all attached displays not known to the given configuration. Otherwise, * the given configuration is applied to the display set. * * @param {RestoreDisplayConfigArgs} args */ module.exports.restoreDisplayConfig = async (args) => { const devicePathNames = args.config .filter(({ targetModeBuffer }) => targetModeBuffer !== undefined) .map(({ devicePath }) => devicePath); const currentConfig = await module.exports.extractDisplayConfig(); const givenAsSet = new Set(currentConfig.map(({ devicePath }) => devicePath)); const expectedEnabledAsSet = new Set(devicePathNames); const missingEnabled = setSubtract(expectedEnabledAsSet, givenAsSet); // Here's the idea behind this: // We have a set of monitors we want enabled, and a set of monitors that are enabled. // Ideally, these should be identical sets. But it's also possible that // // 1. The current state has strictly more enabled monitors than the expected state // 2. The current state has strictly fewer enabled monitors than the expected state // 3. The current state has some monitors that are missing, and some that are unexpected. // // What we're about to do here is coerce the monitor state to the expected state; if more // monitors are enabled or disabled in the given state then that's fine, we're correcting // that away. The trick here is that the monitors in the expected state we _do_ want to // enable have to exist in the first place (we don't care about the ones we want to disable, // missing is also disabled if you squint hard enough). if (missingEnabled.length === 0) { const pathLookup = devicePathLookupForEnabledDisplayConfig(currentConfig); const coercedState = []; for (const entry of args.config) { if (entry.targetModeBuffer === undefined) { continue; } const currentConfigEntry = pathLookup[entry.devicePath]; if (currentConfigEntry === undefined) { continue; } const { sourceConfigId, targetConfigId } = currentConfigEntry; const { pathBuffer, sourceModeBuffer, targetModeBuffer } = entry; coercedState.push({ sourceConfigId, targetConfigId, pathBuffer: Buffer.from(pathBuffer, "base64"), sourceModeBuffer: Buffer.from(sourceModeBuffer, "base64"), targetModeBuffer: Buffer.from(targetModeBuffer, "base64"), }); } await win32_restoreDisplayConfig(coercedState, args.persistent); } else { const seen = new Set(); const enable = []; const disable = []; const notInUse = args.config .filter(({ targetModeBuffer }) => targetModeBuffer === undefined) .map(({ devicePath }) => devicePath); for (const devicePathName of devicePathNames) { if (!seen.has(devicePathName) && givenAsSet.has(devicePathName)) { enable.push(devicePathName); seen.add(devicePathName); } } for (const devicePathName of notInUse) { if (!seen.has(devicePathName) && givenAsSet.has(devicePathName)) { disable.push(devicePathName); seen.add(devicePathName); } } await module.exports.toggleEnabledDisplays({ enable, disable, persistent: args.persistent, }); } }; let currentDisplayConfig; const displayChangeCallbacks = new Set(); async function updateDisplayStateAndNotifyCallbacks() { try { currentDisplayConfig = await module.exports.extractDisplayConfig(); for (const callback of Array.from(displayChangeCallbacks)) { callback(null, currentDisplayConfig); } } catch (e) { for (const callback of Array.from(displayChangeCallbacks)) { callback(e); } } } let currentDisplayConfigPromise = updateDisplayStateAndNotifyCallbacks(); function setupListenForDisplayChanges() { addon.win32_listenForDisplayChanges((err) => { if (err === null) { currentDisplayConfigPromise = currentDisplayConfigPromise.then(() => updateDisplayStateAndNotifyCallbacks() ); } }); } /** * Registers a display change listener. * * This function will be called immediately upon registration, receiving the * current display configuration. It will also be called every time the display * configuration changes in Windows, e.g. when users attach or rearrange new * displays, or alter the output resolution of already-attached displays. * * Note that the Node event loop will continue executing if any outstanding change * listeners are registered, precluding graceful shutdown. Use {@link removeDisplayChangeListener} * to remove outstanding display change listeners and clear the event loop. * * @param {function(Error | null, ExtractedDisplayConfig | undefined): void} listener * @returns {function(Error | null, ExtractedDisplayConfig | undefined): void} the listener argument as passed */ module.exports.addDisplayChangeListener = (listener) => { if (displayChangeCallbacks.size === 0) { setupListenForDisplayChanges(); } displayChangeCallbacks.add(listener); if (currentDisplayConfig !== undefined) { listener(null, currentDisplayConfig); } return listener; }; /** * De-registers a display change listener. * * De-registering all display change listeners clears the event loop of pending * work started by {@link addDisplayChangeListener} to allow for a graceful shutdown. * * @param {function(Error | null, ExtractedDisplayConfig | undefined): void} listener previously passed to {@link addDisplayChangeListener} */ module.exports.removeDisplayChangeListener = (listener) => { displayChangeCallbacks.delete(listener); if (displayChangeCallbacks.size === 0) { addon.win32_stopListeningForDisplayChanges(); } }; /** * Establishes a context for determining the vertical refresh rate. * * Active instances of this class will establish perpetual work on the event loop, * as the internals use {@link addDisplayChangeListener} to react to display changes. * * In order to clear the relevant work on the Node event loop, you must call * {@link VerticalRefreshRateContext.close} when you are finished using this context. */ class VerticalRefreshRateContext { constructor() { let readyPromiseResolver; let readyPromiseResolved = false; this.readyPromise = new Promise((resolve) => { readyPromiseResolver = () => { if (readyPromiseResolved) return; readyPromiseResolved = true; resolve(); }; }); this.geometry = []; const computeDisplayGeometryFromConfig = (err, conf) => { if (err !== null) { return; } const geom = []; for (const { sourceMode, targetVideoSignalInfo, inUse } of conf) { if (!inUse) { continue; } const { width, height, position } = sourceMode; const { vSyncFreq } = targetVideoSignalInfo; // 30Hz is a safe guess for broken vSyncFreq outputs, I think... const vRefreshRate = vSyncFreq.Numerator === 0 || vSyncFreq.Denominator === 0 ? 30 : vSyncFreq.Numerator / vSyncFreq.Denominator; const top = position.y; const bottom = position.y + height; const left = position.x; const right = position.x + width; geom.push({ top, bottom, left, right, vRefreshRate }); } this.geometry = geom; readyPromiseResolver(); }; this.changeListener = module.exports.addDisplayChangeListener( computeDisplayGeometryFromConfig ); } /** * Computes the vertical refresh rate of the displays at a given display point. * * If any displays overlap at the given display point, the return result will * be the minimum of the vertical refresh rates of each physical device displaying * at that effective point. * * This method is asynchronous due to the implementation of addDisplayChangeListener; * it waits for a valid display configuration to be captured before returning the * best possible refresh rate. * * @param {number} x The vertical offset of the display point * @param {number} y The horizontal offset of the display point * * @returns {number | undefined} The vertical refresh rate at the given display point, * or undefined if the given display point is out of bounds of the available display space. */ async findVerticalRefreshRateForDisplayPoint(x, y) { await this.readyPromise; let ret; for (const { top, bottom, left, right, vRefreshRate } of this.geometry) { if (left <= x && x < right && top <= y && y < bottom) { ret = ret === undefined ? vRefreshRate : Math.min(ret, vRefreshRate); } } return ret; } /** * Disconnects this instance from display change events. * * Disconnecting the instance from display change events will clear relevant * work items off of the event loop as per {@link removeDisplayChangeListener}. */ close() { module.exports.removeDisplayChangeListener(this.changeListener); } } module.exports.VerticalRefreshRateContext = VerticalRefreshRateContext; ================================================ FILE: src/modules/win32-displayconfig/package.json ================================================ { "name": "win32-displayconfig", "version": "0.1.0", "description": "Inspect and reconfigure displays in Windows", "main": "index.js", "scripts": { "rebuild": "node-gyp rebuild", "install": "npm run rebuild" }, "repository": { "type": "git", "url": "https://github.com/djsweet/win32-displayconfig.git" }, "keywords": [ "windows" ], "author": "djsweet", "license": "MIT", "bugs": { "url": "https://github.com/djsweet/win32-displayconfig/issues" }, "homepage": "https://github.com/djsweet/win32-displayconfig#readme", "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^8.2.2", "node-gyp": "^10.2.0" }, "devDependencies": { "@types/node": "^14.0.27", "typescript": "^3.9.7" }, "engines": { "node": ">=10.16 <11 || >= 11.8" }, "files": [ "CONTRIBUTORS", "COPYRIGHT", "index.js", "index.d.ts", "binding.gyp", "win32-displayconfig.cc" ] } ================================================ FILE: src/modules/win32-displayconfig/scripts/dumpextract.js ================================================ /* * scripts/dumpextract.js: part of the "win32-displayconfig" Node package. * See the COPYRIGHT file at the top-level directory of this distribution. */ "use strict"; const w32mon = require("../index"); const util = require("util"); w32mon.extractDisplayConfig().then((output) => { console.log(util.inspect(output, { depth: 10 })); }); ================================================ FILE: src/modules/win32-displayconfig/scripts/dumpquery.js ================================================ /* * scripts/dumpquery.js: part of the "win32-displayconfig" Node package. * See the COPYRIGHT file at the top-level directory of this distribution. */ "use strict"; const w32mon = require("../index"); const util = require("util"); w32mon.queryDisplayConfig().then((config) => { const pathArray = config.pathArray.map((pa) => pa.value); const modeArray = config.modeArray.map((ma) => ma.value); console.log( util.inspect( { pathArray, modeArray, nameArray: config.nameArray }, { depth: 10 } ) ); }); ================================================ FILE: src/modules/win32-displayconfig/scripts/watchmouse.js ================================================ /* * scripts/watchmouse.js: part of the "win32-displayconfig" Node package. * See the COPYRIGHT file at the top-level directory of this distribution. */ "use strict"; const robotjs = require("robotjs"); const { VerticalRefreshRateContext } = require("../index"); const ctx = new VerticalRefreshRateContext(); let didShutdown = false; let outstanding = 0; setTimeout(() => { ctx.close(); didShutdown = true; console.log(`Shutting down with ${outstanding} outstanding`); }, 60 * 1000); const pollInterval = setInterval(async () => { outstanding++; if (didShutdown) { clearInterval(pollInterval); outstanding--; return; } const pos = robotjs.getMousePos(); const refreshRate = await ctx.findVerticalRefreshRateForDisplayPoint( pos.x, pos.y ); console.log( `Refresh rate for position ${pos.x}, ${ pos.y }: ${refreshRate} with ${outstanding--} outstanding` ); }, 250); ================================================ FILE: src/modules/win32-displayconfig/win32-displayconfig.cc ================================================ /* * win32-displayconfig.cc: part of the "win32-displayconfig" Node package. * See the COPYRIGHT file at the top-level directory of this distribution. */ #define NAPI_VERSION 4 #include #include #include #include #include #include const int DEVICE_NAME_SIZE = 64; // 64 comes from DISPLAYCONFIG_TARGET_DEVICE_NAME.monitorFriendlyDeviceName const int DEVICE_PATH_SIZE = 128; // 128 comes from DISPLAYCONFIG_TARGET_DEVICE_NAME.monitorDevicePath struct Win32DeviceNameInfo { // Apparently, the adapterId is _not_ persistent between reboots. // And yet, the id is. So we likely want to find a better name. LUID adapterId; UINT32 id; DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS deviceFlags; DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology; UINT16 edidManufactureId; UINT16 edidProductCodeId; UINT32 connectorInstance; WCHAR monitorFriendlyDeviceName[DEVICE_NAME_SIZE]; WCHAR monitorDevicePath[DEVICE_PATH_SIZE]; }; struct Win32QueryDisplayConfigResults { Win32QueryDisplayConfigResults(UINT32 cPathInfo, UINT32 cModeInfo) : error(ERROR_SUCCESS) { this->rgPathInfo = std::vector(cPathInfo); this->rgModeInfo = std::vector(cModeInfo); this->rgNameInfo = std::vector(); } std::vector rgPathInfo; std::vector rgModeInfo; std::vector rgNameInfo; LONG error; BOOL faultWasBuffer; }; struct Win32TransientDeviceId { LUID adapterId; UINT32 id; }; struct Win32DeviceConfigToggleEnabled { Win32DeviceConfigToggleEnabled() : enable(), disable() {} BOOL persistent; std::vector enable; std::vector disable; }; struct Win32RestoreDisplayConfigDevice { struct Win32TransientDeviceId sourceId; struct Win32TransientDeviceId targetId; DISPLAYCONFIG_PATH_INFO pathInfo; DISPLAYCONFIG_MODE_INFO sourceModeInfo; DISPLAYCONFIG_MODE_INFO targetModeInfo; }; DWORD RunDisplayChangeContextLoop(LPVOID lpParam); class Win32DisplayChangeContext { public: Win32DisplayChangeContext(Napi::Env env, Napi::Function &callback) : running(), dwThreadId(0) { this->running.store(TRUE); this->hThread = NULL; this->tsfn = Napi::ThreadSafeFunction::New( env, callback, "Win32DisplayChangeContext thread", 512, 1); } DWORD Start() { this->hThread = CreateThread(NULL, 0, RunDisplayChangeContextLoop, this, 0, &this->dwThreadId); if (this->hThread == NULL) { this->tsfn.Release(); return GetLastError(); } else { return ERROR_SUCCESS; } } void Stop() { if (this->running.load() == FALSE) { return; } this->running.store(FALSE); if (this->hThread != NULL) { PostThreadMessage(this->dwThreadId, WM_USER, 0, 0); WaitForSingleObject(this->hThread, INFINITE); CloseHandle(this->hThread); this->tsfn.Release(); } } std::atomic running; HANDLE hThread; Napi::ThreadSafeFunction tsfn; DWORD dwThreadId; }; void HandleDisplayChangeError(Napi::Env env, Napi::Function callback, LPVOID error) { #pragma warning(push) #pragma warning(disable : 4311 4302) callback.Call(env.Global(), {Napi::Number::New(env, (DWORD)error)}); #pragma warning(pop) } void HandleDisplayChangeSuccess(Napi::Env env, Napi::Function callback) { callback.Call(env.Global(), {env.Null()}); } DWORD RunDisplayChangeContextLoop(LPVOID lpParam) { auto context = (Win32DisplayChangeContext *)lpParam; MSG msg; BOOL getMessageResponse; DWORD error = ERROR_SUCCESS; UINT displayChange = 0; // In order to get WM_DISPLAYCHANGE messages we have to create // a hidden window in this specific thread. HWND hWnd = CreateWindowExW( WS_EX_TRANSPARENT, L"STATIC", L"win32-displayconfig Broadcast Event Monitor", WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL); // The documentation would lead you to believe you get a WM_DISPLAYCHANGE // whenever the display changes. The documentation would be wrong. // In fact, you get _this_ thing instead. Which isn't documented anywhere // but inferred by StackOverflow on the basis of Spy++ output. // YOLO. displayChange = RegisterWindowMessageW(L"UxdDisplayChangeMessage"); if (hWnd == NULL || displayChange == 0) { error = GetLastError(); if (hWnd != NULL) { DestroyWindow(hWnd); } #pragma warning(push) #pragma warning(disable : 4312) context->tsfn.NonBlockingCall((LPVOID)error, HandleDisplayChangeError); #pragma warning(pop) return error; } while (context->running.load() != FALSE && (getMessageResponse = GetMessage(&msg, NULL, 0, 0)) > 0) { if (msg.message == displayChange) { context->tsfn.NonBlockingCall(HandleDisplayChangeSuccess); } TranslateMessage(&msg); DispatchMessage(&msg); } if (getMessageResponse < 0) { error = GetLastError(); #pragma warning(push) #pragma warning(disable : 4312) context->tsfn.NonBlockingCall((LPVOID)error, HandleDisplayChangeError); #pragma warning(pop) } DestroyWindow(hWnd); return error; } bool TransientDeviceIdVectorContains(const std::vector &vec, struct Win32TransientDeviceId &dev) { for (auto it = vec.begin(); it != vec.end(); it++) { if (it->adapterId.LowPart != dev.adapterId.LowPart) { continue; } if (it->adapterId.HighPart != dev.adapterId.HighPart) { continue; } if (it->id != dev.id) { continue; } return true; } return false; } bool AlreadyHasNameInfo(const std::vector &rgNameInfo, LUID &adapterId, UINT32 id) { for (auto it = rgNameInfo.begin(); it != rgNameInfo.end(); it++) { if (it->adapterId.LowPart != adapterId.LowPart) { continue; } if (it->adapterId.HighPart != adapterId.HighPart) { continue; } if (it->id != id) { continue; } return true; } return false; } void AcquireDeviceNames(std::shared_ptr configResults) { DISPLAYCONFIG_TARGET_DEVICE_NAME request; request.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; request.header.size = sizeof(request); for (auto it = configResults->rgPathInfo.begin(); it != configResults->rgPathInfo.end(); it++) { if (AlreadyHasNameInfo(configResults->rgNameInfo, it->targetInfo.adapterId, it->targetInfo.id)) { continue; } request.header.adapterId.LowPart = it->targetInfo.adapterId.LowPart; request.header.adapterId.HighPart = it->targetInfo.adapterId.HighPart; request.header.id = it->targetInfo.id; request.monitorFriendlyDeviceName[0] = '\0'; request.monitorDevicePath[0] = '\0'; auto error = DisplayConfigGetDeviceInfo(&request.header); if (error != ERROR_SUCCESS) { // In the event of failure, drop your breakpoint/logging/evs here. // No, we're not going to expose this to Node. It's too much work. continue; } configResults->rgNameInfo.push_back(Win32DeviceNameInfo()); auto newEntry = configResults->rgNameInfo.end(); newEntry--; newEntry->adapterId.LowPart = it->targetInfo.adapterId.LowPart; newEntry->adapterId.HighPart = it->targetInfo.adapterId.HighPart; newEntry->id = it->targetInfo.id; newEntry->deviceFlags = request.flags; newEntry->outputTechnology = request.outputTechnology; newEntry->edidManufactureId = request.edidManufactureId; newEntry->edidProductCodeId = request.edidProductCodeId; newEntry->connectorInstance = request.connectorInstance; wcscpy_s(newEntry->monitorFriendlyDeviceName, DEVICE_NAME_SIZE, request.monitorFriendlyDeviceName); wcscpy_s(newEntry->monitorDevicePath, DEVICE_PATH_SIZE, request.monitorDevicePath); } } std::shared_ptr DoQueryDisplayConfig() { UINT32 cPathInfo = 0, cModeInfo = 0, cPathInfoMax = 0, cModeInfoMax = 0; while (true) { LONG errorCode = GetDisplayConfigBufferSizes(QDC_ALL_PATHS, &cPathInfo, &cModeInfo); if (errorCode != ERROR_SUCCESS) { cPathInfo = cModeInfo = 0; } else { if (cPathInfo > cPathInfoMax) { cPathInfoMax = cPathInfo; } cPathInfo = cPathInfoMax; if (cModeInfo > cModeInfoMax) { cModeInfoMax = cModeInfo; } cModeInfo = cModeInfoMax; } auto result = std::make_shared(cPathInfo, cModeInfo); if (errorCode != ERROR_SUCCESS) { result->error = errorCode; result->faultWasBuffer = true; return result; } errorCode = QueryDisplayConfig(QDC_ALL_PATHS, &cPathInfo, result->rgPathInfo.data(), &cModeInfo, result->rgModeInfo.data(), NULL); result->error = errorCode; if (errorCode == ERROR_SUCCESS) { result->rgPathInfo.resize(cPathInfo); result->rgModeInfo.resize(cModeInfo); AcquireDeviceNames(result); return result; } else if (errorCode != ERROR_INSUFFICIENT_BUFFER) { result->faultWasBuffer = false; return result; } } } LONG ToggleEnabled(const std::shared_ptr args) { auto initialQueryResults = DoQueryDisplayConfig(); if (initialQueryResults->error != ERROR_SUCCESS) { return initialQueryResults->error; } struct Win32TransientDeviceId currentPathDeviceId; std::vector preserve; std::vector alreadyEnabled; // First, ensure that the already enabled devices are accounted for. // Windows likes to report all the possible source modes for a given monitor, // and we don't want to override them here: we just want to enable the ones // that aren't enabled yet. for (auto it = initialQueryResults->rgPathInfo.begin(); it != initialQueryResults->rgPathInfo.end(); it++) { currentPathDeviceId.adapterId.LowPart = it->targetInfo.adapterId.LowPart; currentPathDeviceId.adapterId.HighPart = it->targetInfo.adapterId.HighPart; currentPathDeviceId.id = it->targetInfo.id; if (it->sourceInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID || it->targetInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID) { continue; } if ((it->flags & DISPLAYCONFIG_PATH_ACTIVE) == DISPLAYCONFIG_PATH_ACTIVE) { auto copied = *it; copied.sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID; copied.sourceInfo.statusFlags = 0; copied.targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID; copied.targetInfo.statusFlags = 0; preserve.push_back(copied); alreadyEnabled.push_back(currentPathDeviceId); } } // Then, enable the devices we wanted to enable but haven't yet for (auto it = initialQueryResults->rgPathInfo.begin(); it != initialQueryResults->rgPathInfo.end(); it++) { currentPathDeviceId.adapterId.LowPart = it->targetInfo.adapterId.LowPart; currentPathDeviceId.adapterId.HighPart = it->targetInfo.adapterId.HighPart; currentPathDeviceId.id = it->targetInfo.id; if (it->sourceInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID) { continue; } if (TransientDeviceIdVectorContains(args->enable, currentPathDeviceId) && !TransientDeviceIdVectorContains(alreadyEnabled, currentPathDeviceId)) { auto copied = *it; copied.sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID; copied.sourceInfo.statusFlags = 0; copied.targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID; copied.targetInfo.statusFlags = 0; copied.targetInfo.scaling = DISPLAYCONFIG_SCALING_PREFERRED; copied.flags = DISPLAYCONFIG_PATH_ACTIVE; preserve.push_back(copied); alreadyEnabled.push_back(currentPathDeviceId); } } // Then, enable all of the devices we know were or need to be enabled. // Note that some disabled devices are still in here. Due to Windows being // Windows, the only way out of this hole is to turn them all on, then turn off // the ones we don't want. auto error = SetDisplayConfig( preserve.size(), preserve.data(), 0, NULL, SDC_APPLY | SDC_TOPOLOGY_SUPPLIED | SDC_TOPOLOGY_CLONE | SDC_TOPOLOGY_EXTEND | SDC_ALLOW_PATH_ORDER_CHANGES); if (error != ERROR_SUCCESS) { return error; } auto allOnQueryResults = DoQueryDisplayConfig(); if (allOnQueryResults->error != ERROR_SUCCESS) { return allOnQueryResults->error; } preserve.clear(); // Finally, disable the monitors that shouldn't be there. for (auto it = allOnQueryResults->rgPathInfo.begin(); it != allOnQueryResults->rgPathInfo.end(); it++) { currentPathDeviceId.adapterId.LowPart = it->targetInfo.adapterId.LowPart; currentPathDeviceId.adapterId.HighPart = it->targetInfo.adapterId.HighPart; currentPathDeviceId.id = it->targetInfo.id; if (it->sourceInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID || it->targetInfo.modeInfoIdx == DISPLAYCONFIG_PATH_MODE_IDX_INVALID) { continue; } if (((it->flags & DISPLAYCONFIG_PATH_ACTIVE) == DISPLAYCONFIG_PATH_ACTIVE) && !TransientDeviceIdVectorContains(args->disable, currentPathDeviceId)) { auto copied = *it; copied.sourceInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID; copied.sourceInfo.statusFlags = 0; copied.targetInfo.modeInfoIdx = DISPLAYCONFIG_PATH_MODE_IDX_INVALID; copied.targetInfo.statusFlags = 0; preserve.push_back(copied); } } error = SetDisplayConfig( preserve.size(), preserve.data(), 0, NULL, SDC_APPLY | SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_PATH_ORDER_CHANGES); if (!args->persistent || error != ERROR_SUCCESS) { return error; } // If we say "persistent", then we have to do this whole dance where we figure out // what Windows decided to give us and hand it _back_ to Windows to save it. auto persistentQueryResults = DoQueryDisplayConfig(); if (persistentQueryResults->error != ERROR_SUCCESS) { return persistentQueryResults->error; } return SetDisplayConfig( persistentQueryResults->rgPathInfo.size(), persistentQueryResults->rgPathInfo.data(), persistentQueryResults->rgModeInfo.size(), persistentQueryResults->rgModeInfo.data(), SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG | SDC_SAVE_TO_DATABASE); } LONG RestoreDeviceConfig(const std::shared_ptr> restoreConfig, BOOL persistent) { std::vector rgPathInfo; std::vector rgModeInfo; DWORD dwModeInfoOffset = 0; for (auto it = restoreConfig->begin(); it != restoreConfig->end(); it++) { auto pathInfoCopy = it->pathInfo; auto sourceModeInfoCopy = it->sourceModeInfo; auto targetModeInfoCopy = it->targetModeInfo; // Take note: the source "id" fields are not modified. // They actually are persistent across reboots, and have special // meaning with respect to which extension is "primary" vs secondary. // The adapterId still needs to be corrected, as do all IDs on the target. // But the source id needs to remain the same. pathInfoCopy.sourceInfo.adapterId = it->sourceId.adapterId; pathInfoCopy.targetInfo.adapterId = it->targetId.adapterId; pathInfoCopy.targetInfo.id = it->targetId.id; pathInfoCopy.sourceInfo.modeInfoIdx = dwModeInfoOffset++; pathInfoCopy.targetInfo.modeInfoIdx = dwModeInfoOffset++; sourceModeInfoCopy.adapterId = it->sourceId.adapterId; targetModeInfoCopy.adapterId = it->targetId.adapterId; targetModeInfoCopy.id = it->targetId.id; rgPathInfo.push_back(pathInfoCopy); rgModeInfo.push_back(sourceModeInfoCopy); rgModeInfo.push_back(targetModeInfoCopy); } auto persistFlag = persistent ? SDC_SAVE_TO_DATABASE : 0; return SetDisplayConfig( rgPathInfo.size(), rgPathInfo.data(), rgModeInfo.size(), rgModeInfo.data(), SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG | persistFlag); } Napi::Object ConvertLUID(Napi::Env env, const LUID *luid) { auto result = Napi::Object::New(env); result.Set("LowPart", (double)luid->LowPart); result.Set("HighPart", (double)luid->HighPart); return result; } Napi::Object ConvertSourcePathInfo(Napi::Env env, const DISPLAYCONFIG_PATH_SOURCE_INFO &sourcePathInfo, bool supportsVirtualMode) { auto result = Napi::Object::New(env); result.Set("adapterId", ConvertLUID(env, &sourcePathInfo.adapterId)); result.Set("id", (double)sourcePathInfo.id); result.Set("statusFlags", (double)sourcePathInfo.statusFlags); if (supportsVirtualMode) { result.Set("cloneGroupId", (double)sourcePathInfo.cloneGroupId); result.Set("modeInfoIdx", (double)sourcePathInfo.sourceModeInfoIdx); } else { result.Set("modeInfoIdx", (double)sourcePathInfo.modeInfoIdx); } return result; } Napi::String ConvertVideoOutputTechnology(Napi::Env env, DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY tech) { switch (tech) { case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15: return Napi::String::New(env, "hd15"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO: return Napi::String::New(env, "svideo"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO: return Napi::String::New(env, "composite"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO: return Napi::String::New(env, "component"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI: return Napi::String::New(env, "dvi"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI: return Napi::String::New(env, "hdmi"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS: return Napi::String::New(env, "ldvs"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN: return Napi::String::New(env, "d_jpn"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI: return Napi::String::New(env, "sdi"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL: return Napi::String::New(env, "displayport_external"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED: return Napi::String::New(env, "displayport_embedded"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL: return Napi::String::New(env, "udi_external"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED: return Napi::String::New(env, "udi_embedded"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE: return Napi::String::New(env, "sdtvdongle"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST: return Napi::String::New(env, "miracast"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_WIRED: return Napi::String::New(env, "indirect_wired"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_VIRTUAL: return Napi::String::New(env, "indirect_virtual"); case DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL: return Napi::String::New(env, "internal"); default: return Napi::String::New(env, "other"); } } Napi::Number ConvertRotation(Napi::Env env, DISPLAYCONFIG_ROTATION rotation) { switch (rotation) { case DISPLAYCONFIG_ROTATION_ROTATE90: return Napi::Number::New(env, 90); case DISPLAYCONFIG_ROTATION_ROTATE180: return Napi::Number::New(env, 180); case DISPLAYCONFIG_ROTATION_ROTATE270: return Napi::Number::New(env, 270); default: return Napi::Number::New(env, 0); } } Napi::String ConvertScaling(Napi::Env env, DISPLAYCONFIG_SCALING scaling) { switch (scaling) { case DISPLAYCONFIG_SCALING_CENTERED: return Napi::String::New(env, "scaling"); case DISPLAYCONFIG_SCALING_STRETCHED: return Napi::String::New(env, "stretched"); case DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX: return Napi::String::New(env, "aspectratiocenteredmax"); case DISPLAYCONFIG_SCALING_CUSTOM: return Napi::String::New(env, "custom"); case DISPLAYCONFIG_SCALING_PREFERRED: return Napi::String::New(env, "preferred"); default: return Napi::String::New(env, "identity"); } } Napi::Object ConvertRational(Napi::Env env, const DISPLAYCONFIG_RATIONAL &rational) { auto result = Napi::Object::New(env); result.Set("Numerator", (double)rational.Numerator); result.Set("Denominator", (double)rational.Denominator); return result; } Napi::String ConvertScanLineOrdering(Napi::Env env, DISPLAYCONFIG_SCANLINE_ORDERING ordering) { switch (ordering) { case DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE: return Napi::String::New(env, "progressive"); case DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED: return Napi::String::New(env, "interlaced"); case DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST: return Napi::String::New(env, "interlaced_lowerfieldfirst"); default: return Napi::String::New(env, "unspecified"); } } Napi::Object ConvertTargetPathInfo(Napi::Env env, const DISPLAYCONFIG_PATH_TARGET_INFO &targetPathInfo, bool supportsVirtualMode) { auto result = Napi::Object::New(env); result.Set("adapterId", ConvertLUID(env, &targetPathInfo.adapterId)); result.Set("id", (double)targetPathInfo.id); result.Set("statusFlags", (double)targetPathInfo.statusFlags); result.Set("outputTechnology", ConvertVideoOutputTechnology(env, targetPathInfo.outputTechnology)); result.Set("rotation", ConvertRotation(env, targetPathInfo.rotation)); result.Set("scaling", ConvertScaling(env, targetPathInfo.scaling)); result.Set("refreshRate", ConvertRational(env, targetPathInfo.refreshRate)); result.Set("scanLineOrdering", ConvertScanLineOrdering(env, targetPathInfo.scanLineOrdering)); result.Set("targetAvailable", targetPathInfo.targetAvailable); result.Set("statusFlags", (double)targetPathInfo.statusFlags); if (supportsVirtualMode) { result.Set("desktopModeInfoIdx", (double)targetPathInfo.desktopModeInfoIdx); result.Set("modeInfoIdx", (double)targetPathInfo.targetModeInfoIdx); } else { result.Set("modeInfoIdx", (double)targetPathInfo.modeInfoIdx); } return result; } Napi::Object ConvertPathInfo(Napi::Env env, const DISPLAYCONFIG_PATH_INFO &pathInfo) { auto result = Napi::Object::New(env); result.Set("flags", (double)pathInfo.flags); auto supportsVirtualMode = (pathInfo.flags & DISPLAYCONFIG_PATH_SUPPORT_VIRTUAL_MODE) == DISPLAYCONFIG_PATH_SUPPORT_VIRTUAL_MODE; result.Set("sourceInfo", ConvertSourcePathInfo(env, pathInfo.sourceInfo, supportsVirtualMode)); result.Set("targetInfo", ConvertTargetPathInfo(env, pathInfo.targetInfo, supportsVirtualMode)); return result; } Napi::Object ConvertUInt64(Napi::Env env, UINT64 num) { auto highPart = num >> 32; auto lowPart = num & 0xffffffff; auto result = Napi::Object::New(env); result.Set("lowPart", (double)lowPart); result.Set("highPart", (double)highPart); return result; } Napi::Object Convert2DRegion(Napi::Env env, const DISPLAYCONFIG_2DREGION ®ion) { auto result = Napi::Object::New(env); result.Set("cx", (double)region.cx); result.Set("cy", (double)region.cy); return result; } Napi::Object ConvertVideoSignalInfo(Napi::Env env, const DISPLAYCONFIG_VIDEO_SIGNAL_INFO &videoSignalInfo) { auto result = Napi::Object::New(env); result.Set("pixelRate", ConvertUInt64(env, videoSignalInfo.pixelRate)); result.Set("hSyncFreq", ConvertRational(env, videoSignalInfo.hSyncFreq)); result.Set("vSyncFreq", ConvertRational(env, videoSignalInfo.vSyncFreq)); result.Set("activeSize", Convert2DRegion(env, videoSignalInfo.activeSize)); result.Set("totalSize", Convert2DRegion(env, videoSignalInfo.totalSize)); result.Set("videoStandard", (double)videoSignalInfo.videoStandard); result.Set("scanlineOrdering", ConvertScanLineOrdering(env, videoSignalInfo.scanLineOrdering)); return result; } Napi::Object ConvertTargetMode(Napi::Env env, const DISPLAYCONFIG_TARGET_MODE &targetMode) { auto result = Napi::Object::New(env); result.Set("targetVideoSignalInfo", ConvertVideoSignalInfo(env, targetMode.targetVideoSignalInfo)); return result; } Napi::Value ConvertPixelFormat(Napi::Env env, DISPLAYCONFIG_PIXELFORMAT pixelFormat) { switch (pixelFormat) { case DISPLAYCONFIG_PIXELFORMAT_8BPP: return Napi::Number::New(env, 8); case DISPLAYCONFIG_PIXELFORMAT_16BPP: return Napi::Number::New(env, 16); case DISPLAYCONFIG_PIXELFORMAT_24BPP: return Napi::Number::New(env, 24); case DISPLAYCONFIG_PIXELFORMAT_32BPP: return Napi::Number::New(env, 32); default: return Napi::String::New(env, "nongdi"); } } Napi::Value ConvertModeInfoType(Napi::Env env, DISPLAYCONFIG_MODE_INFO_TYPE modeInfoType) { switch (modeInfoType) { case DISPLAYCONFIG_MODE_INFO_TYPE_TARGET: return Napi::String::New(env, "target"); case DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE: return Napi::String::New(env, "source"); case DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE: return Napi::String::New(env, "desktopImage"); default: return env.Undefined(); } } Napi::Object ConvertPointL(Napi::Env env, const POINTL &pointl) { auto result = Napi::Object::New(env); result.Set("x", (double)pointl.x); result.Set("y", (double)pointl.y); return result; } Napi::Object ConvertSourceMode(Napi::Env env, const DISPLAYCONFIG_SOURCE_MODE &sourceMode) { auto result = Napi::Object::New(env); result.Set("width", (double)sourceMode.width); result.Set("height", (double)sourceMode.height); result.Set("pixelFormat", ConvertPixelFormat(env, sourceMode.pixelFormat)); result.Set("position", ConvertPointL(env, sourceMode.position)); return result; } Napi::Object ConvertRectL(Napi::Env env, const RECTL &rectl) { auto result = Napi::Object::New(env); result.Set("left", (double)rectl.left); result.Set("top", (double)rectl.top); result.Set("right", (double)rectl.right); result.Set("bottom", (double)rectl.bottom); return result; } Napi::Object ConvertDesktopImageInfo(Napi::Env env, const DISPLAYCONFIG_DESKTOP_IMAGE_INFO &imageInfo) { auto result = Napi::Object::New(env); result.Set("PathSourceSize", ConvertPointL(env, imageInfo.PathSourceSize)); result.Set("DesktopImageRegion", ConvertRectL(env, imageInfo.DesktopImageRegion)); result.Set("DesktopImageClip", ConvertRectL(env, imageInfo.DesktopImageClip)); return result; } Napi::Object ConvertModeInfo(Napi::Env env, const DISPLAYCONFIG_MODE_INFO &modeInfo) { auto result = Napi::Object::New(env); result.Set("infoType", ConvertModeInfoType(env, modeInfo.infoType)); result.Set("id", (double)modeInfo.id); result.Set("adapterId", ConvertLUID(env, &modeInfo.adapterId)); switch (modeInfo.infoType) { case DISPLAYCONFIG_MODE_INFO_TYPE_TARGET: result.Set("targetMode", ConvertTargetMode(env, modeInfo.targetMode)); break; case DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE: result.Set("sourceMode", ConvertSourceMode(env, modeInfo.sourceMode)); break; case DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE: result.Set("desktopImageInfo", ConvertDesktopImageInfo(env, modeInfo.desktopImageInfo)); break; } return result; } Napi::Object ConvertNameInfo(Napi::Env env, const struct Win32DeviceNameInfo &nameInfo) { auto result = Napi::Object::New(env); result.Set("adapterId", ConvertLUID(env, &nameInfo.adapterId)); result.Set("id", (double)nameInfo.id); result.Set("deviceFlags", (double)nameInfo.deviceFlags.value); result.Set("outputTechnology", ConvertVideoOutputTechnology(env, nameInfo.outputTechnology)); result.Set("edidManufactureId", (double)nameInfo.edidManufactureId); result.Set("edidProductCodeId", (double)nameInfo.edidProductCodeId); result.Set("connectorInstance", (double)nameInfo.connectorInstance); result.Set("monitorFriendlyDeviceName", Napi::String::New(env, (const char16_t *)nameInfo.monitorFriendlyDeviceName, wcsnlen_s(nameInfo.monitorFriendlyDeviceName, DEVICE_NAME_SIZE))); result.Set("monitorDevicePath", Napi::String::New(env, (const char16_t *)nameInfo.monitorDevicePath, wcsnlen_s(nameInfo.monitorDevicePath, DEVICE_PATH_SIZE))); return result; } Napi::Array ConvertPathsInfo(Napi::Env env, const std::vector &rgPathInfo) { auto result = Napi::Array::New(env, rgPathInfo.size()); auto data = rgPathInfo.data(); for (int i = 0; i < rgPathInfo.size(); i++) { auto item = Napi::Object::New(env); auto buffer = Napi::Buffer::Copy(env, data + i, 1); item.Set("value", ConvertPathInfo(env, rgPathInfo[i])); item.Set("buffer", buffer); result.Set(i, item); } return result; } Napi::Array ConvertModesInfo(Napi::Env env, const std::vector &rgModeInfo) { auto result = Napi::Array::New(env, rgModeInfo.size()); auto data = rgModeInfo.data(); for (int i = 0; i < rgModeInfo.size(); i++) { auto item = Napi::Object::New(env); auto buffer = Napi::Buffer::Copy(env, data + i, 1); item.Set("value", ConvertModeInfo(env, rgModeInfo[i])); item.Set("buffer", buffer); result.Set(i, item); } return result; } Napi::Array ConvertNamesInfo(Napi::Env env, const std::vector &rgNameInfo) { auto result = Napi::Array::New(env, rgNameInfo.size()); for (int i = 0; i < rgNameInfo.size(); i++) { result.Set(i, ConvertNameInfo(env, rgNameInfo[i])); } return result; } Napi::Object ConvertConfigResults(Napi::Env env, const std::shared_ptr configResults) { auto result = Napi::Object::New(env); result.Set("pathArray", ConvertPathsInfo(env, configResults->rgPathInfo)); result.Set("modeArray", ConvertModesInfo(env, configResults->rgModeInfo)); result.Set("nameArray", ConvertNamesInfo(env, configResults->rgNameInfo)); return result; } class Win32QueryDisplayConfigWorker : public Napi::AsyncWorker { public: Win32QueryDisplayConfigWorker(Napi::Function &callback) : Napi::AsyncWorker(callback), configResults() {} void Execute() { this->configResults = DoQueryDisplayConfig(); } std::vector GetResult(Napi::Env env) { std::vector result{env.Null(), env.Undefined()}; if (this->configResults->error != ERROR_SUCCESS) { result[0] = Napi::Number::New(env, (double)this->configResults->error); } else { result[1] = ConvertConfigResults(env, this->configResults); } return result; } private: std::shared_ptr configResults; }; Napi::Value Win32QueryDisplayConfig(const Napi::CallbackInfo &info) { if (info.Length() < 1) { return Napi::Boolean::New(info.Env(), false); } if (!(info[0].IsFunction())) { return Napi::Boolean::New(info.Env(), false); } auto callback = info[0].As(); auto worker = new Win32QueryDisplayConfigWorker(callback); worker->Queue(); return Napi::Boolean::New(info.Env(), true); } class Win32ToggleEnabledWorker : public Napi::AsyncWorker { public: Win32ToggleEnabledWorker(Napi::Function &callback, std::shared_ptr args) : Napi::AsyncWorker(callback), args(args) {} void Execute() { this->errorCode = ToggleEnabled(this->args); } std::vector GetResult(Napi::Env env) { std::vector result{env.Null(), Napi::Number::New(env, (double)this->errorCode)}; return result; } private: std::shared_ptr args; LONG errorCode; }; bool ExtractTransientDeviceId(Napi::Value val, Win32TransientDeviceId *const receiver) { if (!val.IsObject()) { return false; } auto obj = val.As(); auto adapterIdVal = obj.Get("adapterId"); if (!adapterIdVal.IsObject()) { return false; } auto adapterIdObj = adapterIdVal.As(); auto adapterIdLowPartVal = adapterIdObj.Get("LowPart"); auto adapterIdHighPartVal = adapterIdObj.Get("HighPart"); if (!adapterIdLowPartVal.IsNumber() || !adapterIdHighPartVal.IsNumber()) { return false; } auto idVal = obj.Get("id"); if (!idVal.IsNumber()) { return false; } receiver->adapterId.LowPart = (uint32_t)adapterIdLowPartVal.As(); receiver->adapterId.HighPart = (int32_t)adapterIdHighPartVal.As(); receiver->id = (uint32_t)idVal.As(); return true; } std::shared_ptr ExtractToggleEnabledDisplayArguments(Napi::Object obj) { auto ret = std::make_shared(); struct Win32TransientDeviceId cur; ret->persistent = (bool)obj.Get("persistent").ToBoolean(); auto enableVal = obj.Get("enable"); auto disableVal = obj.Get("disable"); if (enableVal.IsArray()) { auto enableArr = enableVal.As(); for (DWORD i = 0; i < enableArr.Length(); i++) { if (ExtractTransientDeviceId(enableArr.Get(i), &cur)) { ret->enable.push_back(cur); } } } if (disableVal.IsArray()) { auto disableArr = disableVal.As(); for (DWORD i = 0; i < disableArr.Length(); i++) { if (ExtractTransientDeviceId(disableArr.Get(i), &cur)) { ret->disable.push_back(cur); } } } return ret; } Napi::Value Win32ToggleEnabledDisplays(const Napi::CallbackInfo &info) { if (info.Length() < 2) { return Napi::Boolean::New(info.Env(), false); } if (!info[0].IsObject()) { return Napi::Boolean::New(info.Env(), false); } if (!info[1].IsFunction()) { return Napi::Boolean::New(info.Env(), false); } auto args = ExtractToggleEnabledDisplayArguments(info[0].As()); auto worker = new Win32ToggleEnabledWorker(info[1].As(), args); worker->Queue(); return Napi::Boolean::New(info.Env(), true); } class Win32RestoreDisplayConfigWorker : public Napi::AsyncWorker { public: Win32RestoreDisplayConfigWorker(Napi::Function &callback, std::shared_ptr> configs, BOOL persistent) : Napi::AsyncWorker(callback), configs(configs), persistent(persistent) {} void Execute() { this->errorCode = RestoreDeviceConfig(this->configs, this->persistent); } std::vector GetResult(Napi::Env env) { std::vector result{env.Null(), Napi::Number::New(env, (double)this->errorCode)}; return result; } private: std::shared_ptr> configs; LONG errorCode; BOOL persistent; }; BOOL ExtractRestoreDisplayConfigEntry(Napi::Env env, Napi::Object obj, struct Win32RestoreDisplayConfigDevice *receiver) { auto sourceConfigIdVal = obj.Get("sourceConfigId"); auto targetConfigIdVal = obj.Get("targetConfigId"); auto pathBufferVal = obj.Get("pathBuffer"); auto sourceModeBufferVal = obj.Get("sourceModeBuffer"); auto targetModeBufferVal = obj.Get("targetModeBuffer"); if (!sourceConfigIdVal.IsObject() || !targetConfigIdVal.IsObject() || !pathBufferVal.IsBuffer() || !sourceModeBufferVal.IsBuffer() || !targetModeBufferVal.IsBuffer()) { return false; } if (!ExtractTransientDeviceId(sourceConfigIdVal.As(), &receiver->sourceId)) { return false; } if (!ExtractTransientDeviceId(targetConfigIdVal.As(), &receiver->targetId)) { return false; } auto pathBuffer = pathBufferVal.As>(); auto sourceModeBuffer = sourceModeBufferVal.As>(); auto targetModeBuffer = targetModeBufferVal.As>(); if (pathBuffer.Length() != sizeof(DISPLAYCONFIG_PATH_INFO) || sourceModeBuffer.Length() != sizeof(DISPLAYCONFIG_MODE_INFO) || targetModeBuffer.Length() != sizeof(DISPLAYCONFIG_MODE_INFO)) { return false; } memcpy_s(&receiver->pathInfo, sizeof(receiver->pathInfo), pathBuffer.Data(), pathBuffer.Length()); memcpy_s(&receiver->sourceModeInfo, sizeof(receiver->sourceModeInfo), sourceModeBuffer.Data(), sourceModeBuffer.Length()); memcpy_s(&receiver->targetModeInfo, sizeof(receiver->targetModeInfo), targetModeBuffer.Data(), targetModeBuffer.Length()); return true; } Napi::Value Win32RestoreDisplayConfig(const Napi::CallbackInfo &info) { if (info.Length() < 2) { return Napi::Boolean::New(info.Env(), false); } if (!info[0].IsArray() || !info[1].IsFunction()) { return Napi::Boolean::New(info.Env(), false); } BOOL persistent = false; if (info.Length() >= 3) { persistent = info[2].ToBoolean(); } struct Win32RestoreDisplayConfigDevice curConfig; auto configs = std::make_shared>(); auto providedArray = info[0].As(); for (DWORD i = 0; i < providedArray.Length(); i++) { auto providedCur = providedArray.Get(i); if (!providedCur.IsObject()) { continue; } if (ExtractRestoreDisplayConfigEntry(info.Env(), providedCur.As(), &curConfig)) { configs->push_back(curConfig); } } auto worker = new Win32RestoreDisplayConfigWorker(info[1].As(), configs, persistent); worker->Queue(); return Napi::Boolean::New(info.Env(), true); } static Win32DisplayChangeContext *displayEventContext = NULL; Napi::Value Win32ListenForDisplayChanges(const Napi::CallbackInfo &info) { if (info.Length() < 1 || !info[0].IsFunction()) { return Napi::Boolean::New(info.Env(), false); } if (displayEventContext != NULL) { return Napi::Boolean::New(info.Env(), true); } displayEventContext = new Win32DisplayChangeContext(info.Env(), info[0].As()); auto error = displayEventContext->Start(); if (error != ERROR_SUCCESS) { delete displayEventContext; displayEventContext = NULL; } return Napi::Number::New(info.Env(), error); } Napi::Value Win32StopListeningForDisplayChanges(const Napi::CallbackInfo &info) { if (displayEventContext == NULL) { return info.Env().Undefined(); } displayEventContext->Stop(); // ->Stop() waits (blocking) for the outstanding thread, so we'll be the only // thread referencing displayEventContext once it's gone. delete displayEventContext; displayEventContext = NULL; return info.Env().Undefined(); } Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set("win32_queryDisplayConfig", Napi::Function::New(env, Win32QueryDisplayConfig)); exports.Set("win32_toggleEnabledDisplays", Napi::Function::New(env, Win32ToggleEnabledDisplays)); exports.Set("win32_restoreDisplayConfig", Napi::Function::New(env, Win32RestoreDisplayConfig)); // Take note: while none of these functions are meant to be called directly in JavaScript, // these two in particular _depend_ on ordering enforced by JavaScript to function correctly. // You can only have one active event listener passed to this C++ library; otherwise we ignore // further event listeners. // // See index.js for the "right" way to do this: we pass one function to this module that // dispatches other JavaScript functions for us. exports.Set("win32_listenForDisplayChanges", Napi::Function::New(env, Win32ListenForDisplayChanges)); exports.Set("win32_stopListeningForDisplayChanges", Napi::Function::New(env, Win32StopListeningForDisplayChanges)); return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init) ================================================ FILE: src/modules/windows-hdr/.gitignore ================================================ node_modules *.log* build .vscode/ipch .history ================================================ FILE: src/modules/windows-hdr/binding.gyp ================================================ { "targets": [ { "target_name": "windows-hdr", "cflags!": [ ], "cflags_cc!": [ ], "conditions": [ ["OS=='win'", { "sources": [ "windows-hdr.cc" ] }], ], "include_dirs": [ " #include #include #include #include enum DISPLAYCONFIG_DEVICE_INFO_TYPE_INTERNAL { DISPLAYCONFIG_DEVICE_INFO_SET_SDR_WHITE_LEVEL = 0xFFFFFFEE, }; typedef struct _DISPLAYCONFIG_SET_SDR_WHITE_LEVEL { DISPLAYCONFIG_DEVICE_INFO_HEADER header; unsigned int SDRWhiteLevel; unsigned char finalValue; } _DISPLAYCONFIG_SET_SDR_WHITE_LEVEL; LONG pathSetSdrWhite(DISPLAYCONFIG_PATH_INFO path, int nits) { _DISPLAYCONFIG_SET_SDR_WHITE_LEVEL sdrWhiteParams = {}; sdrWhiteParams.header.type = (DISPLAYCONFIG_DEVICE_INFO_TYPE) DISPLAYCONFIG_DEVICE_INFO_SET_SDR_WHITE_LEVEL; sdrWhiteParams.header.size = sizeof(sdrWhiteParams); sdrWhiteParams.header.adapterId = path.targetInfo.adapterId; sdrWhiteParams.header.id = path.targetInfo.id; sdrWhiteParams.SDRWhiteLevel = nits * 1000 / 80; sdrWhiteParams.finalValue = 1; return DisplayConfigSetDeviceInfo(&sdrWhiteParams.header); } struct Display { std::string name; std::string path; int nits; boolean hdrSupported; boolean hdrEnabled; boolean hdrActive; DISPLAYCONFIG_PATH_INFO target; int bits; }; std::string wcharToString(const wchar_t* wstr, boolean hasNullTerminator) { try { int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr) - (hasNullTerminator ? 1 : 0); std::string str(size_needed, 0); WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &str[0], size_needed, nullptr, nullptr); return str; } catch (...) { return (std::string)(""); } } boolean setSDRBrightness(DISPLAYCONFIG_PATH_INFO target, int desiredNits, bool silent) { int nits = desiredNits; try { if (nits < 80) { nits = 80; } if (nits > 480) { nits = 480; } if (nits % 4 != 0) { nits += 4 - (nits % 4); } LONG result = pathSetSdrWhite(target, nits); if (result != ERROR_SUCCESS) { if(!silent) fprintf(stderr, "Error on DisplayConfigSetDeviceInfo for SDR white level\n"); return false; } } catch (...) { return false; } return true; } std::map getDisplays() { std::map newDisplays; DISPLAYCONFIG_PATH_INFO *paths = 0; DISPLAYCONFIG_MODE_INFO *modes = 0; UINT32 pathCount, modeCount; { UINT32 flags = QDC_ONLY_ACTIVE_PATHS; LONG result = ERROR_SUCCESS; do { if (paths) { free(paths); } if (modes) { free(modes); } result = GetDisplayConfigBufferSizes(flags, &pathCount, &modeCount); if (result != ERROR_SUCCESS) { fprintf(stderr, "Error on GetDisplayConfigBufferSizes\n"); return newDisplays; } paths = (DISPLAYCONFIG_PATH_INFO *)malloc(pathCount * sizeof(paths[0])); modes = (DISPLAYCONFIG_MODE_INFO *)malloc(modeCount * sizeof(modes[0])); result = QueryDisplayConfig(flags, &pathCount, paths, &modeCount, modes, 0); if (result != ERROR_SUCCESS && result != ERROR_INSUFFICIENT_BUFFER) { fprintf(stderr, "Error on QueryDisplayConfig\n"); return newDisplays; } } while (result == ERROR_INSUFFICIENT_BUFFER); } for (int i = 0; i < pathCount; i++) { DISPLAYCONFIG_PATH_INFO path = paths[i]; DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {}; targetName.header.adapterId = path.targetInfo.adapterId; targetName.header.id = path.targetInfo.id; targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; targetName.header.size = sizeof(targetName); LONG result = DisplayConfigGetDeviceInfo(&targetName.header); if (result != ERROR_SUCCESS) { fprintf(stderr, "Error on DisplayConfigGetDeviceInfo for target name\n"); return newDisplays; } DISPLAYCONFIG_SDR_WHITE_LEVEL displayInfo = {}; displayInfo.header.type = (DISPLAYCONFIG_DEVICE_INFO_TYPE) DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL; displayInfo.header.size = sizeof(displayInfo); displayInfo.header.adapterId = path.targetInfo.adapterId; displayInfo.header.id = path.targetInfo.id; result = DisplayConfigGetDeviceInfo(&displayInfo.header); if (result != ERROR_SUCCESS) { fprintf(stderr, "Error on DisplayConfigGetDeviceInfo for SDR white level\n"); return newDisplays; } DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO hdrInfo = {}; hdrInfo.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO; hdrInfo.header.size = sizeof(DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO); hdrInfo.header.adapterId = path.targetInfo.adapterId; hdrInfo.header.id = path.targetInfo.id; result = DisplayConfigGetDeviceInfo(&hdrInfo.header); int nits = (int)displayInfo.SDRWhiteLevel * 80 / 1000; std::string monitorDevicePath = wcharToString(targetName.monitorDevicePath, false); Display newDisplay; newDisplay.name = wcharToString(targetName.monitorFriendlyDeviceName, true); newDisplay.path = monitorDevicePath.substr(0, monitorDevicePath.find("#{")); newDisplay.nits = nits; newDisplay.hdrSupported = hdrInfo.advancedColorSupported; newDisplay.hdrEnabled = hdrInfo.advancedColorEnabled; newDisplay.bits = hdrInfo.bitsPerColorChannel; newDisplay.target = path; // Only check for HDR if Windows reports it's on newDisplay.hdrActive = false; if(hdrInfo.advancedColorEnabled) { newDisplay.hdrActive = setSDRBrightness(path, nits, true); } newDisplays.insert({newDisplay.path, newDisplay}); } return newDisplays; } Napi::Array nodeGetDisplays(const Napi::CallbackInfo& info) { std::map displays; try { displays = getDisplays(); } catch (...) { fprintf(stderr, "Error on nodeGetDisplays\n"); } Napi::Env env = info.Env(); Napi::Array out = Napi::Array::New(env); int i = 0; for (auto& display : displays) { Napi::Object displayObj = Napi::Object::New(env); displayObj.Set(Napi::String::New(env, "name"), Napi::String::New(env, display.second.name)); displayObj.Set(Napi::String::New(env, "path"), Napi::String::New(env, display.second.path)); displayObj.Set(Napi::String::New(env, "nits"), Napi::Number::New(env, display.second.nits)); displayObj.Set(Napi::String::New(env, "hdrSupported"), Napi::Boolean::New(env, display.second.hdrSupported)); displayObj.Set(Napi::String::New(env, "hdrEnabled"), Napi::Boolean::New(env, display.second.hdrEnabled)); displayObj.Set(Napi::String::New(env, "hdrActive"), Napi::Boolean::New(env, display.second.hdrActive)); displayObj.Set(Napi::String::New(env, "bits"), Napi::Number::New(env, display.second.bits)); out.Set(i++, displayObj); } return out; } Napi::Boolean nodeSetSDRBrightness(const Napi::CallbackInfo& info) { if(info.Length() != 2) { fprintf(stderr, "Invalid number of parameters.\n"); return Napi::Boolean::New(info.Env(), false); } Napi::String path = info[0].As(); Napi::Number nits = info[1].As(); std::map displays = getDisplays(); boolean result = false; for (auto& display : displays) { if(display.second.path == (std::string)path) { result = setSDRBrightness(display.second.target, nits, false); break; } } return Napi::Boolean::New(info.Env(), result); } Napi::Object Init(Napi::Env env, Napi::Object exports) { exports.Set(Napi::String::New(env, "getDisplays"), Napi::Function::New(env, nodeGetDisplays)); exports.Set(Napi::String::New(env, "setSDRBrightness"), Napi::Function::New(env, nodeSetSDRBrightness)); return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init) ================================================ FILE: src/modules/wmi-bridge/binding.gyp ================================================ { "targets": [ { "target_name": "wmi_bridge", "cflags!": [ ], "cflags_cc!": [ ], "conditions": [ ["OS=='win'", { "sources": [ "wmi-bridge.cc" ] }], ], "msvs_settings": { "VCCLCompilerTool": { 'AdditionalOptions': ['/permissive'], }, }, "include_dirs": [ " { console.log("==== TESTING WMIBRIDGE ====") const monitors = WMIBridgeTest.getMonitors(); console.log(`getMonitors: ${Object.keys(monitors)}`) const brightness = WMIBridgeTest.getBrightness(); console.log(`getBrightness:`, brightness) const ok = WMIBridgeTest.setBrightness(100); console.log(`setBrightness: ${ok}`) console.log('===========================') console.log(" ") console.log(" ") }, 500) ================================================ FILE: src/modules/wmi-bridge/index.js ================================================ "use strict"; const addon = require("bindings")("wmi_bridge"); require("os").setPriority(0, require("os").constants.priority.PRIORITY_BELOW_NORMAL) class WMIBridge { constructor() {} setBrightness = async (level = 50) => { let ok = false try { ok = addon.setBrightness(level) } catch(e) { console.log(e) } return ok } getBrightness = async () => { let brightness = { failed: true } try { brightness = addon.getBrightness() } catch (e) { console.log(e) } return brightness } getMonitors = async () => { try { return addon.getMonitors() } catch(e) { console.log(e) return { failed: true } } } } module.exports = new WMIBridge(); ================================================ FILE: src/modules/wmi-bridge/package.json ================================================ { "name": "wmi-bridge", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "node example.js", "rebuild": "node-gyp rebuild", "install": "npm run rebuild" }, "author": "xanderfrangos", "dependencies": { "bindings": "1.5.0", "node-addon-api": "3.1.0" }, "files": [ "index.js", "binding.gyp", "wmi-bridge.cc", "example.js" ], "devDependencies": { "@types/node": "^14.14.32", "typescript": "^4.2.3" } } ================================================ FILE: src/modules/wmi-bridge/wmi-bridge.cc ================================================ #define _WIN32_DCOM #include #include #include #include #include #include #include "oaidl.h" #include "oleauto.h" using namespace std; #pragma comment(lib, "wbemuuid.lib") HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED); IWbemServices *pService = NULL; bool wmiConnected = false; Napi::Object failedObj; void p(string str) { //cout << "Line: " << str << endl; } // Set up COM stuff once bool wmiConnect() { try { p("wmiConnect 1"); if (wmiConnected == true) return true; p("wmiConnect 2"); hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (FAILED(hRes)) { cout << "Unable to launch COM: 0x" << std::hex << hRes << endl; return false; } p("wmiConnect 3"); if ((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0)))) { cout << "Unable to initialize security: 0x" << std::hex << hRes << endl; return false; } p("wmiConnect 4 END"); wmiConnected = true; return true; } catch (...) { return false; } } // https://stackoverflow.com/questions/6284524/bstr-to-stdstring-stdwstring-and-vice-versa std::string bstr_to_str(BSTR bstr) { int wslen = ::SysStringLen(bstr); const wchar_t* pstr = (wchar_t*)bstr; int len = ::WideCharToMultiByte(CP_ACP, 0, pstr, wslen, NULL, 0, NULL, NULL); std::string dblstr(len, '\0'); len = ::WideCharToMultiByte(CP_ACP, 0 /* no flags */, pstr, wslen /* not necessary NULL-terminated */, &dblstr[0], len, NULL, NULL /* no default char */); return dblstr; } // Used to read weird WMIMonitorID strings string getWMIClassUINTString(HRESULT &hr, VARIANT &vtProp) { p("getWMIClassUINTString 1"); string out = ""; if (!FAILED(hr)) { p("getWMIClassUINTString 2"); if ((vtProp.vt == VT_NULL) || (vtProp.vt == VT_EMPTY)) { p("getWMIClassUINTString 3a"); } else if ((vtProp.vt & VT_ARRAY)) { p("getWMIClassUINTString 3b"); long lLower, lUpper; UINT32 Element = NULL; SAFEARRAY *pSafeArray = vtProp.parray; p("getWMIClassUINTString 4"); SafeArrayGetLBound(pSafeArray, 1, &lLower); SafeArrayGetUBound(pSafeArray, 1, &lUpper); p("getWMIClassUINTString 5"); for (long i = lLower; i <= lUpper; i++) { hr = SafeArrayGetElement(pSafeArray, &i, &Element); if (Element != 0) { out.push_back(char(Element)); } } p("getWMIClassUINTString 6"); //SafeArrayDestroy(pSafeArray); } } p("getWMIClassUINTString 7"); VariantClear(&vtProp); p("getWMIClassUINTString 8 END"); return out; } Napi::Object getWMIBrightness(const Napi::CallbackInfo &info) { using std::cin; using std::cout; using std::endl; p("getWMIBrightness 1"); // Monitors info Napi::Object monitor = Napi::Object::New(info.Env()); // Failure/Error response Napi::Object failed = Napi::Object::New(info.Env()); failed.Set("failed", Napi::Boolean::New(info.Env(), true)); try { int brightness = -1; bool connected = wmiConnect(); p("getWMIBrightness 2"); IWbemLocator *pLocator = NULL; if (FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator)))) { cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl; return failed; } p("getWMIBrightness 3"); if (FAILED(hRes = pLocator->ConnectServer(L"root\\WMI", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService))) { pLocator->Release(); cout << "Unable to connect to \"WMI\": " << std::hex << hRes << endl; return failed; } p("getWMIBrightness 4"); IEnumWbemClassObject *pEnumerator = NULL; if (FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM WmiMonitorBrightness", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator))) { // Likely due to not being a laptop pLocator->Release(); pService->Release(); return failed; } p("getWMIBrightness 5"); IWbemClassObject *clsObj = NULL; int numElems; while ((hRes = pEnumerator->Next(500, 1, &clsObj, (ULONG *)&numElems)) != WBEM_S_FALSE) { if (FAILED(hRes)) break; VARIANT vRet; VariantInit(&vRet); p("getWMIBrightness 6a"); if (SUCCEEDED(clsObj->Get(L"InstanceName", 0, &vRet, NULL, NULL))) { string InstanceName = bstr_to_str(vRet.bstrVal); monitor.Set("InstanceName", Napi::String::New(info.Env(), InstanceName)); VariantClear(&vRet); } VariantInit(&vRet); p("getWMIBrightness 6b"); if (SUCCEEDED(clsObj->Get(L"CurrentBrightness", 0, &vRet, NULL, NULL))) { brightness = vRet.intVal; monitor.Set("Brightness", Napi::Number::New(info.Env(), brightness)); VariantClear(&vRet); } clsObj->Release(); } p("getWMIBrightness 7"); pEnumerator->Release(); pService->Release(); pLocator->Release(); p("getWMIBrightness 8 END"); } catch (...) { p("getWMIBrightness FAILED"); return failed; } return monitor; } Napi::Object getWMIMonitors(const Napi::CallbackInfo &info) { using std::cin; using std::cout; using std::endl; p("getWMIMonitors 1"); // Monitors info Napi::Object monitors = Napi::Object::New(info.Env()); // Failure/Error response Napi::Object failed = Napi::Object::New(info.Env()); failed.Set("failed", Napi::Boolean::New(info.Env(), true)); bool connected = wmiConnect(); p("getWMIMonitors 2"); try { IWbemLocator *pLocator = NULL; if (FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator)))) { cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl; return failed; } p("getWMIMonitors 3"); if (FAILED(hRes = pLocator->ConnectServer(L"root\\WMI", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService))) { pLocator->Release(); cout << "Unable to connect to \"WMI\": " << std::hex << hRes << endl; return failed; } p("getWMIMonitors 4"); IEnumWbemClassObject *pEnumerator = NULL; if (FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM WmiMonitorID", WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator))) { pLocator->Release(); pService->Release(); cout << "Unable to retrive desktop monitors: " << std::hex << hRes << endl; return failed; } p("getWMIMonitors 5"); IWbemClassObject *clsObj = NULL; int numElems; while ((hRes = pEnumerator->Next(500, 1, &clsObj, (ULONG *)&numElems)) != WBEM_S_FALSE) { try { if (FAILED(hRes)) break; Napi::Object monitor = Napi::Object::New(info.Env()); string InstanceName; VARIANT vRet; VariantInit(&vRet); p("getWMIMonitors 6"); HRESULT hr = clsObj->Get(L"InstanceName", 0, &vRet, NULL, NULL); if (SUCCEEDED(hr) && vRet.vt == VT_BSTR) { InstanceName = bstr_to_str(vRet.bstrVal); monitor.Set("InstanceName", Napi::String::New(info.Env(), InstanceName)); VariantClear(&vRet); } p("getWMIMonitors 7"); try { VARIANT vtProp; VariantInit(&vtProp); HRESULT hr = clsObj->Get(L"UserFriendlyName", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { string UserFriendlyName = getWMIClassUINTString(hr, vtProp); monitor.Set("UserFriendlyName", Napi::String::New(info.Env(), UserFriendlyName)); p("getWMIMonitors 8"); } } catch (...) { p("getWMIMonitors Loop failed to get optional values"); } monitors.Set(InstanceName, monitor); p("getWMIMonitors 12"); } catch (...) { p("getWMIMonitors loop failed"); } clsObj->Release(); } p("getWMIMonitors 13"); pEnumerator->Release(); pService->Release(); pLocator->Release(); } catch (...) { p("getWMIMonitors FAILED"); return failed; } p("getWMIMonitors 14 END"); return monitors; } bool setWMIBrightness(int brightness) { p("setWMIBrightness 1"); //HRESULT hRes; bool connected = wmiConnect(); try { IWbemLocator *pLocator = NULL; if (FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator)))) { cout << "Unable to create a WbemLocator: " << std::hex << hRes << endl; return false; } p("setWMIBrightness 2"); IWbemServices *pSvc = NULL; // Connect to the local root\wminamespace // and obtain pointer pSvc to make IWbemServices calls. hRes = pLocator->ConnectServer( _bstr_t(L"ROOT\\WMI"), NULL, NULL, 0, NULL, 0, 0, &pSvc); p("setWMIBrightness 3"); if (FAILED(hRes)) { cout << "Could not connect. Error code = 0x" << hex << hRes << endl; pLocator->Release(); CoUninitialize(); return false; } p("setWMIBrightness 4"); // Step 5: -------------------------------------------------- // Set security levels for the proxy ------------------------ hRes = CoSetProxyBlanket( pSvc, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); p("setWMIBrightness 5"); if (FAILED(hRes)) { cout << "Could not set proxy blanket. Error code = 0x" << hex << hRes << endl; pSvc->Release(); pLocator->Release(); CoUninitialize(); return false; } p("setWMIBrightness 6"); // Step 6: -------------------------------------------------- // Call WmiSetBrightness method ----------------------------- // set up to call the Win32_Process::Create method BSTR ClassName = SysAllocString(L"WmiMonitorBrightnessMethods"); BSTR MethodName = SysAllocString(L"WmiSetBrightness"); BSTR bstrQuery = SysAllocString(L"Select * from WmiMonitorBrightnessMethods"); IEnumWbemClassObject *pEnum = NULL; p("setWMIBrightness 7"); hRes = pSvc->ExecQuery(_bstr_t(L"WQL"), //Query Language bstrQuery, //Query to Execute WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, //Make a semi-synchronous call NULL, //Context &pEnum /*Enumeration Interface*/); p("setWMIBrightness 8"); hRes = WBEM_S_NO_ERROR; p("setWMIBrightness 9"); ULONG ulReturned; IWbemClassObject *pObj; DWORD retVal = 0; if (FAILED(hRes)) return false; p("setWMIBrightness 10"); //Get the Next Object from the collection hRes = pEnum->Next(500, //Timeout 1, //No of objects requested &pObj, //Returned Object &ulReturned /*No of object returned*/); p("setWMIBrightness 11"); if (FAILED(hRes)) return false; p("setWMIBrightness 12"); IWbemClassObject *pClass = NULL; hRes = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL); if (FAILED(hRes)) return false; p("setWMIBrightness 13"); IWbemClassObject *pInParamsDefinition = NULL; hRes = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL); if (FAILED(hRes)) return false; p("setWMIBrightness 14"); IWbemClassObject *pClassInstance = NULL; hRes = pInParamsDefinition->SpawnInstance(0, &pClassInstance); if (FAILED(hRes)) return false; p("setWMIBrightness 15"); VARIANT var1; VariantInit(&var1); BSTR ArgName0 = SysAllocString(L"Timeout"); p("setWMIBrightness 16"); V_VT(&var1) = VT_UI1; V_UI1(&var1) = 0; hRes = pClassInstance->Put(ArgName0, 0, &var1, CIM_UINT32); //CIM_UINT64 p("setWMIBrightness 17"); if (FAILED(hRes)) return false; VARIANT var2; VariantInit(&var2); BSTR ArgName1 = SysAllocString(L"Brightness"); p("setWMIBrightness 18"); V_VT(&var2) = VT_UI1; V_UI1(&var2) = brightness; //Brightness value hRes = pClassInstance->Put(ArgName1, 0, &var2, CIM_UINT8); p("setWMIBrightness 19"); if (FAILED(hRes)) return false; // Call the method VARIANT pathVariable; VariantInit(&pathVariable); p("setWMIBrightness 20"); hRes = pObj->Get(_bstr_t(L"__PATH"), 0, &pathVariable, NULL, NULL); if (FAILED(hRes)) return false; p("setWMIBrightness 21"); hRes = pSvc->ExecMethod(pathVariable.bstrVal, MethodName, 0, NULL, pClassInstance, NULL, NULL); p("setWMIBrightness 22"); if (FAILED(hRes)) return false; p("setWMIBrightness 23"); VariantClear(&var1); VariantClear(&var2); p("setWMIBrightness 24"); VariantClear(&pathVariable); p("setWMIBrightness 25 END"); } catch (...) { p("setWMIBrightness FAILED"); return false; } return !FAILED(hRes); } // Set WMI brightness (laptops/tablets) Napi::Boolean setBrightness(const Napi::CallbackInfo &info) { try { int level = info[0].ToNumber().Int32Value(); bool ok = false; try { ok = setWMIBrightness(level); } catch (...) { p("setBrightness failed"); } return Napi::Boolean::New(info.Env(), ok); } catch (...) { return Napi::Boolean::New(info.Env(), false); } } // Get WMI brightness (laptops/tablets) Napi::Object getBrightness(const Napi::CallbackInfo &info) { try { Napi::Object monInfo = getWMIBrightness(info); return monInfo; } catch (...) { return failedObj; } } // Get known monitor info from WMI Napi::Object getMonitors(const Napi::CallbackInfo &info) { try { Napi::Object monInfo = getWMIMonitors(info); return monInfo; } catch (...) { return failedObj; } } Napi::Object Init(Napi::Env env, Napi::Object exports) { failedObj = Napi::Object::New(env); failedObj.Set("failed", Napi::Boolean::New(env, true)); exports.Set(Napi::String::New(env, "setBrightness"), Napi::Function::New(env, setBrightness)); exports.Set(Napi::String::New(env, "getBrightness"), Napi::Function::New(env, getBrightness)); exports.Set(Napi::String::New(env, "getMonitors"), Napi::Function::New(env, getMonitors)); return exports; } NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init); ================================================ FILE: src/monitor-rules.json ================================================ { "ddcBrightnessCodes": { "FUS087C": 107, "FUS06AB": 19 }, "skipReapply": [ "DEL41D9" ] } ================================================ FILE: src/panel-preload.js ================================================ const { ipcRenderer: ipc } = require('electron'); const StackBlur = require('stackblur-canvas'); window.StackBlur = StackBlur const { setPriority } = require("os") const { priority } = require("os").constants setPriority(0, priority.PRIORITY_BELOW_NORMAL) // Send logs to main thread const log = console.log const con = { log: console.log, warn: console.warn, error: console.error } console.log = (...e) => { e.forEach((c) => { ipc.send('log', c); con.log(c) }) } console.error = (...e) => { e.forEach((c) => { ipc.send('log', c); con.error(c) }) } window.winPosition = { x: 0, y: 0, width: 0, height: 0 } let jsVars function getArgumentVars() { try { if(jsVars) return jsVars; const jsVarsString = process.argv.find(arg => arg.indexOf("jsVars") === 0) jsVars = JSON.parse(atob(jsVarsString.substring(6))) return jsVars } catch(e) { return {} } } // Show or hide the brightness panel function setPanelVisibility(visible) { window.showPanel = visible if (visible) { setPriority(0, priority.PRIORITY_ABOVE_NORMAL) window.document.body.dataset["visible"] = true window.dispatchEvent(new CustomEvent('sleepUpdated', { detail: false })) if (!settings.useNativeAnimation) { setTimeout(() => { if (window.showPanel) { ipc.send('show-acrylic') } }, 500) } window.updateMica?.() } else { setPriority(0, priority.PRIORITY_BELOW_NORMAL) window.document.body.dataset["visible"] = false window.document.body.dataset["acrylicShow"] = false if (window.isAcrylic) { window.isAcrylic = false } window.dispatchEvent(new CustomEvent('sleepUpdated', { detail: true })) } // Update #root value if (window.isAcrylic) { window.isAcrylic = false } window.document.getElementById("root").dataset["visible"] = window.showPanel window.sleep = !visible // Blur all inputs to fix visual bugs if ("activeElement" in document) document.activeElement.blur(); } function requestMonitors() { ipc.send('request-monitors') } function requestAccent() { ipc.send('request-colors') } // Send brightness update request. Params are the monitor's index in the array and requested brightness level. function updateBrightness(index, level) { if (!window.showPanel) return false; ipc.send('update-brightness', { index, level }) } function detectSunValley() { if(!window.reactReady) return false; try { // Detect new Fluent Icons (Windows build 21327+) if(window.settings.enableSunValley && document.fonts.check("12px Segoe Fluent Icons")) { window.document.getElementById("root").dataset.fluentIcons = true } else { window.document.getElementById("root").dataset.fluentIcons = false } // Detect new system font (Windows build 21376+) if(window.settings.enableSunValley && document.fonts.check("12px Segoe UI Variable Text")) { window.document.getElementById("root").dataset.segoeUIVariable = true } else { window.document.getElementById("root").dataset.segoeUIVariable = false } // Detect Windows 11 window.document.body.dataset.isWin11 = (window.settings.isWin11 ? true : false) } catch(e) { console.log("Couldn't test for Sun Valley", e) } } function openSettings() { setPanelVisibility(false) ipc.send('blur-panel') setTimeout(() => { ipc.send("open-settings") }, 111) } function sendSettings(newSettings) { ipc.send('send-settings', { newSettings, sendUpdate: true }) } function requestSettings() { ipc.send('request-settings') } function sendHeight(height) { ipc.send('panel-height', height) } function pauseMonitorUpdates() { ipc.send('pause-updates') } function panelAnimationDone() { if (showPanel === false) { ipc.send('panel-hidden') window.sleep = true window.document.body.dataset["acrylicShow"] = false window.document.getElementById("root").dataset["sleep"] = true window.dispatchEvent(new CustomEvent('sleepUpdated', { detail: true })) } else { } } function shouldSendHeightUpdate() { setTimeout(() => { try { if(window.document.getElementById("panel")) { const height = window.document.getElementById("panel").offsetHeight window.sendHeight(height) } } catch(e) { console.error(e) } }, 99) } function turnOffDisplays() { setPanelVisibility(false) ipc.send('blur-panel') setTimeout(() => { ipc.send('sleep-displays') }, 111) } function installUpdate() { ipc.send('get-update', window.latestVersion) ipc.send('clear-update', window.latestVersion.version) } function dismissUpdate() { ipc.send('ignore-update', window.latestVersion.version) } // Tray icon clicked ipc.on('tray-clicked', () => { window.document.getElementById("root").dataset["sleep"] = false setPanelVisibility(true) }) ipc.on("panelBlur", (e) => { setPanelVisibility(false) setTimeout(() => global.gc(), 2000) }) ipc.on("panel-unsleep", () => { window.dispatchEvent(new CustomEvent('sleepUpdated', { detail: false })) }) // Monitor info updated ipc.on("monitors-updated", (e, monitors) => { if (JSON.stringify(window.allMonitors) === JSON.stringify(monitors)) return false; window.allMonitors = monitors window.lastUpdate = Date.now() window.dispatchEvent(new CustomEvent('monitorsUpdated', { detail: monitors })) }) ipc.on("force-refresh-monitors", (e) => { window.allMonitors = {} ipc.send('full-refresh', true) }) // Accent colors recieved ipc.on('update-colors', (event, data) => { window.document.body.style.setProperty("--system-accent-color", data.accent.hex) window.document.body.style.setProperty("--system-accent-lighter", data.lighter) window.document.body.style.setProperty("--system-accent-light", data.light) window.document.body.style.setProperty("--system-accent-medium", data.medium) window.document.body.style.setProperty("--system-accent-medium-dark", data.mediumDark) window.document.body.style.setProperty("--system-accent-transparent", data.transparent) window.document.body.style.setProperty("--system-accent-dark", data.dark) window.document.body.style.setProperty("--system-accent-dark1", data.accentDark1.hex) window.document.body.style.setProperty("--system-accent-dark2", data.accentDark2.hex) window.document.body.style.setProperty("--system-accent-dark3", data.accentDark3.hex) window.document.body.style.setProperty("--system-accent-light1", data.accentLight1.hex) window.document.body.style.setProperty("--system-accent-light2", data.accentLight2.hex) window.document.body.style.setProperty("--system-accent-light3", data.accentLight3.hex) }) // Taskbar position recieved ipc.on('taskbar', (event, taskbar) => { window.document.getElementById("root").dataset["position"] = taskbar.position }) // Set display mode (overlay or normal) ipc.on('display-mode', (event, mode) => { window.document.getElementById("root").dataset["mode"] = mode shouldSendHeightUpdate() }) ipc.on('request-height', () => { ipc.send('panel-height', window.document.getElementById("panel").offsetHeight) }) // Taskbar position recieved ipc.on('isRefreshing', (event, newValue) => { window.isRefreshing = newValue window.dispatchEvent(new CustomEvent('isRefreshing', { detail: newValue })) }) // Settings recieved ipc.on('settings-updated', (event, settings) => { if (settings.isDev == false) { console.log = () => { } } else { console.log = log console.log = (...e) => { e.forEach((c) => ipc.send('log', c)) } } window.settings = settings detectSunValley() window.dispatchEvent(new CustomEvent('settingsUpdated', { detail: settings })) }) // Localization recieved ipc.on('localization-updated', (event, localization) => { window.dispatchEvent(new CustomEvent('localizationUpdated', { detail: localization })) }) // New app update recieved ipc.on('latest-version', (event, version) => { window.latestVersion = version window.dispatchEvent(new CustomEvent('updateUpdated', { detail: version })) }) // Update download progress ipc.on('updateProgress', (event, progress) => { window.dispatchEvent(new CustomEvent('updateProgress', { detail: { progress } })) }) // Updated window position variable ipc.on('panel-position', (event, pos) => { window.winPosition = pos window.updateMica?.() }) // User personalization settings recieved ipc.on('theme-settings', (event, theme) => { try { window.theme = (theme.SystemUsesLightTheme == 0 ? "dark" : "light") window.document.body.dataset["systemTheme"] = (theme.SystemUsesLightTheme == 0 ? "dark" : "light") window.document.body.dataset["theme"] = (settings.theme == "dark" || settings.theme == "light" ? settings.theme : window.theme) window.document.body.dataset["transparent"] = (theme.EnableTransparency == 0 || theme.UseAcrylic == 0 ? "false" : "true") window.document.body.dataset["acrylic"] = (theme.UseAcrylic == 0 || settings?.isWin11 ? "false" : "true") window.document.body.dataset["coloredTaskbar"] = (theme.ColorPrevalence == 0 ? "false" : "true") window.document.body.dataset["useNativeAnimation"] = (settings.useNativeAnimation == false ? "false" : "true") isTransparent = theme.EnableTransparency } catch (e) { window.document.body.dataset["systemTheme"] = "default" window.document.body.dataset["theme"] = "dark" window.document.body.dataset["transparent"] = "false" window.document.body.dataset["acrylic"] = "false" window.document.body.dataset["coloredTaskbar"] = "false" window.document.body.dataset["useNativeAnimation"] = "false" } }) // Play non-acrylic animation ipc.on('playPanelAnimation', () => { window.document.getElementById("root").dataset["visible"] = true }) // Play non-acrylic animation ipc.on('closePanelAnimation', () => { window.document.getElementById("root").dataset["visible"] = false }) ipc.on('set-acrylic-show', () => { window.document.body.dataset["acrylicShow"] = true }) window.micaState = { visibility: "hidden", src: "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" } ipc.on('mica-wallpaper', (event, wallpaper) => { const mica = document.querySelector("#mica .displays") const micaIMG = document.querySelector("#mica img") if(!mica) return false; if(!wallpaper) { mica.style.visibility = "hidden" window.micaState.visibility = "hidden" return false } if(window.micaState.src !== wallpaper.path) { window.micaState.visibility = "visible" window.micaState.wallpaper = wallpaper window.micaState.src = wallpaper.path mica.style.visibility = "visible" micaIMG.src = wallpaper.path } micaIMG.width = wallpaper.size?.width micaIMG.height = wallpaper.size?.height }) let lastPath = "" ipc.on('mica-wallpaper-create', (event, wallpaper) => { if(lastPath === wallpaper.path) { lastPath = wallpaper.path ipc.send('mica-wallpaper-same') return false } lastPath = wallpaper.path const img = new Image() const ratio = wallpaper.size.width / wallpaper.size.height const canvas = document.createElement("canvas") canvas.width = 500 * wallpaper.size.scale canvas.height = (500 / ratio) * wallpaper.size.scale img.addEventListener("load", () => { fitImageToCanvas(img, canvas) StackBlur.canvasRGB(canvas, 0, 0, canvas.width, canvas.height, 30 * wallpaper.size.scale ) const data = canvas.toDataURL("image/jpeg", 0.95) ipc.send('mica-wallpaper-data', data) }) img.src = wallpaper.path }) const fitImageToCanvas = (image,canvas) => { const canvasContext = canvas.getContext("2d"); const ratio = image.width / image.height; let newWidth = canvas.width; let newHeight = newWidth / ratio; if (newHeight < canvas.height) { newHeight = canvas.height; newWidth = newHeight * ratio; } const xOffset = newWidth > canvas.width ? (canvas.width - newWidth) / 2 : 0; const yOffset = newHeight > canvas.height ? (canvas.height - newHeight) / 2 : 0; canvasContext.drawImage(image, xOffset, yOffset, newWidth, newHeight); }; // Request startup data window.addEventListener('DOMContentLoaded', () => { requestSettings() requestAccent() }) // VCP code handling const vcpMap = { 0x10: "luminance", 0x13: "brightness", 0x12: "contrast", 0xD6: "powerState", 0x60: "inputs", 0x62: "volume" } window.addEventListener("setVCP", e => { if(!window.showPanel) return false; const { monitor, code, value } = e.detail ipc.send("set-vcp", { monitor, code, value }) if(vcpMap[vcp] && monitor.features[vcpMap[vcp]]) { monitor.features[vcpMap[vcp]][0] = level } }) window.ipc = ipc window.updateBrightness = updateBrightness window.requestMonitors = requestMonitors window.openSettings = openSettings window.sendSettings = sendSettings window.requestSettings = requestSettings window.pauseMonitorUpdates = pauseMonitorUpdates window.installUpdate = installUpdate window.dismissUpdate = dismissUpdate window.sendHeight = sendHeight window.panelAnimationDone = panelAnimationDone window.setPanelVisibility = setPanelVisibility window.turnOffDisplays = turnOffDisplays window.allMonitors = [] window.lastUpdate = Date.now() window.showPanel = false window.isAcrylic = false window.reactReady = false window.theme = "dark" window.settings = {} window.jsVars = getArgumentVars() window.isRefreshing = getArgumentVars().isRefreshing window.isAppX = (getArgumentVars().appName == "twinkle-tray-appx" ? true : false) ================================================ FILE: src/panel.js ================================================ import React from "react"; import { createRoot } from 'react-dom/client'; import BrightnessPanel from "./components/BrightnessPanel"; if (window.settings == undefined) window.settings = {} createRoot(document.getElementById("root")).render() window.updateMica = () => { const pos = [window.winPosition[0], window.winPosition[1]] if(window.settings.isWin11) { pos[0] += 12 pos[1] += 12 } const micaDisplays = document.querySelector("#mica .displays") if(micaDisplays) micaDisplays.style.transform = `translate(${pos[0] * -1}px, ${pos[1] * -1}px)`; } // Demo mode window.addEventListener("enableDemoMode", () => { window.allMonitors = [{ "brightness": 63, "device": "\\\\?\\DISPLAY#ACR0408#5&2e7612e0&0&UID4357#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", "id": "\\\\.\\DISPLAY1", "localID": 0, "max": 100, "min": 0, "name": "XB270HU", "num": 0, "type": "ddcci" }, { "brightness": 46, "device": "\\\\?\\DISPLAY#DELA0BC#5&2e7612e0&0&UID4356#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}", "id": "\\\\.\\DISPLAY2", "localID": 1, "max": 100, "min": 0, "name": "DELL U2415", "num": 1, "type": "ddcci" }] window.dispatchEvent(new Event("monitorsUpdated")) window.document.getElementById("root").dataset["visible"] = true window.document.body.style.setProperty("--system-accent-color", window.accent || "#744DA9") }) window.document.getElementById("root").addEventListener('transitionend', function () { window.panelAnimationDone() }); window.document.addEventListener('keydown', (e) => { if (e.key === "Escape") { window.ipc.send('blur-panel') } }) allMonitors = {} window.ipc.send('get-mica-wallpaper') window.ipc.send('get-refreshing') window.ipc.send('request-localization') setTimeout(() => { window.ipc.send('request-localization') }, 200) ================================================ FILE: src/parcel.js ================================================ const ParcelAPI = require("./parcelAPI") let mode let logLevel try { let modeFlagPos = (process.argv.indexOf("--mode")) mode = (process.argv[modeFlagPos + 1]) } catch(e) { console.log("Couldn't read mode flag.", e) } try { let logFlagPos = (process.argv.indexOf("--logLevel")) logLevel = (process.argv[logFlagPos + 1]) } catch(e) { console.log("Couldn't read log flag.", e) } ParcelAPI(mode, logLevel) ================================================ FILE: src/parcelAPI.js ================================================ const Bundler = require('parcel-bundler') const Path = require('path') const fs = require("fs") const entryFiles = Path.join(__dirname, './html/*.html') const optionsDev = { outDir: './cache', watch: true, minify: false, sourceMaps: true, hmr: true } const optionsProd = { outDir: './build', publicUrl: './', watch: true, cache: false, sourceMaps: false, minify: false, scopeHoist: false, hmr: false } function clearDirectory(relativePath) { const dir = Path.join(__dirname, relativePath) if (fs.existsSync(dir)){ fs.rmSync(dir, { recursive: true }) } if (!fs.existsSync(dir)){ fs.mkdirSync(dir) } } async function runParcel(mode = "dev", logLevel = null) { const parcelMode = mode?.toLocaleLowerCase?.() if(parcelMode == "dev") { clearDirectory('../cache') const bundler = new Bundler(entryFiles, Object.assign(optionsDev, { watch: true, logLevel: (logLevel ?? 3) })) return await bundler.serve(3000) } if(parcelMode == "live") { clearDirectory('../build') const bundler = new Bundler(entryFiles, Object.assign(optionsProd, { watch: true, logLevel: (logLevel ?? 1) })) return await bundler.bundle() } if(parcelMode == "build") { clearDirectory('../build') const bundler = new Bundler(entryFiles, Object.assign(optionsProd, { watch: false, logLevel: (logLevel ?? 3) })) return await bundler.bundle() } } module.exports = runParcel ================================================ FILE: src/settings-preload.js ================================================ const { ipcRenderer: ipc } = require('electron'); function getArgumentVars() { try { const jsVarsString = process.argv.find(arg => arg.indexOf("jsVars") === 0) const jsVars = JSON.parse(atob(jsVarsString.substring(6))) return jsVars } catch(e) { return {} } } function requestMonitors(fullRefresh = false) { if (fullRefresh) { ipc.send('full-refresh') } else { ipc.send('request-monitors') } } function requestAccent() { ipc.send('request-colors') } // Send brightness update request. Params are the monitor's index in the array and requested brightness level. function updateBrightness(index, level) { ipc.send('update-brightness', { index, level }) } // // Send Settings // - Send immediately if no recent changes. Throttle if frequent changes. // // let sendSettingsThrottle = false let sendSettingsObj = {} function sendSettings(newSettings = {}) { sendSettingsObj = Object.assign(sendSettingsObj, newSettings) if (!sendSettingsThrottle) { actuallySendSettings() sendSettingsThrottle = setTimeout(() => { actuallySendSettings() sendSettingsThrottle = false }, 500) } } function sendSettingsImmediate(newSettings = {}) { ipc.send('send-settings', { newSettings, sendUpdate: false }) } function actuallySendSettings() { ipc.send('send-settings', { newSettings: sendSettingsObj, sendUpdate: true }) sendSettingsObj = {} } function requestSettings() { ipc.send('request-settings') } function resetSettings() { ipc.send('reset-settings') } function detectSunValley() { if(!window.reactReady) return false; try { // Detect new Fluent Icons (Windows build 21327+) if(window.settings.enableSunValley && document.fonts.check("12px Segoe Fluent Icons")) { window.document.body.dataset.fluentIcons = true } else { window.document.body.dataset.fluentIcons = false } // Detect new system font (Windows build 21376+) if(window.settings.enableSunValley && document.fonts.check("12px Segoe UI Variable Text")) { window.document.body.dataset.segoeUIVariable = true } else { window.document.body.dataset.segoeUIVariable = false } // Detect Windows 11 window.document.body.dataset.isWin11 = (window.settings.isWin11 ? true : false) } catch(e) { console.log("Couldn't test for Sun Valley", e) } } function openURL(url) { ipc.send('open-url', url) } function getUpdate() { ipc.send('get-update', window.latestVersion) ipc.send('clear-update', window.latestVersion.version) } function checkForUpdates() { ipc.send('check-for-updates') } window.reloadReactMonitors = function() { window.dispatchEvent(new CustomEvent('monitorsUpdated', { detail: window.allMonitors })) } // New app update recieved ipc.on('latest-version', (event, version) => { window.latestVersion = version window.dispatchEvent(new CustomEvent('updateUpdated', { detail: version })) }) // Update download progress ipc.on('updateProgress', (event, progress) => { window.dispatchEvent(new CustomEvent('updateProgress', { detail: { progress } })) }) // Monitor info updated ipc.on("monitors-updated", (e, monitors) => { if (JSON.stringify(window.allMonitors) == JSON.stringify(monitors)) return false; window.allMonitors = monitors window.lastUpdate = Date.now() window.dispatchEvent(new CustomEvent('monitorsUpdated', { detail: monitors })) }) // Accent colors recieved ipc.on('update-colors', (event, data) => { window.document.body.style.setProperty("--system-accent-color", data.accent.hex) window.document.body.style.setProperty("--system-accent-lighter", data.lighter) window.document.body.style.setProperty("--system-accent-light", data.light) window.document.body.style.setProperty("--system-accent-medium", data.medium) window.document.body.style.setProperty("--system-accent-medium-dark", data.mediumDark) window.document.body.style.setProperty("--system-accent-transparent", data.transparent) window.document.body.style.setProperty("--system-accent-dark", data.dark) window.document.body.style.setProperty("--system-accent-dark1", data.accentDark1.hex) window.document.body.style.setProperty("--system-accent-dark2", data.accentDark2.hex) window.document.body.style.setProperty("--system-accent-dark3", data.accentDark3.hex) window.document.body.style.setProperty("--system-accent-light1", data.accentLight1.hex) window.document.body.style.setProperty("--system-accent-light2", data.accentLight2.hex) window.document.body.style.setProperty("--system-accent-light3", data.accentLight3.hex) window.accent = data.accent.hex }) ipc.on('settings-updated', (event, settings) => { window.settings = settings detectSunValley() window.dispatchEvent(new CustomEvent('settingsUpdated', { detail: settings })) }) ipc.on('window-history', (event, history) => { window.windowHistory = history window.dispatchEvent(new CustomEvent('windowHistory', { detail: history })) }) // Localization recieved ipc.on('localization-updated', (event, localization) => { window.dispatchEvent(new CustomEvent('localizationUpdated', { detail: localization })) }) const processTheme = (event, theme) => { try { window.theme = (theme.SystemUsesLightTheme == 0 ? "dark" : "light") window.document.body.dataset["systemTheme"] = (theme.SystemUsesLightTheme == 0 ? "dark" : "light") window.document.body.dataset["theme"] = (settings.theme == "dark" || settings.theme == "light" ? settings.theme : window.theme) window.document.body.dataset["transparent"] = (theme.EnableTransparency == 0 || theme.UseAcrylic == 0 ? "false" : "true") window.document.body.dataset["acrylic"] = (theme.UseAcrylic == 0 ? "false" : "true") // Disable acrylic on W10 because it's buggy if(!window.settings?.isWin11) { window.document.body.dataset["transparent"] = false window.document.body.dataset["acrylic"] = false } window.document.body.dataset["coloredTaskbar"] = (theme.ColorPrevalence == 0 ? "false" : "true") } catch (e) { window.document.body.dataset["systemTheme"] = "default" window.document.body.dataset["theme"] = "dark" window.document.body.dataset["transparent"] = "false" window.document.body.dataset["acrylic"] = false window.document.body.dataset["coloredTaskbar"] = "false" } } // User personalization settings recieved ipc.on('theme-settings', processTheme) ipc.on('mica-wallpaper', (event, wallpaper) => { const mica = document.querySelector("#mica .displays") const micaIMG = document.querySelector("#mica img") if(!wallpaper) { mica.style.visibility = "hidden" } else { mica.style.visibility = "visible" micaIMG.src = wallpaper.path micaIMG.width = wallpaper.size?.width micaIMG.height = wallpaper.size?.height } }) // Request startup data window.addEventListener("DOMContentLoaded", () => { processTheme(undefined, getArgumentVars().lastTheme) requestSettings() requestMonitors() requestAccent() }) // VCP code handling window.addEventListener("setVCP", e => { const { monitor, code, value } = e.detail ipc.send("set-vcp", { monitor, code, value }) }) window.addEventListener("set-sdr-brightness", e => { const { monitor, value } = e.detail ipc.send("set-sdr-brightness", { monitor, value }) }) const SunCalc = require('suncalc') function getSunCalcTimes(lat, long) { const localTimes = SunCalc.getTimes(new Date(), lat, long) for (const timeName in localTimes) { const time = localTimes[timeName].toLocaleTimeString() localTimes[timeName] = `${time.slice(0,4)}${time.slice(7)}` } return localTimes } window.ipc = ipc window.updateBrightness = updateBrightness window.requestMonitors = requestMonitors window.sendSettings = sendSettings window.sendSettingsImmediate = sendSettingsImmediate window.requestSettings = requestSettings window.resetSettings = resetSettings window.getUpdate = getUpdate window.checkForUpdates = checkForUpdates window.openURL = openURL window.allMonitors = [] window.lastUpdate = Date.now() window.showPanel = false window.reactReady = false window.settings = getArgumentVars().settings window.accent = "cyan" window.getSunCalcTimes = getSunCalcTimes window.version = 'v' + getArgumentVars().appVersion window.versionTag = getArgumentVars().appVersionTag window.versionBuild = getArgumentVars().appBuild window.isAppX = (getArgumentVars().appName == "twinkle-tray-appx" ? true : false) window.settingsPath = getArgumentVars().settingsPath ================================================ FILE: src/settings.js ================================================ import React from "react"; import { createRoot } from 'react-dom/client'; import SettingsWindow from "./components/SettingsWindow.jsx"; const micaDisplays = document.querySelector("#mica .displays") function updateMicaPosition(pos = [0, 0]) { micaDisplays.style.transform = `translate(${pos[0] * -1}px, ${pos[1] * -1}px)` } window.ipc.on("settingsWindowMove", (e, position) => { updateMicaPosition(position) }) window.addEventListener("blur", () => { document.body.dataset.focused = "false" }) window.addEventListener("focus", () => { document.body.dataset.focused = "true" }) createRoot(document.getElementById("settings")).render() setTimeout(() => { window.requestSettings() }, 33) ================================================ FILE: src/utils/BrightnessPanel/getMonitorName.js ================================================ const getMonitorName = (monitor, renames) => { if (Object.keys(renames).indexOf(monitor.id) >= 0 && renames[monitor.id] != "") { return renames[monitor.id] } else { return monitor.name } } export default getMonitorName ================================================ FILE: src/vcp-codes.js ================================================ /** * Full list of MCCS v2.2a VCP codes. */ module.exports = { // 8.1 - Preset Functions CODE_PAGE: 0x00 , RESTORE_FACTORY_COLOR_DEFAULTS: 0x08 , RESTORE_FACTORY_DEFAULTS: 0x04 , RESTORE_FACTORY_GEOMETRY_DEFAULTS: 0x06 , RESTORE_FACTORY_LUMINANCE_CONTRAST_DEFAULTS: 0x05 , RESTORE_FACTORY_TV_DEFAULTS: 0x0a , SAVE_RESTORE_SETTINGS: 0xb0 // 8.2 - Image Adjustment , SIX_AXIS_HUE_CONTROL_BLUE: 0x9f , SIX_AXIS_HUE_CONTROL_CYAN: 0x9e , SIX_AXIS_HUE_CONTROL_GREEN: 0x9d , SIX_AXIS_HUE_CONTROL_MAGENTA: 0xa0 , SIX_AXIS_HUE_CONTROL_RED: 0x9b , SIX_AXIS_HUE_CONTROL_YELLOW: 0x9c , SIX_AXIS_SATURATION_CONTROL_BLUE: 0x5d , SIX_AXIS_SATURATION_CONTROL_CYAN: 0x5c , SIX_AXIS_SATURATION_CONTROL_GREEN: 0x5b , SIX_AXIS_SATURATION_CONTROL_MAGENTA: 0x5e , SIX_AXIS_SATURATION_CONTROL_RED: 0x59 , SIX_AXIS_SATURATION_CONTROL_YELLOW: 0x5a , ADJUST_ZOOM: 0x7c , AUTO_COLOR_SETUP: 0x1f , AUTO_SETUP: 0x1e , AUTO_SETUP_ON_OFF: 0xa2 , BACKLIGHT_CONTROL: 0x13 , BACKLIGHT_LEVEL_BLUE: 0x71 , BACKLIGHT_LEVEL_GREEN: 0x6f , BACKLIGHT_LEVEL_RED: 0x6d , BACKLIGHT_LEVEL_WHITE: 0x6b , BLOCK_LUT_OPERATION: 0x75 , CLOCK: 0x0e , CLOCK_PHASE: 0x3e , COLOR_SATURATION: 0x8a , COLOR_TEMPERATURE_INCREMENT: 0x0b , COLOR_TEMPERATURE_REQUEST: 0x0c , CONTRAST: 0x12 , DISPLAY_APPLICATION: 0xdc , FLESH_TONE_ENHANCEMENT: 0x11 , FOCUS: 0x1c , GAMMA: 0x72 , GRAY_SCALE_EXPANSION: 0x2e , HORIZONTAL_MOIRE: 0x56 , HUE: 0x90 , LUMINANCE: 0x10 , LUT_SIZE: 0x73 , SCREEN_ORIENTATION: 0xaa , SELECT_COLOR_PRESET: 0x14 , SHARPNESS: 0x87 , SINGLE_POINT_LUT_OPERATION: 0x74 , STEREO_VIDEO_MODE: 0xd4 , TV_BLACK_LEVEL_LUMINANCE: 0x92 , TV_CONTRAST: 0x8e , TV_SHARPNESS: 0x8c , USER_COLOR_VISION_COMPENSATION: 0x17 , VELOCITY_SCAN_MODULATION: 0x88 , VERTICAL_MOIRE: 0x58 , VIDEO_BLACK_LEVEL_BLUE: 0x70 , VIDEO_BLACK_LEVEL_GREEN: 0x6e , VIDEO_BLACK_LEVEL_RED: 0x6c , VIDEO_GAIN_BLUE: 0x1a , VIDEO_GAIN_GREEN: 0x18 , VIDEO_GAIN_RED: 0x16 , WINDOW_BACKGROUND: 0x9a , WINDOW_CONTROL_ON_OFF: 0xa4 , WINDOW_SELECT: 0xa5 , WINDOW_SIZE: 0xa6 , WINDOW_TRANSPARENCY: 0xa7 // 8.3 - Display Control , DISPLAY_CONTROLLER_ID: 0xc8 , DISPLAY_FIRMWARE_LEVEL: 0xc9 , DISPLAY_USAGE_TIME: 0xc6 , HORIZONTAL_FREQUENCY: 0xac , IMAGE_MODE: 0xdb , OSD_BUTTON_LEVEL_CONTROL: 0xca , OSD_LANGUAGE: 0xcc , POWER_MODE: 0xd6 , SOURCE_COLOR_CODING: 0xb5 , SOURCE_TIMING_MODE: 0xb4 , VERSION: 0xdf , VERTICAL_FREQUENCY: 0xae // 8.4 - Geometry , BOTTOM_CORNER_FLARE: 0x4a , BOTTOM_CORNER_HOOK: 0x4c , DISPLAY_SCALING: 0x86 , HORIZONTAL_CONVERGENCE_M_G: 0x29 , HORIZONTAL_CONVERGENCE_R_B: 0x28 , HORIZONTAL_KEYSTONE: 0x42 , HORIZONTAL_LINEARITY: 0x2a , HORIZONTAL_LINEARITY_BALANCE: 0x2c , HORIZONTAL_MIRROR: 0x82 , HORIZONTAL_PARALLELOGRAM: 0x40 , HORIZONTAL_PINCUSHION: 0x24 , HORIZONTAL_PINCUSHION_BALANCE: 0x26 , HORIZONTAL_POSITION: 0x20 , HORIZONTAL_SIZE: 0x22 , ROTATION: 0x44 , SCAN_MODE: 0xda , TOP_CORNER_FLARE: 0x46 , TOP_CORNER_HOOK: 0x48 , VERTICAL_CONVERGENCE_M_G: 0x39 , VERTICAL_CONVERGENCE_R_B: 0x38 , VERTICAL_KEYSTONE: 0x43 , VERTICAL_LINEARITY: 0x3a , VERTICAL_LINEARITY_BALANCE: 0x3c , VERTICAL_MIRROR: 0x84 , VERTICAL_PARALLELOGRAM: 0x41 , VERTICAL_PINCUSHION: 0x34 , VERTICAL_PINCUSHION_BALANCE: 0x36 , VERTICAL_POSITION: 0x30 , VERTICAL_SIZE: 0x32 , WINDOW_POSITION_BR_X: 0x97 , WINDOW_POSITION_BR_Y: 0x98 , WINDOW_POSITION_TL_X: 0x95 , WINDOW_POSITION_TL_Y: 0x96 // 8.5 - Miscellaneous , ACTIVE_CONTROL: 0x52 , AMBIENT_LIGHT_SENSOR: 0x66 , APPLICATION_ENABLE_KEY: 0xc6 , ASSET_TAG: 0xd2 , AUXILIARY_DISPLAY_DATA: 0xcf , AUXILIARY_DISPLAY_SIZE: 0xce , AUXILIARY_POWER_OUTPUT: 0xd7 , DEGAUSS: 0x01 , DISPLAY_DESCRIPTOR_LENGTH: 0xc2 , DISPLAY_IDENTIFICATION_DATA_OPERATION: 0x87 , DISPLAY_TECHNOLOGY_TYPE: 0xb6 , ENABLE_DISPLAY_OF_DISPLAY_DESCRIPTOR: 0xc4 , FLAT_PANEL_SUB_PIXEL_LAYOUT: 0xb2 , INPUT_SOURCE: 0x60 , NEW_CONTROL_VALUE: 0x02 , OUTPUT_SELECT: 0xd0 , PERFORMANCE_PRESERVATION: 0x54 , REMOTE_PROCEDURE_CALL: 0x76 , SCRATCH_PAD: 0xde , SOFT_CONTROLS: 0x03 , STATUS_INDICATORS: 0xcd , TRANSMIT_DISPLAY_DESCRIPTOR: 0xc3 , TV_CHANNEL_UP_DOWN: 0x8b // 8.6 - Audio Function , AUDIO_BALANCE_L_R: 0x93 , AUDIO_BASS: 0x91 , AUDIO_JACK_CONNECTION_STATUS: 0x65 , AUDIO_MICROPHONE_VOLUME: 0x64 , AUDIO_MUTE: 0x8d , AUDIO_PROCESSOR_MODE: 0x94 , AUDIO_SPEAKER_SELECT: 0x63 , AUDIO_SPEAKER_VOLUME: 0x62 , AUDIO_TREBLE: 0x8f // 8.7 - DPVL Support , BODY_CRC_ERROR_COUNT: 0xbc , CLIENT_ID: 0xbd , HEADER_ERROR_COUNT: 0xbb , LINK_CONTROL: 0xbe , MONITOR_STATUS: 0xb7 , MONITOR_X_ORIGIN: 0xb9 , MONITOR_Y_ORIGIN: 0xba , PACKET_COUNT: 0xb8 }; ================================================ FILE: src/wmi-bridge-test.js ================================================ console.log("\x1b[45mRunning wmi-bridge test...\x1b[0m") const wmibridge = require("wmi-bridge"); require("os").setPriority(0, require("os").constants.priority.PRIORITY_BELOW_NORMAL) function readInstanceName(insName) { return (insName ? insName.replace(/&/g, '&').split("\\") : undefined) } // For testing timeouts function wait4s() { return new Promise(resolve => { setTimeout(() => { resolve(true); }, 4000); }); } getMonitorsWMI = () => { return new Promise(async (resolve, reject) => { const foundMonitors = {} try { const wmiMonitors = await wmibridge.getMonitors(); if (wmiMonitors.failed) { // Something went wrong console.log("\x1b[41m" + "wmi-bridge-test: Recieved FAILED response from getMonitors()" + "\x1b[0m") reject(foundMonitors) } else { // Sort through results for (let monitorHWID in wmiMonitors) { const monitor = wmiMonitors[monitorHWID] if (!monitor.InstanceName) continue; let hwid = readInstanceName(monitor.InstanceName) hwid[2] = hwid[2].split("_")[0] const wmiInfo = { id: `\\\\?\\${hwid[0]}#${hwid[1]}#${hwid[2]}`, key: hwid[2], hwid: hwid, serial: monitor.SerialNumberID } if (monitor.UserFriendlyName !== null && monitor.UserFriendlyName !== "") { wmiInfo.name = monitor.UserFriendlyName } foundMonitors[hwid[2]] = wmiInfo } } } catch (e) { console.log(`wmi-bridge-test: Failed to get all monitors.`) console.log(e) } resolve(foundMonitors) }) } process.send({ type: 'ready' }) //wait4s().then(() => { }) getMonitorsWMI().then(() => { process.send({ type: 'ok' }) }).catch(() => { process.send({ type: 'failed' }) })