mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2026-11-14 02:32:44 +03:00
Merge branch 'release-5.8.0' into stable
This commit is contained in:
88 files changed
+11201
-9786
No files matched your search
@@ -6,8 +6,9 @@ exclude =
|
||||
dist.win32/
|
||||
FDevIDs/
|
||||
venv/
|
||||
venv-py39/
|
||||
.venv/
|
||||
wix/
|
||||
hotkey/darwin.py # FIXME: Check under macOS VM at some point
|
||||
|
||||
# Show exactly where in a line the error happened
|
||||
#show-source = True
|
||||
|
||||
@@ -9,10 +9,15 @@ name: Push-Checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ develop ]
|
||||
# We'll catch issues on `develop` or any PR branch.
|
||||
branches-ignore:
|
||||
- 'main'
|
||||
- 'stable'
|
||||
- 'releases'
|
||||
- 'beta'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
push_checks:
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
@@ -59,3 +64,7 @@ jobs:
|
||||
grep -E -z -Z '\.py$' | \
|
||||
xargs -0 flake8 --count --statistics --extend-ignore D
|
||||
#######################################################################
|
||||
|
||||
- name: mypy type checks
|
||||
run: |
|
||||
./scripts/mypy-all.sh --platform win32
|
||||
@@ -2,9 +2,10 @@
|
||||
name: Submodule Updates
|
||||
|
||||
on:
|
||||
# We might want this on a schedule once this is in `main`
|
||||
push:
|
||||
branches: [ develop ]
|
||||
# push:
|
||||
# branches: [ develop ]
|
||||
schedule:
|
||||
- cron: '0 12 * * *'
|
||||
|
||||
jobs:
|
||||
check_submodules:
|
||||
@@ -19,6 +20,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: '${{ env.CHECKOUT_BRANCH }}'
|
||||
submodules: true
|
||||
|
||||
- name: Update submodules
|
||||
@@ -33,50 +35,34 @@ jobs:
|
||||
continue-on-error: true
|
||||
run: |
|
||||
changes=$(git status --porcelain)
|
||||
git status --porcelain
|
||||
if [ -n "${changes}" ];
|
||||
then
|
||||
echo '::set-output changes=true'
|
||||
echo 'changes=true' >> $GITHUB_OUTPUT
|
||||
echo "changes_text=${changes}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo 'changes=false' >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo '::set-output changes=false'
|
||||
exit 0
|
||||
|
||||
- name: Create submodules changes branch
|
||||
if: steps.check_for_changes.outputs.changes == 'true'
|
||||
run: |
|
||||
git checkout -b $GITHUB_RUN_ID
|
||||
git checkout -b "submodule-change/$GITHUB_RUN_ID" $CHECKOUT_BRANCH
|
||||
git commit -am "updating submodules"
|
||||
git push --set-upstream origin $GITHUB_RUN_ID
|
||||
git push --set-upstream origin "submodule-change/$GITHUB_RUN_ID"
|
||||
|
||||
- name: Create pull request against target branch
|
||||
if: steps.check_for_changes.outputs.changes == 'true'
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ inputs.github_token }}
|
||||
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
script: |
|
||||
await github.rest.pulls.create({
|
||||
owner: '${{ inputs.owner }}',
|
||||
repo: '${{ inputs.parent_repository }}'.split('/')[1].trim(),
|
||||
head: process.env.GITHUB_RUN_ID,
|
||||
base: '${{ inputs.pr_against_branch }}',
|
||||
owner: '${{ github.repository_owner }}',
|
||||
repo: '${{ github.repository }}'.split('/')[1].trim(),
|
||||
head: 'submodule-change/${{ github.run_id }}',
|
||||
base: '${{ env.PR_AGAINST_BRANCH }}',
|
||||
title: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`,
|
||||
body: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`,
|
||||
});
|
||||
|
||||
- name: Add labels
|
||||
if: steps.check_for_changes.outputs.changes == 'true'
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ inputs.github_token }}
|
||||
script: |
|
||||
const res = await github.rest.issues.listForRepo({
|
||||
owner: '${{ inputs.owner }}',
|
||||
repo: '${{ inputs.parent_repository }}'.split('/')[1].trim(),
|
||||
});
|
||||
const pr = res.data.filter(i => i.title.includes(process.env.GITHUB_RUN_ID));
|
||||
const prNumber = pr[0].number;
|
||||
await github.rest.issues.addLabels({
|
||||
issue_number: prNumber,
|
||||
owner: '${{ inputs.owner }}',
|
||||
repo: '${{ inputs.parent_repository }}'.split('/')[1].trim(),
|
||||
labels: ['${{ inputs.label }}']
|
||||
body: '${{ steps.check_for_changes.outputs.changes_text }}',
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
# vim: tabstop=2 shiftwidth=2
|
||||
name: Build EDMC for Windows
|
||||
|
||||
on:
|
||||
@@ -7,7 +8,61 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
variables:
|
||||
outputs:
|
||||
sem_ver: ${{ steps.var.outputs.sem_ver }}
|
||||
archive_exclusions: ${{ steps.var.outputs.archive_exclusions }}
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- name: Setting global variables
|
||||
uses: actions/github-script@v6
|
||||
id: var
|
||||
with:
|
||||
script: |
|
||||
core.setOutput('sem_ver', '${{ github.ref_name }}'.replaceAll('Release\/', ''))
|
||||
|
||||
linux_build:
|
||||
needs: [variables]
|
||||
name: Linux environment build steps
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Make tar archive
|
||||
run: |
|
||||
# For 'tar' we can only specify filename/glob exclusions, not any
|
||||
# directory location
|
||||
tar -c -v -z \
|
||||
-f ../EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz \
|
||||
-C .. \
|
||||
--exclude=EDMarketConnector-release-*.* \
|
||||
--exclude=.editorconfig \
|
||||
--exclude=.flake8 \
|
||||
--exclude=.git* \
|
||||
--exclude=.mypy.ini \
|
||||
--exclude=.pre-commit-config.yaml \
|
||||
--exclude=Build-exe-and-msi.py \
|
||||
--exclude=*.manifest \
|
||||
--exclude=coriolis-data \
|
||||
--exclude=img \
|
||||
--exclude=pyproject.toml \
|
||||
--exclude=scripts \
|
||||
--exclude=tests \
|
||||
--exclude=wix \
|
||||
EDMarketConnector
|
||||
mv ../EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz .
|
||||
|
||||
- name: Upload build files
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Built files
|
||||
path: |
|
||||
EDMarketConnector-release-*.tar.gz
|
||||
|
||||
windows_build:
|
||||
needs: [variables]
|
||||
name: Build EDMC
|
||||
runs-on: windows-2019
|
||||
|
||||
@@ -20,6 +75,25 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Make zip archive
|
||||
uses: thedoctor0/zip-release@main
|
||||
with:
|
||||
type: 'zip'
|
||||
# We want an in-zip prefix of `EDMarketConnector/` for all files, so
|
||||
# we specify that:
|
||||
# 1. We work from the parent directory
|
||||
directory: '..'
|
||||
# 2. The path we're using is the 'root' directory
|
||||
path: 'EDMarketConnector'
|
||||
# 3. The .zip file has to be in the 'root' so that upload-artifact
|
||||
# will process it. Can't use relative paths.
|
||||
filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.zip'
|
||||
# 4. And all the exclusions need to be prefixed with the 'root'
|
||||
# directory.
|
||||
# NB: If this gets too long it can cause zip 'Command Line Error',
|
||||
# presumably due to a Windows CL length limit.
|
||||
exclusions: 'EDMarketConnector/EDMarketConnector-release-*.* EDMarketConnector/.editorconfig EDMarketConnector/.flake8 EDMarketConnector/.git* EDMarketConnector/.mypy.ini EDMarketConnector/.pre-commit-config.yaml EDMarketConnector/Build-exe-and-msi.py EDMarketConnector/*.manifest EDMarketConnector/coriolis-data/ EDMarketConnector/img/ EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/'
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version-file: '.python-version'
|
||||
@@ -44,12 +118,14 @@ jobs:
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Built files
|
||||
path: EDMarketConnector_win*.msi
|
||||
path: |
|
||||
EDMarketConnector_win_*.msi
|
||||
EDMarketConnector-release-*.zip
|
||||
|
||||
release:
|
||||
name: Release new version
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
needs: [ windows_build, linux_build ]
|
||||
if: "${{ github.event_name != 'workflow_dispatch' }}"
|
||||
|
||||
steps:
|
||||
@@ -60,7 +136,7 @@ jobs:
|
||||
path: ./
|
||||
|
||||
- name: Hash files
|
||||
run: sha256sum EDMarketConnector_win*.msi > ./hashes.sum
|
||||
run: sha256sum EDMarketConnector_win_*.msi EDMarketConnector-release-*.{zip,tar.gz} > ./hashes.sum
|
||||
|
||||
- name: Create Draft Release
|
||||
uses: "softprops/action-gh-release@v1"
|
||||
@@ -70,5 +146,7 @@ jobs:
|
||||
prerelease: true
|
||||
discussion_category_name: "Announcement"
|
||||
files: |
|
||||
./EDMarketConnector_win*.msi
|
||||
./EDMarketConnector_win_*.msi
|
||||
./EDMarketConnector-release-*.zip
|
||||
./EDMarketConnector-release-*.tar.gz
|
||||
./hashes.sum
|
||||
+2
-1
@@ -18,7 +18,8 @@ EDMarketConnector.VisualElementsManifest.xml
|
||||
|
||||
.idea
|
||||
.vscode
|
||||
venv
|
||||
.venv/
|
||||
venv/
|
||||
*.code-workspace
|
||||
htmlcov/
|
||||
.ignored
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
[mypy]
|
||||
follow_imports = skip
|
||||
follow_imports = normal
|
||||
ignore_missing_imports = True
|
||||
scripts_are_modules = True
|
||||
; Without this bare `mypy <file>` may get warnings for e.g.
|
||||
; `<var> = <value>`
|
||||
; i.e. no typing info.
|
||||
check-untyped-defs = True
|
||||
check_untyped_defs = True
|
||||
; platform = darwin
|
||||
explicit_package_bases = True
|
||||
@@ -46,12 +46,12 @@ repos:
|
||||
# mypy - static type checking
|
||||
# mypy --follow-imports skip <file>
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: 'v0.931'
|
||||
rev: 'v0.991'
|
||||
hooks:
|
||||
- id: mypy
|
||||
# verbose: true
|
||||
# log_file: 'pre-commit_mypy.log'
|
||||
additional_dependencies: [ types-requests ]
|
||||
additional_dependencies: [ types-pkg-resources, types-requests, types-urllib3 ]
|
||||
# args: [ "--follow-imports", "skip", "--ignore-missing-imports", "--scripts-are-modules" ]
|
||||
|
||||
### # pydocstyle.exe <file>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"""Build to executables and MSI installer using py2exe and other tools."""
|
||||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
@@ -22,12 +21,14 @@ if sys.version_info[0:2] != (3, 11):
|
||||
raise AssertionError(f'Unexpected python version {sys.version}')
|
||||
|
||||
if sys.platform == 'win32':
|
||||
assert platform.architecture()[0] == '32bit', 'A Python 32bit build is required'
|
||||
import py2exe # noqa: F401 # Yes, this *is* used
|
||||
dist_dir = 'dist.win32'
|
||||
|
||||
else:
|
||||
raise AssertionError(f'Unsupported platform {sys.platform}')
|
||||
|
||||
# This added to make mypy happy
|
||||
assert sys.platform == 'win32'
|
||||
###########################################################################
|
||||
|
||||
###########################################################################
|
||||
@@ -83,6 +84,7 @@ OPTIONS = {
|
||||
'packages': [
|
||||
'asyncio', # No longer auto as of py3.10+py2exe 0.11
|
||||
'multiprocessing', # No longer auto as of py3.10+py2exe 0.11
|
||||
'pkg_resources._vendor.platformdirs', # Necessary 2023-01-17
|
||||
'sqlite3', # Included for plugins
|
||||
'util', # 2022-02-01 only imported in plugins/eddn.py
|
||||
],
|
||||
|
||||
+217
-1
@@ -13,10 +13,17 @@ produce the Windows executables and installer.
|
||||
|
||||
**As a consequence of this we no longer support Windows 7.
|
||||
This is due to
|
||||
[Python 3.10.x itself not supporting Windows 7](https://www.python.org/downloads/windows/).
|
||||
[Python 3.10.x and later not supporting Windows 7](https://www.python.org/downloads/windows/).
|
||||
The application (both EDMarketConnector.exe and EDMC.exe) will crash on
|
||||
startup due to a missing DLL.**
|
||||
|
||||
As [Windows 8.1 is now End-Of-Life](https://learn.microsoft.com/en-us/lifecycle/faq/windows#windows-8-1)
|
||||
we no longer explicitly support it, but for the time being it will likely
|
||||
continue to work. This is dependent on future Python releases not dropping
|
||||
support for Windows 8.1 in a manner that prevents it working. Any bug report
|
||||
made against Windows 8.1 use may be ignored unless reproduced on a supported
|
||||
OS.
|
||||
|
||||
This should have no other impact on users or plugin developers, other
|
||||
than the latter now being free to use features that were introduced since the
|
||||
Python 3.7 series.
|
||||
@@ -27,6 +34,215 @@ produce the Windows executables and installer.
|
||||
|
||||
---
|
||||
|
||||
Release 5.8.0
|
||||
===
|
||||
This release is essentially the same as 5.8.0-rc3 with only the version and
|
||||
this changelog updated.
|
||||
|
||||
It brings a new feature related to Fleetcarrier data, some convenience for
|
||||
Linux users, some fixes, and otherwise some internal changes that should not
|
||||
adversely affect either users or third-party plugins. For the latter, read
|
||||
below for some new/changed things that could benefit you.
|
||||
|
||||
* This release, and all future ones, now create two additional archive files
|
||||
in the GitHub release:
|
||||
|
||||
1. `EDMarketConnector-release-<version>.zip`
|
||||
2. `EDMarketConnector-release-<version>.tar.gz`
|
||||
|
||||
The advantage of these over the GitHub auto-generated ones is that they
|
||||
have been hand-crafted to contain *all* the necessary files, and *only*
|
||||
those files.
|
||||
|
||||
**If you use the application from source, and not via a git clone, then we
|
||||
highly recommend you use one of these archives, not the GitHub
|
||||
auto-generated ones.**
|
||||
|
||||
Anyone installing on Windows should continue to use the
|
||||
`EDMarketConnector_win_<version>.msi` files as before.
|
||||
|
||||
* **New Feature** - You can now have the application query the `/fleetcarrier`
|
||||
CAPI endpoint for data about your Fleet Carrier. The data will then be
|
||||
passed to interested plugins.
|
||||
|
||||
Note that there are some caveats:
|
||||
|
||||
1. This feature defaults to *Off*. The option is on the Configuration tab
|
||||
of Settings as "Enable Fleetcarrier CAPI Queries". **It is advised to only
|
||||
enable this if you know you utilise plugins that make use of the data.**
|
||||
2. These queries are *only* triggered by `CarrierBuy` and `CarrierStats`
|
||||
Journal events, i.e. upon buying a Fleetcarrier or opening the Carrier
|
||||
Management UI in-game. **NB: There is a 15 minute cooldown between
|
||||
queries.**
|
||||
|
||||
3. If you have Fleetcarrier cargo which got into the cargo hold through a lot
|
||||
of individual transactions, or if you have a lot of separate buy/sell
|
||||
orders then these queries can take a *long* time to complete.
|
||||
|
||||
**If this happens with your game account then all other CAPI queries will
|
||||
be blocked until the `/fleetcarrier` query completes.** 'Other CAPI
|
||||
queries' means those usually triggered upon docking to gather station
|
||||
market, shipyard and outfitting data. To ameliorate the effects of this
|
||||
there is currently a timeout of 60 seconds on `/fleetcarrier` queries,
|
||||
**and will not occur more often than every 15 minutes**.
|
||||
|
||||
We plan to address this by moving the `/fleetcarrier` queries into their
|
||||
own separate thread in the future.
|
||||
|
||||
* The code for choosing the 'Output' folder is now simply the `tkinter`
|
||||
function for such a dialogue, rather than a special case on Windows. In
|
||||
the past the former had issues with Unicode characters, but in testing no
|
||||
such issue was observed (on a supported OS).
|
||||
|
||||
* There are two new items on the "Help" menu:
|
||||
1. Troubleshooting -> [Wiki:Troubleshooting](https://github.com/EDCD/EDMarketConnector/wiki/Troubleshooting)
|
||||
2. Report A Bug -> [Issues - New Bug Report](https://github.com/EDCD/EDMarketConnector/issues/new?assignees=&labels=bug%2C+unconfirmed&template=bug_report.md&title=)
|
||||
|
||||
* Translations have been updated. Thanks again to our volunteer translators!
|
||||
|
||||
* If we ever activate any functionality killswitches, the popup denoting which
|
||||
are active has been made more readable.
|
||||
|
||||
* There's a new section in `Contributing.md` - "Python Environment". This
|
||||
should aid any new developers in getting things set up.
|
||||
|
||||
Linux Users
|
||||
---
|
||||
We now ship an `io.edcd.EDMarketConnector.desktop` file. To make use of this
|
||||
you should run `scripts/linux-setup.sh` *once*. This will:
|
||||
|
||||
1. Check that you have `$HOME/bin` in your PATH. If not, it will abort.
|
||||
2. Create a shell script `edmarketconnector` in `$HOME/bin` to launch the
|
||||
application.
|
||||
|
||||
NB: This relies on the filesystem location you placed the source in not
|
||||
changing. So if you move the source you will need to re-run the script.
|
||||
3. Copy the .desktop and .icon files into appropriate locations. The .desktop
|
||||
file utilises the shell script created in step 2, and thus relies on it
|
||||
existing *and* on it being in a directory that is in your PATH.
|
||||
|
||||
Once this has been completed any XDG-compliant desktops should have an entry
|
||||
for "E:D Market Connector" in their "Games" menu.
|
||||
|
||||
Fixes
|
||||
---
|
||||
|
||||
* The tracking of a Cmdr's location that was being performed by the core EDDN
|
||||
plugin has been moved into the Journal monitoring code. This results in
|
||||
the tracking being correct upon application (re)start, reflecting the state
|
||||
from the latest Journal file, rather than only picking up with any
|
||||
subsequent new Journal events.
|
||||
|
||||
This change should remove instances of "Wrong System! Missed Jump ?" and
|
||||
similar sanity-check "errors" when continuing to play after a user restarts
|
||||
the application whilst the game is running.
|
||||
|
||||
Plugin developers, see below for how this change can positively affect you.
|
||||
|
||||
* The name of the files written by "File" > "Save Raw Data" now have a `.`
|
||||
between the system and station names.
|
||||
|
||||
* Use of CAPI data in `EDMC.exe` when invoked with either `-s` or `-n`
|
||||
arguments hadn't been updated for prior changes, causing such invocations to
|
||||
fail. This has been fixed.
|
||||
|
||||
Plugin Developers
|
||||
---
|
||||
|
||||
* Each plugin is now handed its own sub-frame as the `parent` parameter passed
|
||||
to `plugin_app()` *instead of the actual main UI frame*. These new Frames
|
||||
are placed in the position that plugin UI would have gone into. This should
|
||||
have no side effects on well-behaved plugins.
|
||||
|
||||
However, if you have code that attempts to do things like `parent.children()`
|
||||
or the like in your `plugin_app()` implementation, this might have stopped
|
||||
working. You shouldn't be trying to do anything with any of the UI outside
|
||||
your plugin *anyway*, but if you definitely have a need then look things up
|
||||
using `.nametowidget()`. There are examples in the core plugins (which *DO*
|
||||
have good reason, due to maintaining main UI label values).
|
||||
|
||||
All of the plugins listed on our Wiki were given *perfunctory* testing and no
|
||||
issues from this change were observed.
|
||||
|
||||
This is a necessary first step to some pending plugin/UI work:
|
||||
|
||||
* [UI: Alllow for re-ordering third-party plugins' UIs](https://github.com/EDCD/EDMarketConnector/issues/1792)
|
||||
* [UI: Allow configuration of number of UI columns.](https://github.com/EDCD/EDMarketConnector/issues/1813)
|
||||
* [Re-work how Plugins' Settings are accessed](https://github.com/EDCD/EDMarketConnector/issues/1814)
|
||||
* **New** - `capi_fleetcarrier()` function to receive the data from a CAPI
|
||||
`/fleetcarrier` query. See PLUGINS.md for details.
|
||||
|
||||
* It was found that the `ShutDown` event (note the capitalisation, this is
|
||||
distinct from the actual Journal `Shutdown` event) synthesized for plugins
|
||||
when it is detected that the game has exited was never actually being
|
||||
delivered. Instead this was erroneously replaced with a synthesized `StartUp`
|
||||
event. This has been fixed.
|
||||
|
||||
* As the location tracking has been moved out of the core EDDN plugin, and into
|
||||
monitor.py all of it is now available as members of the `state` dictionary
|
||||
which is passed to `journal_entry()`.
|
||||
|
||||
This both means that no plugin should need to perform such location state
|
||||
tracking itself *and* they can take advantage of it being fully up to date
|
||||
when a user restarts the application with the game running.
|
||||
|
||||
A reminder: When performing 'catch up' on the newest Journal file found at
|
||||
startup, the application does **not** pass any events to the
|
||||
`journal_entry()` method in plugins. This is to avoid spamming with
|
||||
data/state that has possibly already been handled, and in the case of the
|
||||
Cmdr moving around will end up not being relevant by the time the end of the
|
||||
file is reached. This limitation was also why the core EDDN plugin couldn't
|
||||
properly initiate its location tracking state in this scenario.
|
||||
|
||||
See PLUGINS.md for details of the new `state` members. Pay particular
|
||||
attention to the footnote that details the caveats around Body tracking.
|
||||
|
||||
Careful testing has been done for *only* the following. So, if you make use
|
||||
of any of the other new state values and spot a bug, please report it:
|
||||
|
||||
1. SystemName
|
||||
2. SystemAddress
|
||||
3. Body (Name)
|
||||
4. BodyID
|
||||
5. BodyType
|
||||
6. StationName
|
||||
7. StationType
|
||||
8. (Station) MarketID
|
||||
|
||||
* There is an additional property `request_cmdr` on `CAPIData` objects, which
|
||||
records the name of the Cmdr the request was made for.
|
||||
|
||||
* `FDevIDs` files are their latest versions at time of this version's build.
|
||||
|
||||
* `examples\plugintest` - dropped the "pre-5.0.0 config" code, as it's long
|
||||
since irrelevant.
|
||||
|
||||
Developers
|
||||
---
|
||||
|
||||
* If you utilise a git clone of the source code, you should also ensure the
|
||||
sub-modules are initialised and synchronised.
|
||||
[wiki:Running from source](https://github.com/EDCD/EDMarketConnector/wiki/Running-from-source#obtain-a-copy-of-the-application-source)
|
||||
has been updated to include the necessary commands.
|
||||
|
||||
* The `coriolis-data` git sub-module now uses an HTTPS, not "git" URL, so won't
|
||||
require authentication for a simple `git pull`.
|
||||
|
||||
* If you have a `dump` directory in CWD when running EDMarketConnector.py under
|
||||
a debugger you will get files in that location when CAPI queries complete.
|
||||
This will now include files with names of the form
|
||||
`FleetCarrier.<callsign>.<timstamp>.json` for `/fleetcarrier` data.
|
||||
|
||||
* All the main UI tk widgets are now properly named. This might make things
|
||||
easier if debugging UI widgets as you'll no longer see a bunch of `!label1`,
|
||||
`!frame1` and the like.
|
||||
|
||||
Each plugin's separator is named as per the scheme `plugin_hr_<X>`, and when
|
||||
a plugin has UI its new container Frame is named `plugin_X`. Both of these
|
||||
start with `1`, not `0`.
|
||||
|
||||
---
|
||||
|
||||
Release 5.7.0
|
||||
===
|
||||
This release re-enables CAPI queries for Legacy players. As a result, the
|
||||
|
||||
+97
-3
@@ -196,6 +196,99 @@ Currently, the only file that defines the version code-wise is
|
||||
matter handled as part of
|
||||
[the release process](docs/Releasing.md#distribution).
|
||||
|
||||
---
|
||||
## Python Environment
|
||||
Whilst you can use whatever IDE/development environment best suits you, much
|
||||
of the setup in this project has only been tested against PyCharm or VSCode,
|
||||
along with 'git bash' command-line.
|
||||
|
||||
### Use the version denoted by `.python-version`
|
||||
We only test, and build with, the python version as defined in the file
|
||||
`.python-version`. Trying to use any other version might mean things just
|
||||
don't run at all, or don't work as expected.
|
||||
|
||||
### Use a Python virtual environment
|
||||
Always use a Python virtual environment specific to working on this project.
|
||||
|
||||
An example, when using Python 3.11.x would be:
|
||||
```bash
|
||||
python -m venv ../edmc-venv-3.11
|
||||
```
|
||||
Note how the 'venv' is placed in a sub-directory *of the parent directory* of
|
||||
the project. This avoids any issues with scripts working recursively picking
|
||||
up your 'venv' files.
|
||||
|
||||
If you have good reason to put the 'venv' inside the project directory then
|
||||
you **MUST** use either `venv` or `.venv`, else you'll run into all sorts of
|
||||
problems with pre-commit checks.
|
||||
|
||||
### Install the development requirements
|
||||
Whilst simply running the project only requires
|
||||
`pip install -r requirements.txt`-provided modules, development work will
|
||||
instead require:
|
||||
```bash
|
||||
pip install -r requirements-dev.txt
|
||||
```
|
||||
NB: This itself will also take note of `requirements.txt`.
|
||||
|
||||
This will ensure you have all the necessary tools to hand for the pre-commit
|
||||
checks.
|
||||
|
||||
### Set up `pre-commit`
|
||||
In order to have any submitted PR be in the least-worse shape when first opened
|
||||
you **MUST** run the checks as specified in `.pre-commit-config.yaml`.
|
||||
```bash
|
||||
pre-commit install --install-hooks
|
||||
```
|
||||
Now whenever you `git commit` the various checks will be run to ensure your
|
||||
code is compliant with our requirements. If you have a *temporary* need to
|
||||
bypass this (e.g. wanting to commit one change and fix a non-compliant file
|
||||
later) you can add `-n` to the `git commit` arguments.
|
||||
|
||||
**NB: There is [a problem](https://github.com/microsoft/vscode-python/issues/10165)
|
||||
with pre-commit if using VSCode.** There's a workaround in
|
||||
[one of the comments](https://github.com/microsoft/vscode-python/issues/10165#issuecomment-1277237676).
|
||||
|
||||
### Consider running `pytest` before any `git push`
|
||||
The GitHub workflows for PRs and pushes will run `pytest` and flag an error
|
||||
if the tests don't pass, so it's in your interests to ensure you've not broken
|
||||
any tests.
|
||||
|
||||
You could endeavour to remember to run `pytest` manually, or you could add
|
||||
this git hook:
|
||||
|
||||
`.git/hooks/pre-push`
|
||||
```bash
|
||||
#!/bin/sh
|
||||
|
||||
# If this script exits with a non-zero status nothing will be pushed.
|
||||
#
|
||||
# This hook is called with the following parameters:
|
||||
#
|
||||
# $1 -- Name of the remote to which the push is being done
|
||||
# $2 -- URL to which the push is being done
|
||||
#
|
||||
# If pushing without using a named remote those arguments will be equal.
|
||||
#
|
||||
# Information about the commits which are being pushed is supplied as lines to
|
||||
# the standard input in the form:
|
||||
#
|
||||
# <local ref> <local sha1> <remote ref> <remote sha1>
|
||||
|
||||
remote="$1"
|
||||
url="$2"
|
||||
|
||||
echo "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
|
||||
echo " Running pytest..."
|
||||
pytest || exit 1
|
||||
echo " All tests passed, proceeding..."
|
||||
echo "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
|
||||
|
||||
exit 0
|
||||
```
|
||||
It's probably overkill, and will become painful if enough tests are added, to
|
||||
run `pytest` in a `pre-commit` hook.
|
||||
|
||||
---
|
||||
|
||||
## Linting
|
||||
@@ -296,7 +389,7 @@ information about this build process.
|
||||
|
||||
Thus, you **MUST** check if any imports you add in `plugins/*.py` files are only
|
||||
referenced in that file (or also only in any other core plugin), and if so
|
||||
**YOU MUST ENSURE THAT PERTINENT ADJUSTMENTS ARE MADE IN `setup.py`
|
||||
**YOU MUST ENSURE THAT PERTINENT ADJUSTMENTS ARE MADE IN `Build-exe-and-msi.py`
|
||||
IN ORDER TO ENSURE THE FILES ARE ACTUALLY PRESENT IN AN END-USER
|
||||
INSTALLATION ON WINDOWS.**
|
||||
|
||||
@@ -316,8 +409,9 @@ the appropriate `packages` definition to:
|
||||
Note that in this case it's in `packages` because we want the whole directory
|
||||
adding. For a single file an extra item in `includes` would suffice.
|
||||
|
||||
Such additions to `setup.py` should not cause any issues if subsequent project
|
||||
changes cause `py2exe` to automatically pick up the same file(s).
|
||||
Such additions to `Build-exe-and-msi.py` should not cause any issues if
|
||||
subsequent project changes cause `py2exe` to automatically pick up the same
|
||||
file(s).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ def versioncmp(versionstring) -> List:
|
||||
return list(map(int, versionstring.split('.')))
|
||||
|
||||
|
||||
def deep_get(target: dict, *args: str, default=None) -> Any:
|
||||
def deep_get(target: dict | companion.CAPIData, *args: str, default=None) -> Any:
|
||||
"""
|
||||
Walk into a dict and return the specified deep value.
|
||||
|
||||
@@ -224,12 +224,15 @@ sys.path: {sys.path}'''
|
||||
|
||||
logger.debug(f'logdir = "{monitor.currentdir}"')
|
||||
logfile = monitor.journal_newest_filename(monitor.currentdir)
|
||||
if logfile is None:
|
||||
raise ValueError("None from monitor.journal_newest_filename")
|
||||
|
||||
logger.debug(f'Using logfile "{logfile}"')
|
||||
with open(logfile, 'r', encoding='utf-8') as loghandle:
|
||||
with open(logfile, 'rb', 0) as loghandle:
|
||||
for line in loghandle:
|
||||
try:
|
||||
monitor.parse_entry(line)
|
||||
|
||||
except Exception:
|
||||
logger.debug(f'Invalid journal entry {line!r}')
|
||||
|
||||
@@ -323,10 +326,12 @@ sys.path: {sys.path}'''
|
||||
raise companion.CmdrError()
|
||||
|
||||
elif (
|
||||
data['lastSystem']['name'] != monitor.system or
|
||||
((data['commander']['docked'] and data['lastStarport']['name'] or None) != monitor.station) or
|
||||
data['ship']['id'] != monitor.state['ShipID'] or
|
||||
data['ship']['name'].lower() != monitor.state['ShipType']
|
||||
data['lastSystem']['name'] != monitor.state['SystemName']
|
||||
or (
|
||||
(data['commander']['docked'] and data['lastStarport']['name'] or None) != monitor.state['StationName']
|
||||
)
|
||||
or data['ship']['id'] != monitor.state['ShipID']
|
||||
or data['ship']['name'].lower() != monitor.state['ShipType']
|
||||
):
|
||||
raise companion.ServerLagging()
|
||||
|
||||
@@ -410,12 +415,29 @@ sys.path: {sys.path}'''
|
||||
|
||||
# Retry for shipyard
|
||||
sleep(SERVER_RETRY)
|
||||
new_data = companion.session.station()
|
||||
# might have undocked while we were waiting for retry in which case station data is unreliable
|
||||
if new_data['commander'].get('docked') and \
|
||||
deep_get(new_data, 'lastSystem', 'name') == monitor.system and \
|
||||
deep_get(new_data, 'lastStarport', 'name') == monitor.station:
|
||||
companion.session.station(int(time()))
|
||||
# Wait for the response
|
||||
_capi_request_timeout = 60
|
||||
try:
|
||||
capi_response = companion.session.capi_response_queue.get(
|
||||
block=True, timeout=_capi_request_timeout
|
||||
)
|
||||
|
||||
except queue.Empty:
|
||||
logger.error(f'CAPI requests timed out after {_capi_request_timeout} seconds')
|
||||
sys.exit(EXIT_SERVER)
|
||||
|
||||
if isinstance(capi_response, companion.EDMCCAPIFailedRequest):
|
||||
logger.error(f'Failed Request: {capi_response.message}')
|
||||
sys.exit(EXIT_SERVER)
|
||||
|
||||
new_data = capi_response.capi_data
|
||||
# might have undocked while we were waiting for retry in which case station data is unreliable
|
||||
if (
|
||||
new_data['commander'].get('docked')
|
||||
and deep_get(new_data, 'lastSystem', 'name') == monitor.state['SystemName']
|
||||
and deep_get(new_data, 'lastStarport', 'name') == monitor.state['StationName']
|
||||
):
|
||||
data = new_data
|
||||
|
||||
if args.s:
|
||||
|
||||
+4
-4
@@ -145,7 +145,7 @@ class Logger:
|
||||
logging.Logger instance.
|
||||
"""
|
||||
|
||||
def __init__(self, logger_name: str, loglevel: int = _default_loglevel):
|
||||
def __init__(self, logger_name: str, loglevel: int | str = _default_loglevel):
|
||||
"""
|
||||
Set up a `logging.Logger` with our preferred configuration.
|
||||
|
||||
@@ -216,7 +216,7 @@ class Logger:
|
||||
"""
|
||||
return self.logger_channel
|
||||
|
||||
def set_channels_loglevel(self, level: int) -> None:
|
||||
def set_channels_loglevel(self, level: int | str) -> None:
|
||||
"""
|
||||
Set the specified log level on the channels.
|
||||
|
||||
@@ -226,7 +226,7 @@ class Logger:
|
||||
self.logger_channel.setLevel(level)
|
||||
self.logger_channel_rotating.setLevel(level)
|
||||
|
||||
def set_console_loglevel(self, level: int) -> None:
|
||||
def set_console_loglevel(self, level: int | str) -> None:
|
||||
"""
|
||||
Set the specified log level on the console channel.
|
||||
|
||||
@@ -541,7 +541,7 @@ def get_main_logger(sublogger_name: str = '') -> 'LoggerMixin':
|
||||
|
||||
|
||||
# Singleton
|
||||
loglevel = config.get_str('loglevel')
|
||||
loglevel: str | int = config.get_str('loglevel')
|
||||
if not loglevel:
|
||||
loglevel = logging.INFO
|
||||
|
||||
|
||||
+326
-120
@@ -16,7 +16,7 @@ from builtins import object, str
|
||||
from os import chdir, environ
|
||||
from os.path import dirname, join
|
||||
from time import localtime, strftime, time
|
||||
from typing import TYPE_CHECKING, Literal, Optional, Tuple, Union
|
||||
from typing import TYPE_CHECKING, Any, Literal, Optional, Tuple, Union
|
||||
|
||||
# Have this as early as possible for people running EDMarketConnector.exe
|
||||
# from cmd.exe or a bat file or similar. Else they might not be in the correct
|
||||
@@ -168,6 +168,11 @@ if __name__ == '__main__': # noqa: C901
|
||||
help='Have EDDN plugin show what it is tracking',
|
||||
action='store_true',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--killswitches-file',
|
||||
help='Specify a custom killswitches file',
|
||||
)
|
||||
###########################################################################
|
||||
|
||||
args = parser.parse_args()
|
||||
@@ -382,7 +387,9 @@ if __name__ == '__main__': # noqa: C901
|
||||
if (
|
||||
(
|
||||
git_branch == 'develop'
|
||||
or '-alpha0' in str(appversion())
|
||||
or (
|
||||
git_branch == '' and '-alpha0' in str(appversion())
|
||||
)
|
||||
) and (
|
||||
(
|
||||
sys.platform == 'linux'
|
||||
@@ -469,6 +476,8 @@ class AppWindow(object):
|
||||
def __init__(self, master: tk.Tk): # noqa: C901, CCR001 # TODO - can possibly factor something out
|
||||
|
||||
self.capi_query_holdoff_time = config.get_int('querytime', default=0) + companion.capi_query_cooldown
|
||||
self.capi_fleetcarrier_query_holdoff_time = config.get_int('fleetcarrierquerytime', default=0) \
|
||||
+ companion.capi_fleetcarrier_query_cooldown
|
||||
|
||||
self.w = master
|
||||
self.w.title(applongname)
|
||||
@@ -500,7 +509,7 @@ class AppWindow(object):
|
||||
|
||||
else:
|
||||
self.w.tk.call('wm', 'iconphoto', self.w, '-default',
|
||||
tk.PhotoImage(file=join(config.respath_path, 'EDMarketConnector.png')))
|
||||
tk.PhotoImage(file=join(config.respath_path, 'io.edcd.EDMarketConnector.png')))
|
||||
|
||||
# TODO: Export to files and merge from them in future ?
|
||||
self.theme_icon = tk.PhotoImage(
|
||||
@@ -514,20 +523,21 @@ class AppWindow(object):
|
||||
frame.grid(sticky=tk.NSEW)
|
||||
frame.columnconfigure(1, weight=1)
|
||||
|
||||
self.cmdr_label = tk.Label(frame)
|
||||
self.cmdr_label = tk.Label(frame, name='cmdr_label')
|
||||
self.cmdr = tk.Label(frame, compound=tk.RIGHT, anchor=tk.W, name='cmdr')
|
||||
self.ship_label = tk.Label(frame)
|
||||
self.ship_label = tk.Label(frame, name='ship_label')
|
||||
self.ship = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.shipyard_url, name='ship')
|
||||
self.suit_label = tk.Label(frame)
|
||||
self.suit_label = tk.Label(frame, name='suit_label')
|
||||
self.suit = tk.Label(frame, compound=tk.RIGHT, anchor=tk.W, name='suit')
|
||||
self.system_label = tk.Label(frame)
|
||||
self.system_label = tk.Label(frame, name='system_label')
|
||||
self.system = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.system_url, popup_copy=True, name='system')
|
||||
self.station_label = tk.Label(frame)
|
||||
self.station_label = tk.Label(frame, name='station_label')
|
||||
self.station = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.station_url, name='station')
|
||||
# system and station text is set/updated by the 'provider' plugins
|
||||
# eddb, edsm and inara. Look for:
|
||||
#
|
||||
# parent.children['system'] / parent.children['station']
|
||||
# parent.nametowidget(f".{appname.lower()}.system")
|
||||
# parent.nametowidget(f".{appname.lower()}.station")
|
||||
|
||||
ui_row = 1
|
||||
|
||||
@@ -551,10 +561,26 @@ class AppWindow(object):
|
||||
self.station.grid(row=ui_row, column=1, sticky=tk.EW)
|
||||
ui_row += 1
|
||||
|
||||
plugin_no = 0
|
||||
for plugin in plug.PLUGINS:
|
||||
appitem = plugin.get_app(frame)
|
||||
# Per plugin separator
|
||||
plugin_sep = tk.Frame(
|
||||
frame, highlightthickness=1, name=f"plugin_hr_{plugin_no + 1}"
|
||||
)
|
||||
# Per plugin frame, for it to use as its parent for own widgets
|
||||
plugin_frame = tk.Frame(
|
||||
frame,
|
||||
name=f"plugin_{plugin_no + 1}"
|
||||
)
|
||||
appitem = plugin.get_app(plugin_frame)
|
||||
if appitem:
|
||||
tk.Frame(frame, highlightthickness=1).grid(columnspan=2, sticky=tk.EW) # separator
|
||||
plugin_no += 1
|
||||
plugin_sep.grid(columnspan=2, sticky=tk.EW)
|
||||
ui_row = frame.grid_size()[1]
|
||||
plugin_frame.grid(
|
||||
row=ui_row, columnspan=2, sticky=tk.NSEW
|
||||
)
|
||||
plugin_frame.columnconfigure(1, weight=1)
|
||||
if isinstance(appitem, tuple) and len(appitem) == 2:
|
||||
ui_row = frame.grid_size()[1]
|
||||
appitem[0].grid(row=ui_row, column=0, sticky=tk.W)
|
||||
@@ -563,9 +589,26 @@ class AppWindow(object):
|
||||
else:
|
||||
appitem.grid(columnspan=2, sticky=tk.EW)
|
||||
|
||||
else:
|
||||
# This plugin didn't provide any UI, so drop the frames
|
||||
plugin_frame.destroy()
|
||||
plugin_sep.destroy()
|
||||
|
||||
# LANG: Update button in main window
|
||||
self.button = ttk.Button(frame, text=_('Update'), width=28, default=tk.ACTIVE, state=tk.DISABLED)
|
||||
self.theme_button = tk.Label(frame, width=32 if sys.platform == 'darwin' else 28, state=tk.DISABLED)
|
||||
self.button = ttk.Button(
|
||||
frame,
|
||||
name='update_button',
|
||||
text=_('Update'), # LANG: Main UI Update button
|
||||
width=28,
|
||||
default=tk.ACTIVE,
|
||||
state=tk.DISABLED
|
||||
)
|
||||
self.theme_button = tk.Label(
|
||||
frame,
|
||||
name='themed_update_button',
|
||||
width=32 if sys.platform == 'darwin' else 28,
|
||||
state=tk.DISABLED
|
||||
)
|
||||
|
||||
ui_row = frame.grid_size()[1]
|
||||
self.button.grid(row=ui_row, columnspan=2, sticky=tk.NSEW)
|
||||
@@ -583,11 +626,20 @@ class AppWindow(object):
|
||||
child.grid_configure(padx=self.PADX, pady=(
|
||||
sys.platform != 'win32' or isinstance(child, tk.Frame)) and 2 or 0)
|
||||
|
||||
# The type needs defining for adding the menu entry, but won't be
|
||||
# properly set until later
|
||||
self.updater: update.Updater = None
|
||||
|
||||
self.menubar = tk.Menu()
|
||||
|
||||
# This used to be *after* the menu setup for some reason, but is testing
|
||||
# as working (both internal and external) like this. -Ath
|
||||
import update
|
||||
|
||||
if getattr(sys, 'frozen', False):
|
||||
# Running in frozen .exe, so use (Win)Sparkle
|
||||
self.updater = update.Updater(tkroot=self.w, provider='external')
|
||||
|
||||
else:
|
||||
self.updater = update.Updater(tkroot=self.w, provider='internal')
|
||||
self.updater.check_for_updates() # Sparkle / WinSparkle does this automatically for packaged apps
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
# Can't handle (de)iconify if topmost is set, so suppress iconify button
|
||||
# http://wiki.tcl.tk/13428 and p15 of
|
||||
@@ -613,6 +665,8 @@ class AppWindow(object):
|
||||
self.menubar.add_cascade(menu=window_menu)
|
||||
self.help_menu = tk.Menu(self.menubar, name='help')
|
||||
self.w.createcommand("::tk::mac::ShowHelp", self.help_general)
|
||||
self.help_menu.add_command(command=self.help_troubleshooting)
|
||||
self.help_menu.add_command(command=self.help_report_a_bug)
|
||||
self.help_menu.add_command(command=self.help_privacy)
|
||||
self.help_menu.add_command(command=self.help_releases)
|
||||
self.menubar.add_cascade(menu=self.help_menu)
|
||||
@@ -637,10 +691,13 @@ class AppWindow(object):
|
||||
self.edit_menu.add_command(accelerator='Ctrl+C', state=tk.DISABLED, command=self.copy)
|
||||
self.menubar.add_cascade(menu=self.edit_menu)
|
||||
self.help_menu = tk.Menu(self.menubar, tearoff=tk.FALSE) # type: ignore
|
||||
self.help_menu.add_command(command=self.help_general)
|
||||
self.help_menu.add_command(command=self.help_privacy)
|
||||
self.help_menu.add_command(command=self.help_releases)
|
||||
self.help_menu.add_command(command=lambda: self.updater.check_for_updates())
|
||||
self.help_menu.add_command(command=self.help_general) # Documentation
|
||||
self.help_menu.add_command(command=self.help_troubleshooting) # Troubleshooting
|
||||
self.help_menu.add_command(command=self.help_report_a_bug) # Report A Bug
|
||||
self.help_menu.add_command(command=self.help_privacy) # Privacy Policy
|
||||
self.help_menu.add_command(command=self.help_releases) # Release Notes
|
||||
self.help_menu.add_command(command=lambda: self.updater.check_for_updates()) # Check for Updates...
|
||||
# About E:D Market Connector
|
||||
self.help_menu.add_command(command=lambda: not self.HelpAbout.showing and self.HelpAbout(self.w))
|
||||
|
||||
self.menubar.add_cascade(menu=self.help_menu)
|
||||
@@ -666,11 +723,15 @@ class AppWindow(object):
|
||||
theme.register(self.help_menu)
|
||||
|
||||
# Alternate title bar and menu for dark theme
|
||||
self.theme_menubar = tk.Frame(frame)
|
||||
self.theme_menubar = tk.Frame(frame, name="alternate_menubar")
|
||||
self.theme_menubar.columnconfigure(2, weight=1)
|
||||
theme_titlebar = tk.Label(self.theme_menubar, text=applongname,
|
||||
image=self.theme_icon, cursor='fleur',
|
||||
anchor=tk.W, compound=tk.LEFT)
|
||||
theme_titlebar = tk.Label(
|
||||
self.theme_menubar,
|
||||
name="alternate_titlebar",
|
||||
text=applongname,
|
||||
image=self.theme_icon, cursor='fleur',
|
||||
anchor=tk.W, compound=tk.LEFT
|
||||
)
|
||||
theme_titlebar.grid(columnspan=3, padx=2, sticky=tk.NSEW)
|
||||
self.drag_offset: Tuple[Optional[int], Optional[int]] = (None, None)
|
||||
theme_titlebar.bind('<Button-1>', self.drag_start)
|
||||
@@ -703,7 +764,7 @@ class AppWindow(object):
|
||||
tk.Frame(self.theme_menubar, highlightthickness=1).grid(columnspan=5, padx=self.PADX, sticky=tk.EW)
|
||||
theme.register(self.theme_minimize) # images aren't automatically registered
|
||||
theme.register(self.theme_close)
|
||||
self.blank_menubar = tk.Frame(frame)
|
||||
self.blank_menubar = tk.Frame(frame, name="blank_menubar")
|
||||
tk.Label(self.blank_menubar).grid()
|
||||
tk.Label(self.blank_menubar).grid()
|
||||
tk.Frame(self.blank_menubar, height=2).grid()
|
||||
@@ -755,16 +816,6 @@ class AppWindow(object):
|
||||
# Start a protocol handler to handle cAPI registration. Requires main loop to be running.
|
||||
self.w.after_idle(lambda: protocol.protocolhandler.start(self.w))
|
||||
|
||||
# Load updater after UI creation (for WinSparkle)
|
||||
import update
|
||||
|
||||
if getattr(sys, 'frozen', False):
|
||||
# Running in frozen .exe, so use (Win)Sparkle
|
||||
self.updater = update.Updater(tkroot=self.w, provider='external')
|
||||
else:
|
||||
self.updater = update.Updater(tkroot=self.w, provider='internal')
|
||||
self.updater.check_for_updates() # Sparkle / WinSparkle does this automatically for packaged apps
|
||||
|
||||
# Migration from <= 3.30
|
||||
for username in config.get_list('fdev_usernames', default=[]):
|
||||
config.delete_password(username)
|
||||
@@ -879,8 +930,11 @@ class AppWindow(object):
|
||||
self.system_menu.entryconfigure(1, label=_("Check for Updates...")) # LANG: Help > Check for Updates...
|
||||
self.file_menu.entryconfigure(0, label=_('Save Raw Data...')) # LANG: File > Save Raw Data...
|
||||
self.view_menu.entryconfigure(0, label=_('Status')) # LANG: File > Status
|
||||
self.help_menu.entryconfigure(1, label=_('Privacy Policy')) # LANG: Help > Privacy Policy
|
||||
self.help_menu.entryconfigure(2, label=_('Release Notes')) # LANG: Help > Release Notes
|
||||
self.help_menu.entryconfigure(1, label=_('Documentation')) # LANG: Help > Documentation
|
||||
self.help_menu.entryconfigure(2, label=_('Troubleshooting')) # LANG: Help > Troubleshooting
|
||||
self.help_menu.entryconfigure(3, label=_('Report A Bug')) # LANG: Help > Report A Bug
|
||||
self.help_menu.entryconfigure(4, label=_('Privacy Policy')) # LANG: Help > Privacy Policy
|
||||
self.help_menu.entryconfigure(5, label=_('Release Notes')) # LANG: Help > Release Notes
|
||||
else:
|
||||
self.menubar.entryconfigure(1, label=_('File')) # LANG: 'File' menu title
|
||||
self.menubar.entryconfigure(2, label=_('Edit')) # LANG: 'Edit' menu title
|
||||
@@ -897,16 +951,28 @@ class AppWindow(object):
|
||||
|
||||
# Help menu
|
||||
self.help_menu.entryconfigure(0, label=_('Documentation')) # LANG: Help > Documentation
|
||||
self.help_menu.entryconfigure(1, label=_('Privacy Policy')) # LANG: Help > Privacy Policy
|
||||
self.help_menu.entryconfigure(2, label=_('Release Notes')) # LANG: Help > Release Notes
|
||||
self.help_menu.entryconfigure(3, label=_('Check for Updates...')) # LANG: Help > Check for Updates...
|
||||
self.help_menu.entryconfigure(4, label=_("About {APP}").format(APP=applongname)) # LANG: Help > About App
|
||||
self.help_menu.entryconfigure(1, label=_('Troubleshooting')) # LANG: Help > Troubleshooting
|
||||
self.help_menu.entryconfigure(2, label=_('Report A Bug')) # LANG: Help > Report A Bug
|
||||
self.help_menu.entryconfigure(3, label=_('Privacy Policy')) # LANG: Help > Privacy Policy
|
||||
self.help_menu.entryconfigure(4, label=_('Release Notes')) # LANG: Help > Release Notes
|
||||
self.help_menu.entryconfigure(5, label=_('Check for Updates...')) # LANG: Help > Check for Updates...
|
||||
self.help_menu.entryconfigure(6, label=_("About {APP}").format(APP=applongname)) # LANG: Help > About App
|
||||
|
||||
# Edit menu
|
||||
self.edit_menu.entryconfigure(0, label=_('Copy')) # LANG: Label for 'Copy' as in 'Copy and Paste'
|
||||
|
||||
def login(self):
|
||||
"""Initiate CAPI/Frontier login and set other necessary state."""
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
||||
if should_return:
|
||||
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
||||
# LANG: CAPI auth aborted because of killswitch
|
||||
self.status['text'] = _('CAPI auth disabled by killswitch')
|
||||
return
|
||||
|
||||
if not self.status['text']:
|
||||
# LANG: Status - Attempting to get a Frontier Auth Access Token
|
||||
self.status['text'] = _('Logging in...')
|
||||
@@ -992,6 +1058,16 @@ class AppWindow(object):
|
||||
:param event: Tk generated event details.
|
||||
"""
|
||||
logger.trace_if('capi.worker', 'Begin')
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
||||
if should_return:
|
||||
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
||||
# LANG: CAPI auth query aborted because of killswitch
|
||||
self.status['text'] = _('CAPI auth disabled by killswitch')
|
||||
hotkeymgr.play_bad()
|
||||
return
|
||||
|
||||
auto_update = not event
|
||||
play_sound = (auto_update or int(event.type) == self.EVENT_VIRTUAL) and not config.get_int('hotkey_mute')
|
||||
|
||||
@@ -1013,7 +1089,7 @@ class AppWindow(object):
|
||||
self.status['text'] = _('CAPI query aborted: GameVersion unknown')
|
||||
return
|
||||
|
||||
if not monitor.system:
|
||||
if not monitor.state['SystemName']:
|
||||
logger.trace_if('capi.worker', 'Aborting Query: Current star system unknown')
|
||||
# LANG: CAPI queries aborted because current star system name unknown
|
||||
self.status['text'] = _('CAPI query aborted: Current system unknown')
|
||||
@@ -1062,6 +1138,55 @@ class AppWindow(object):
|
||||
play_sound=play_sound
|
||||
)
|
||||
|
||||
def capi_request_fleetcarrier_data(self, event=None) -> None:
|
||||
"""
|
||||
Perform CAPI fleetcarrier data retrieval and associated actions.
|
||||
|
||||
This is triggered by certain FleetCarrier journal events
|
||||
|
||||
:param event: Tk generated event details.
|
||||
"""
|
||||
logger.trace_if('capi.worker', 'Begin')
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('capi.request.fleetcarrier', {})
|
||||
if should_return:
|
||||
logger.warning('capi.fleetcarrier has been disabled via killswitch. Returning.')
|
||||
# LANG: CAPI fleetcarrier query aborted because of killswitch
|
||||
self.status['text'] = _('CAPI fleetcarrier disabled by killswitch')
|
||||
hotkeymgr.play_bad()
|
||||
return
|
||||
|
||||
if not monitor.cmdr:
|
||||
logger.trace_if('capi.worker', 'Aborting Query: Cmdr unknown')
|
||||
# LANG: CAPI fleetcarrier query aborted because Cmdr name is unknown
|
||||
self.status['text'] = _('CAPI query aborted: Cmdr name unknown')
|
||||
return
|
||||
|
||||
if monitor.state['GameVersion'] is None:
|
||||
logger.trace_if('capi.worker', 'Aborting Query: GameVersion unknown')
|
||||
# LANG: CAPI fleetcarrier query aborted because GameVersion unknown
|
||||
self.status['text'] = _('CAPI query aborted: GameVersion unknown')
|
||||
return
|
||||
|
||||
if not companion.session.retrying:
|
||||
if time() < self.capi_fleetcarrier_query_holdoff_time: # Was invoked while in cooldown
|
||||
logger.debug('CAPI fleetcarrier query aborted, too soon since last request')
|
||||
return
|
||||
|
||||
# LANG: Status - Attempting to retrieve data from Frontier CAPI
|
||||
self.status['text'] = _('Fetching data...')
|
||||
self.w.update_idletasks()
|
||||
|
||||
query_time = int(time())
|
||||
logger.trace_if('capi.worker', 'Requesting fleetcarrier data')
|
||||
config.set('fleetcarrierquerytime', query_time)
|
||||
logger.trace_if('capi.worker', 'Calling companion.session.fleetcarrier')
|
||||
companion.session.fleetcarrier(
|
||||
query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME
|
||||
)
|
||||
|
||||
def capi_handle_response(self, event=None): # noqa: C901, CCR001
|
||||
"""Handle the resulting data from a CAPI query."""
|
||||
logger.trace_if('capi.worker', 'Handling response')
|
||||
@@ -1086,8 +1211,32 @@ class AppWindow(object):
|
||||
logger.error(msg)
|
||||
raise ValueError(msg)
|
||||
|
||||
if capi_response.capi_data.source_endpoint == companion.session.FRONTIER_CAPI_PATH_FLEETCARRIER:
|
||||
# Fleetcarrier CAPI response
|
||||
# Validation
|
||||
if 'name' not in capi_response.capi_data:
|
||||
# LANG: No data was returned for the fleetcarrier from the Frontier CAPI
|
||||
err = self.status['text'] = _('CAPI: No fleetcarrier data returned')
|
||||
|
||||
elif not capi_response.capi_data.get('name', {}).get('callsign'):
|
||||
# LANG: We didn't have the fleetcarrier callsign when we should have
|
||||
err = self.status['text'] = _("CAPI: Fleetcarrier data incomplete") # Shouldn't happen
|
||||
|
||||
else:
|
||||
if __debug__: # Recording
|
||||
companion.session.dump_capi_data(capi_response.capi_data)
|
||||
|
||||
err = plug.notify_capi_fleetcarrierdata(capi_response.capi_data)
|
||||
self.status['text'] = err and err or ''
|
||||
if err:
|
||||
play_bad = True
|
||||
|
||||
self.capi_fleetcarrier_query_holdoff_time = capi_response.query_time \
|
||||
+ companion.capi_fleetcarrier_query_cooldown
|
||||
|
||||
# Other CAPI response
|
||||
# Validation
|
||||
if 'commander' not in capi_response.capi_data:
|
||||
elif 'commander' not in capi_response.capi_data:
|
||||
# This can happen with EGS Auth if no commander created yet
|
||||
# LANG: No data was returned for the commander from the Frontier CAPI
|
||||
err = self.status['text'] = _('CAPI: No commander data returned')
|
||||
@@ -1123,30 +1272,32 @@ class AppWindow(object):
|
||||
f"not {capi_response.capi_data['commander'].get('docked')!r}")
|
||||
raise companion.ServerLagging()
|
||||
|
||||
elif capi_response.capi_data['lastSystem']['name'] != monitor.system:
|
||||
elif capi_response.capi_data['lastSystem']['name'] != monitor.state['SystemName']:
|
||||
# CAPI system must match last journal one
|
||||
logger.warning(f"{capi_response.capi_data['lastSystem']['name']!r} != {monitor.system!r}")
|
||||
logger.warning(f"{capi_response.capi_data['lastSystem']['name']!r} != "
|
||||
f"{monitor.state['SystemName']!r}")
|
||||
raise companion.ServerLagging()
|
||||
|
||||
elif capi_response.capi_data['lastStarport']['name'] != monitor.station:
|
||||
if monitor.state['OnFoot'] and monitor.station:
|
||||
logger.warning(f"({capi_response.capi_data['lastStarport']['name']!r} != {monitor.station!r}) AND "
|
||||
f"{monitor.state['OnFoot']!r} and {monitor.station!r}")
|
||||
elif capi_response.capi_data['lastStarport']['name'] != monitor.state['StationName']:
|
||||
if monitor.state['OnFoot'] and monitor.state['StationName']:
|
||||
logger.warning(f"({capi_response.capi_data['lastStarport']['name']!r} != "
|
||||
f"{monitor.state['StationName']!r}) AND "
|
||||
f"{monitor.state['OnFoot']!r} and {monitor.state['StationName']!r}")
|
||||
raise companion.ServerLagging()
|
||||
|
||||
elif capi_response.capi_data['commander']['docked'] and monitor.station is None:
|
||||
elif capi_response.capi_data['commander']['docked'] and monitor.state['StationName'] is None:
|
||||
# Likely (re-)Embarked on ship docked at an EDO settlement.
|
||||
# Both Disembark and Embark have `"Onstation": false` in Journal.
|
||||
# So there's nothing to tell us which settlement we're (still,
|
||||
# or now, if we came here in Apex and then recalled ship) docked at.
|
||||
logger.debug("docked AND monitor.station is None - so EDO settlement?")
|
||||
logger.debug("docked AND monitor.state['StationName'] is None - so EDO settlement?")
|
||||
raise companion.NoMonitorStation()
|
||||
|
||||
self.capi_query_holdoff_time = capi_response.query_time + companion.capi_query_cooldown
|
||||
|
||||
elif capi_response.capi_data['lastStarport']['id'] != monitor.station_marketid:
|
||||
elif capi_response.capi_data['lastStarport']['id'] != monitor.state['MarketID']:
|
||||
logger.warning(f"MarketID mis-match: {capi_response.capi_data['lastStarport']['id']!r} !="
|
||||
f" {monitor.station_marketid!r}")
|
||||
f" {monitor.state['MarketID']!r}")
|
||||
raise companion.ServerLagging()
|
||||
|
||||
elif not monitor.state['OnFoot'] and capi_response.capi_data['ship']['id'] != monitor.state['ShipID']:
|
||||
@@ -1210,10 +1361,18 @@ class AppWindow(object):
|
||||
if err:
|
||||
play_bad = True
|
||||
|
||||
# Export market data
|
||||
if not self.export_market_data(capi_response.capi_data):
|
||||
err = 'Error: Exporting Market data'
|
||||
play_bad = True
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('capi.request./market', {})
|
||||
if should_return:
|
||||
logger.warning("capi.request./market has been disabled by killswitch. Returning.")
|
||||
|
||||
else:
|
||||
# Export market data
|
||||
if not self.export_market_data(capi_response.capi_data):
|
||||
err = 'Error: Exporting Market data'
|
||||
play_bad = True
|
||||
|
||||
self.capi_query_holdoff_time = capi_response.query_time + companion.capi_query_cooldown
|
||||
|
||||
@@ -1228,7 +1387,7 @@ class AppWindow(object):
|
||||
|
||||
except companion.CredentialsRequireRefresh:
|
||||
# We need to 'close' the auth else it'll see STATE_OK and think login() isn't needed
|
||||
companion.session.close()
|
||||
companion.session.reinit_session()
|
||||
# LANG: Frontier CAPI Access Token expired, trying to get a new one
|
||||
self.status['text'] = _('CAPI: Refreshing access token...')
|
||||
if companion.session.login():
|
||||
@@ -1369,7 +1528,7 @@ class AppWindow(object):
|
||||
self.update_suit_text()
|
||||
self.suit_show_if_set()
|
||||
|
||||
self.edit_menu.entryconfigure(0, state=monitor.system and tk.NORMAL or tk.DISABLED) # Copy
|
||||
self.edit_menu.entryconfigure(0, state=monitor.state['SystemName'] and tk.NORMAL or tk.DISABLED) # Copy
|
||||
|
||||
if entry['event'] in (
|
||||
'Undocked',
|
||||
@@ -1396,7 +1555,7 @@ class AppWindow(object):
|
||||
config.set('cmdrs', config.get_list('cmdrs', default=[]) + [monitor.cmdr])
|
||||
self.login()
|
||||
|
||||
if monitor.mode == 'CQC' and entry['event']:
|
||||
if monitor.cmdr and monitor.mode == 'CQC' and entry['event']:
|
||||
err = plug.notify_journal_entry_cqc(monitor.cmdr, monitor.is_beta, entry, monitor.state)
|
||||
if err:
|
||||
self.status['text'] = err
|
||||
@@ -1410,11 +1569,13 @@ class AppWindow(object):
|
||||
return # Startup
|
||||
|
||||
if entry['event'] in ['StartUp', 'LoadGame'] and monitor.started:
|
||||
logger.info('Startup or LoadGame event')
|
||||
logger.info('StartUp or LoadGame event')
|
||||
|
||||
# Disable WinSparkle automatic update checks, IFF configured to do so when in-game
|
||||
if config.get_int('disable_autoappupdatecheckingame') and 1:
|
||||
self.updater.set_automatic_updates_check(False)
|
||||
if self.updater is not None:
|
||||
self.updater.set_automatic_updates_check(False)
|
||||
|
||||
logger.info('Monitor: Disable WinSparkle automatic update checks')
|
||||
|
||||
# Can't start dashboard monitoring
|
||||
@@ -1426,16 +1587,20 @@ class AppWindow(object):
|
||||
and config.get_int('output') & config.OUT_SHIP:
|
||||
monitor.export_ship()
|
||||
|
||||
err = plug.notify_journal_entry(monitor.cmdr,
|
||||
monitor.is_beta,
|
||||
monitor.system,
|
||||
monitor.station,
|
||||
entry,
|
||||
monitor.state)
|
||||
if err:
|
||||
self.status['text'] = err
|
||||
if not config.get_int('hotkey_mute'):
|
||||
hotkeymgr.play_bad()
|
||||
if monitor.cmdr:
|
||||
err = plug.notify_journal_entry(
|
||||
monitor.cmdr,
|
||||
monitor.is_beta,
|
||||
monitor.state['SystemName'],
|
||||
monitor.state['StationName'],
|
||||
entry,
|
||||
monitor.state
|
||||
)
|
||||
|
||||
if err:
|
||||
self.status['text'] = err
|
||||
if not config.get_int('hotkey_mute'):
|
||||
hotkeymgr.play_bad()
|
||||
|
||||
auto_update = False
|
||||
# Only if auth callback is not pending
|
||||
@@ -1443,7 +1608,7 @@ class AppWindow(object):
|
||||
# Only if configured to do so
|
||||
if (not config.get_int('output') & config.OUT_MKT_MANUAL
|
||||
and config.get_int('output') & config.OUT_STATION_ANY):
|
||||
if entry['event'] in ('StartUp', 'Location', 'Docked') and monitor.station:
|
||||
if entry['event'] in ('StartUp', 'Location', 'Docked') and monitor.state['StationName']:
|
||||
# TODO: Can you log out in a docked Taxi and then back in to
|
||||
# the taxi, so 'Location' should be covered here too ?
|
||||
if entry['event'] == 'Docked' and entry.get('Taxi'):
|
||||
@@ -1459,13 +1624,25 @@ class AppWindow(object):
|
||||
elif entry['event'] == 'Disembark' and entry.get('Taxi') and entry.get('OnStation'):
|
||||
auto_update = True
|
||||
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
|
||||
if auto_update:
|
||||
self.w.after(int(SERVER_RETRY * 1000), self.capi_request_data)
|
||||
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
||||
if not should_return:
|
||||
self.w.after(int(SERVER_RETRY * 1000), self.capi_request_data)
|
||||
|
||||
if entry['event'] in ('CarrierBuy', 'CarrierStats') and config.get_bool('capi_fleetcarrier'):
|
||||
should_return, new_data = killswitch.check_killswitch('capi.request.fleetcarrier', {})
|
||||
if not should_return:
|
||||
self.w.after(int(SERVER_RETRY * 1000), self.capi_request_fleetcarrier_data)
|
||||
|
||||
if entry['event'] == 'ShutDown':
|
||||
# Enable WinSparkle automatic update checks
|
||||
# NB: Do this blindly, in case option got changed whilst in-game
|
||||
self.updater.set_automatic_updates_check(True)
|
||||
if self.updater is not None:
|
||||
self.updater.set_automatic_updates_check(True)
|
||||
|
||||
logger.info('Monitor: Enable WinSparkle automatic update checks')
|
||||
|
||||
def auth(self, event=None) -> None:
|
||||
@@ -1508,21 +1685,23 @@ class AppWindow(object):
|
||||
|
||||
entry = dashboard.status
|
||||
# Currently we don't do anything with these events
|
||||
err = plug.notify_dashboard_entry(monitor.cmdr, monitor.is_beta, entry)
|
||||
if err:
|
||||
self.status['text'] = err
|
||||
if not config.get_int('hotkey_mute'):
|
||||
hotkeymgr.play_bad()
|
||||
if monitor.cmdr:
|
||||
err = plug.notify_dashboard_entry(monitor.cmdr, monitor.is_beta, entry)
|
||||
|
||||
if err:
|
||||
self.status['text'] = err
|
||||
if not config.get_int('hotkey_mute'):
|
||||
hotkeymgr.play_bad()
|
||||
|
||||
def plugin_error(self, event=None) -> None:
|
||||
"""Display asynchronous error from plugin."""
|
||||
if plug.last_error.get('msg'):
|
||||
self.status['text'] = plug.last_error['msg']
|
||||
if plug.last_error.msg:
|
||||
self.status['text'] = plug.last_error.msg
|
||||
self.w.update_idletasks()
|
||||
if not config.get_int('hotkey_mute'):
|
||||
hotkeymgr.play_bad()
|
||||
|
||||
def shipyard_url(self, shipname: str) -> str:
|
||||
def shipyard_url(self, shipname: str) -> str | None:
|
||||
"""Despatch a ship URL to the configured handler."""
|
||||
if not (loadout := monitor.ship()):
|
||||
logger.warning('No ship loadout, aborting.')
|
||||
@@ -1549,13 +1728,18 @@ class AppWindow(object):
|
||||
|
||||
return f'file://localhost/{file_name}'
|
||||
|
||||
def system_url(self, system: str) -> str:
|
||||
def system_url(self, system: str) -> str | None:
|
||||
"""Despatch a system URL to the configured handler."""
|
||||
return plug.invoke(config.get_str('system_provider'), 'EDSM', 'system_url', monitor.system)
|
||||
return plug.invoke(
|
||||
config.get_str('system_provider'), 'EDSM', 'system_url', monitor.state['SystemName']
|
||||
)
|
||||
|
||||
def station_url(self, station: str) -> str:
|
||||
def station_url(self, station: str) -> str | None:
|
||||
"""Despatch a station URL to the configured handler."""
|
||||
return plug.invoke(config.get_str('station_provider'), 'eddb', 'station_url', monitor.system, monitor.station)
|
||||
return plug.invoke(
|
||||
config.get_str('station_provider'), 'eddb', 'station_url',
|
||||
monitor.state['SystemName'], monitor.state['StationName']
|
||||
)
|
||||
|
||||
def cooldown(self) -> None:
|
||||
"""Display and update the cooldown timer for 'Update' button."""
|
||||
@@ -1569,28 +1753,43 @@ class AppWindow(object):
|
||||
|
||||
else:
|
||||
self.button['text'] = self.theme_button['text'] = _('Update') # LANG: Update button in main window
|
||||
self.button['state'] = self.theme_button['state'] = (monitor.cmdr and
|
||||
monitor.mode and
|
||||
monitor.mode != 'CQC' and
|
||||
not monitor.state['Captain'] and
|
||||
monitor.system and
|
||||
tk.NORMAL or tk.DISABLED)
|
||||
self.button['state'] = self.theme_button['state'] = (
|
||||
monitor.cmdr and
|
||||
monitor.mode and
|
||||
monitor.mode != 'CQC' and
|
||||
not monitor.state['Captain'] and
|
||||
monitor.state['SystemName'] and
|
||||
tk.NORMAL or tk.DISABLED
|
||||
)
|
||||
|
||||
def ontop_changed(self, event=None) -> None:
|
||||
"""Set main window 'on top' state as appropriate."""
|
||||
config.set('always_ontop', self.always_ontop.get())
|
||||
self.w.wm_attributes('-topmost', self.always_ontop.get())
|
||||
if sys.platform == 'win32':
|
||||
def ontop_changed(self, event=None) -> None:
|
||||
"""Set main window 'on top' state as appropriate."""
|
||||
config.set('always_ontop', self.always_ontop.get())
|
||||
self.w.wm_attributes('-topmost', self.always_ontop.get())
|
||||
|
||||
def copy(self, event=None) -> None:
|
||||
"""Copy system, and possible station, name to clipboard."""
|
||||
if monitor.system:
|
||||
if monitor.state['SystemName']:
|
||||
self.w.clipboard_clear()
|
||||
self.w.clipboard_append(monitor.station and f'{monitor.system},{monitor.station}' or monitor.system)
|
||||
self.w.clipboard_append(
|
||||
f"{monitor.state['SystemName']},{monitor.state['StationName']}" if monitor.state['StationName']
|
||||
else monitor.state['SystemName']
|
||||
)
|
||||
|
||||
def help_general(self, event=None) -> None:
|
||||
"""Open Wiki Help page in browser."""
|
||||
webbrowser.open('https://github.com/EDCD/EDMarketConnector/wiki')
|
||||
|
||||
def help_troubleshooting(self, event=None) -> None:
|
||||
"""Open Wiki Privacy page in browser."""
|
||||
webbrowser.open("https://github.com/EDCD/EDMarketConnector/wiki/Troubleshooting")
|
||||
|
||||
def help_report_a_bug(self, event=None) -> None:
|
||||
"""Open Wiki Privacy page in browser."""
|
||||
webbrowser.open("https://github.com/EDCD/EDMarketConnector/issues/new?assignees=&labels=bug%2C+unconfirmed"
|
||||
"&template=bug_report.md&title=")
|
||||
|
||||
def help_privacy(self, event=None) -> None:
|
||||
"""Open Wiki Privacy page in browser."""
|
||||
webbrowser.open('https://github.com/EDCD/EDMarketConnector/wiki/Privacy-Policy')
|
||||
@@ -1630,7 +1829,7 @@ class AppWindow(object):
|
||||
|
||||
self.resizable(tk.FALSE, tk.FALSE)
|
||||
|
||||
frame = ttk.Frame(self)
|
||||
frame = tk.Frame(self)
|
||||
frame.grid(sticky=tk.NSEW)
|
||||
|
||||
row = 1
|
||||
@@ -1643,7 +1842,7 @@ class AppWindow(object):
|
||||
|
||||
############################################################
|
||||
# version <link to changelog>
|
||||
ttk.Label(frame).grid(row=row, column=0) # spacer
|
||||
tk.Label(frame).grid(row=row, column=0) # spacer
|
||||
row += 1
|
||||
self.appversion_label = tk.Label(frame, text=appversion())
|
||||
self.appversion_label.grid(row=row, column=0, sticky=tk.E)
|
||||
@@ -1711,7 +1910,7 @@ class AppWindow(object):
|
||||
defaultextension=default_extension,
|
||||
filetypes=[('JSON', '.json'), ('All Files', '*')],
|
||||
initialdir=config.get_str('outdir'),
|
||||
initialfile=f'{monitor.system}{monitor.station}.{timestamp}'
|
||||
initialfile=f"{monitor.state['SystemName']}.{monitor.state['StationName']}.{timestamp}"
|
||||
)
|
||||
if not f:
|
||||
return
|
||||
@@ -1719,13 +1918,14 @@ class AppWindow(object):
|
||||
with open(f, 'wb') as h:
|
||||
h.write(str(companion.session.capi_raw_data).encode(encoding='utf-8'))
|
||||
|
||||
def exit_tray(self, systray: 'SysTrayIcon') -> None:
|
||||
"""Tray icon is shutting down."""
|
||||
exit_thread = threading.Thread(
|
||||
target=self.onexit,
|
||||
daemon=True,
|
||||
)
|
||||
exit_thread.start()
|
||||
if sys.platform == 'win32':
|
||||
def exit_tray(self, systray: 'SysTrayIcon') -> None:
|
||||
"""Tray icon is shutting down."""
|
||||
exit_thread = threading.Thread(
|
||||
target=self.onexit,
|
||||
daemon=True,
|
||||
)
|
||||
exit_thread.start()
|
||||
|
||||
def onexit(self, event=None) -> None:
|
||||
"""Application shutdown procedure."""
|
||||
@@ -1751,7 +1951,8 @@ class AppWindow(object):
|
||||
|
||||
# First so it doesn't interrupt us
|
||||
logger.info('Closing update checker...')
|
||||
self.updater.close()
|
||||
if self.updater is not None:
|
||||
self.updater.close()
|
||||
|
||||
# Earlier than anything else so plugin code can't interfere *and* it
|
||||
# won't still be running in a manner that might rely on something
|
||||
@@ -1859,10 +2060,13 @@ Locale LC_TIME: {locale.getlocale(locale.LC_TIME)}'''
|
||||
)
|
||||
|
||||
|
||||
def setup_killswitches():
|
||||
def setup_killswitches(filename: Optional[str]):
|
||||
"""Download and setup the main killswitch list."""
|
||||
logger.debug('fetching killswitches...')
|
||||
killswitch.setup_main_list()
|
||||
if filename is not None:
|
||||
filename = "file:" + filename
|
||||
|
||||
killswitch.setup_main_list(filename)
|
||||
|
||||
|
||||
def show_killswitch_poppup(root=None):
|
||||
@@ -1891,17 +2095,15 @@ def show_killswitch_poppup(root=None):
|
||||
for version in kills:
|
||||
tk.Label(frame, text=f'Version: {version.version}').grid(row=idx, sticky=tk.W)
|
||||
idx += 1
|
||||
for id, reason in version.kills.items():
|
||||
for id, kill in version.kills.items():
|
||||
tk.Label(frame, text=id).grid(column=0, row=idx, sticky=tk.W, padx=(10, 0))
|
||||
tk.Label(frame, text=reason).grid(column=1, row=idx, sticky=tk.E, padx=(0, 10))
|
||||
tk.Label(frame, text=kill.reason).grid(column=1, row=idx, sticky=tk.E, padx=(0, 10))
|
||||
idx += 1
|
||||
idx += 1
|
||||
|
||||
ok_button = tk.Button(frame, text="ok", command=tl.destroy)
|
||||
ok_button = tk.Button(frame, text="Ok", command=tl.destroy)
|
||||
ok_button.grid(columnspan=2, sticky=tk.EW)
|
||||
|
||||
theme.apply(tl)
|
||||
|
||||
|
||||
# Run the app
|
||||
if __name__ == "__main__": # noqa: C901
|
||||
@@ -2026,7 +2228,8 @@ sys.path: {sys.path}'''
|
||||
|
||||
Translations.install(config.get_str('language')) # Can generate errors so wait til log set up
|
||||
|
||||
setup_killswitches()
|
||||
setup_killswitches(args.killswitches_file)
|
||||
|
||||
root = tk.Tk(className=appname.lower())
|
||||
if sys.platform != 'win32' and ((f := config.get_str('font')) is not None or f != ''):
|
||||
size = config.get_int('font_size', default=-1)
|
||||
@@ -2045,10 +2248,13 @@ sys.path: {sys.path}'''
|
||||
if not ui_scale:
|
||||
ui_scale = 100
|
||||
config.set('ui_scale', ui_scale)
|
||||
|
||||
theme.default_ui_scale = root.tk.call('tk', 'scaling')
|
||||
logger.trace_if('tk', f'Default tk scaling = {theme.default_ui_scale}')
|
||||
theme.startup_ui_scale = ui_scale
|
||||
root.tk.call('tk', 'scaling', theme.default_ui_scale * float(ui_scale) / 100.0)
|
||||
if theme.default_ui_scale is not None:
|
||||
root.tk.call('tk', 'scaling', theme.default_ui_scale * float(ui_scale) / 100.0)
|
||||
|
||||
app = AppWindow(root)
|
||||
|
||||
def messagebox_not_py3():
|
||||
|
||||
+1
-1
Submodule FDevIDs updated: 3fd5d202e5...2aaf3cb023.
+361
-361
@@ -1,623 +1,623 @@
|
||||
/* Language name */
|
||||
"!Language" = "Čeština";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Odesílání dat do EDDN...";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Chyba: Nelze se připojit k EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Odeslat data o stanici do Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:673; load.py:682; eddn.py:1133; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Odeslat sken a data o systému do Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:683; load.py:692; eddn.py:1144; */
|
||||
"Delay sending until docked" = "Pozdržet odeslání po zadokování";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:197; load.py:197; edsm.py:237; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Odesílat letový log a status CMDRa do EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "Přihlašovací údaje Elite Dangerous Star Map";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "Jméno CMDRa";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "API klíč";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Žádná";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Chyba: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Chyba: Nelze se připojit k EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:215; load.py:215; inara.py:222; */
|
||||
"Send flight log and Cmdr status to Inara" = "Odesílat letový log a status CMDRa na Inaru";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:225; load.py:225; inara.py:234; */
|
||||
"Inara credentials" = "Přihlašovací údaje k Inaře";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1316; inara.py:1328; load.py:1319; load.py:1331; inara.py:1587; inara.py:1600; */
|
||||
"Error: Inara {MSG}" = "Chyba: Inara {MSG}";
|
||||
|
||||
/* coriolis.py: 'Auto' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - auto; In files: load.py:51; load.py:51; load.py:88; load.py:104; load.py:110; coriolis.py:52; coriolis.py:55; coriolis.py:101; coriolis.py:117; coriolis.py:123; */
|
||||
"Auto" = "Auto";
|
||||
|
||||
/* coriolis.py: 'Normal' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - normal; In files: load.py:51; load.py:88; load.py:102; coriolis.py:53; coriolis.py:99; coriolis.py:115; */
|
||||
"Normal" = "Normal";
|
||||
|
||||
/* coriolis.py: 'Beta' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - beta; In files: load.py:51; load.py:88; load.py:103; coriolis.py:54; coriolis.py:100; coriolis.py:116; */
|
||||
"Beta" = "Beta";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Help/hint for changing coriolis URLs; In files: load.py:64:66; coriolis.py:69:71; */
|
||||
"Set the URL to use with coriolis.io ship loadouts. Note that this MUST end with '/import?data='" = "Nastavte si URL pro konfiguraci lodi na coriolis.io. Adresa MUSÍ končit '/import?data='";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */
|
||||
"Normal URL" = "Normal URL";
|
||||
|
||||
/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */
|
||||
"Reset" = "Reset";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */
|
||||
"Beta URL" = "Beta URL";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */
|
||||
"Invalid Coriolis override mode!" = "Neplatný režim přepisu Coriolis!";
|
||||
|
||||
/* eddb.py: Journal Processing disabled due to an active killswitch; In files: load.py:99; eddb.py:100; */
|
||||
"EDDB Journal processing disabled. See Log." = "Zpracování EDDB deníku je deaktivováno. Zkontrolujte log.";
|
||||
|
||||
/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */
|
||||
"EDDN journal handler disabled. See Log." = "Obsluha EDDN deníku je deaktivována. Zkontrolujte log.";
|
||||
|
||||
/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */
|
||||
"EDSM Handler disabled. See Log." = "Obsluha EDSM deaktivována. Zkontrolujte log.";
|
||||
|
||||
/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */
|
||||
"Inara disabled. See Log." = "Inara deaktivována. Zkontrolujte log.";
|
||||
|
||||
/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: test_ast_stuff.py:2; EDMarketConnector.py:1047; */
|
||||
"CAPI: No commander data returned" = "CAPI: Nebyla vrácena žádná data komandéra";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */
|
||||
"Override Beta/Normal Selection" = "Přepsat volbu Beta/Normal";
|
||||
|
||||
/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */
|
||||
"Journal directory already locked" = "Adresář deníku je již uzamčen";
|
||||
|
||||
/* journal_lock.py: Text for when newly selected Journal directory is already locked; In files: journal_lock.py:223:224; */
|
||||
"The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this." = "Nové umístění adresáře deníku je již uzamčeno. {CR} Můžete zkusit tento problém vyřešit a Opakovat, nebo Ignorovat.";
|
||||
|
||||
/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */
|
||||
"Retry" = "Opakovat";
|
||||
|
||||
/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */
|
||||
"Ignore" = "Ignorovat";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Kopírovat";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Aktualizovat";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Vždy navrchu";
|
||||
|
||||
/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */
|
||||
"Unknown" = "Neznámý";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Role";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Loď";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */
|
||||
"Suit" = "Oblek";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "Systém";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Stanice";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "Soubor";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Upravit";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "Zobrazit";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Okno";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Nápověda";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "O {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Zkontrolovat aktualizace...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Uložit surová data...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Zásady ochrany osobních údajů";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Poznámky k verzi";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Nastavení";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Ukončit";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Dokumentace";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Přihlašování...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "Přihlášení bylo úspěšné";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = "Nejste zadokováni ve stanici!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "Stanice nenabízí žádné služby!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "Stanice nemá obchod!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Načítání dat...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Kdo jste?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Kde zrovna jste?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "S jakou lodí létáte?";
|
||||
|
||||
/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */
|
||||
"Frontier CAPI server error" = "Chyba Frontier CAPI serveru";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Poslední aktualizace %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */
|
||||
"Fighter" = "Fighter";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */
|
||||
"Gunner" = "Gunner";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */
|
||||
"Helm" = "Helm";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "Počkej ještě {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1693; */
|
||||
"Shutting down..." = "Vypínání...";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2008:2014; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Jeden nebo více aktivních pluginů ještě stále nepodporuje Python 3.x. Podívejte se na jejich seznam v záložce '{PLUGINS}' v '{FILE}' > '{SETTINGS}'. Zkontrolujte si jestli není dostupná novější verze pluginu, pokud ne, tak kontaktujte vývojáře pluginu o tom, že musí upravit jejich plugin pro Python 3.x.\n\nPlugin můžete vypnout přidáním '{DISABLED}' na konec názvu jeho složky.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */
|
||||
"Plugins" = "Pluginy";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2029; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Pluginy, které nepodporují Python 3.x";
|
||||
|
||||
/* companion.py: Frontier CAPI didn't respond; In files: companion.py:218; */
|
||||
/* companion.py: Frontier CAPI didn't respond; In files: companion.py:226; */
|
||||
"Error: Frontier CAPI didn't respond" = "Chyba: Frontier CAPI neodpovídá";
|
||||
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:237; */
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:245; */
|
||||
"Error: Frontier server is lagging" = "Chyba: Server Frontieru laguje";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Chyba: Chybné přihlašovací údaje";
|
||||
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:288; */
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:296; */
|
||||
"Error: Wrong Cmdr" = "Chyba: Nesprávný CMDR";
|
||||
|
||||
/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:414; companion.py:499; */
|
||||
/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:432; companion.py:517; */
|
||||
"Error" = "Chyba";
|
||||
|
||||
/* companion.py: Frontier auth, no 'usr' section in returned data; companion.py: Frontier auth, no 'customer_id' in 'usr' section in returned data; In files: companion.py:457; companion.py:462; */
|
||||
/* companion.py: Frontier auth, no 'usr' section in returned data; companion.py: Frontier auth, no 'customer_id' in 'usr' section in returned data; In files: companion.py:475; companion.py:480; */
|
||||
"Error: Couldn't check token customer_id" = "Chyba: Nejde ověřit token customer_id";
|
||||
|
||||
/* companion.py: Frontier auth customer_id doesn't match game session FID; In files: companion.py:468; */
|
||||
/* companion.py: Frontier auth customer_id doesn't match game session FID; In files: companion.py:486; */
|
||||
"Error: customer_id doesn't match!" = "Chyba: customer_id nesouhlasí!";
|
||||
|
||||
/* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:490; */
|
||||
/* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:508; */
|
||||
"Error: unable to get token" = "Chyba: nepovedlo se získat token";
|
||||
|
||||
/* companion.py: Frontier CAPI data retrieval failed; In files: companion.py:809; */
|
||||
/* companion.py: Frontier CAPI data retrieval failed; In files: companion.py:856; */
|
||||
"Frontier CAPI query failure" = "Dotaz na Frontier CAPI selhal";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Aktualizovat";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Vždy navrchu";
|
||||
|
||||
/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */
|
||||
"Unknown" = "Neznámý";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Role";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Loď";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */
|
||||
"Suit" = "Oblek";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "Systém";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Stanice";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "Soubor";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Upravit";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "Zobrazit";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Okno";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Nápověda";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "O {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Zkontrolovat aktualizace...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Uložit surová data...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Dokumentace";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Zásady ochrany osobních údajů";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Poznámky k verzi";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Nastavení";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Ukončit";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Kopírovat";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Přihlašování...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "Přihlášení bylo úspěšné";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = "Nejste zadokováni ve stanici!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "Stanice nenabízí žádné služby!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "Stanice nemá obchod!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Načítání dat...";
|
||||
|
||||
/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */
|
||||
"CAPI: No commander data returned" = "CAPI: Nebyla vrácena žádná data komandéra";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Kdo jste?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Kde zrovna jste?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "S jakou lodí létáte?";
|
||||
|
||||
/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */
|
||||
"Frontier CAPI server error" = "Chyba Frontier CAPI serveru";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Poslední aktualizace %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */
|
||||
"Fighter" = "Fighter";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */
|
||||
"Gunner" = "Gunner";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */
|
||||
"Helm" = "Helm";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "Počkej ještě {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1936; */
|
||||
"Shutting down..." = "Vypínání...";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2253:2259; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Jeden nebo více aktivních pluginů ještě stále nepodporuje Python 3.x. Podívejte se na jejich seznam v záložce '{PLUGINS}' v '{FILE}' > '{SETTINGS}'. Zkontrolujte si jestli není dostupná novější verze pluginu, pokud ne, tak kontaktujte vývojáře pluginu o tom, že musí upravit jejich plugin pro Python 3.x.\n\nPlugin můžete vypnout přidáním '{DISABLED}' na konec názvu jeho složky.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */
|
||||
"Plugins" = "Pluginy";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2274; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Pluginy, které nepodporují Python 3.x";
|
||||
|
||||
/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:208; */
|
||||
"Journal directory already locked" = "Adresář deníku je již uzamčen";
|
||||
|
||||
/* journal_lock.py: Text for when newly selected Journal directory is already locked; In files: journal_lock.py:225:226; */
|
||||
"The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this." = "Nové umístění adresáře deníku je již uzamčeno. {CR} Můžete zkusit tento problém vyřešit a Opakovat, nebo Ignorovat.";
|
||||
|
||||
/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */
|
||||
"Retry" = "Opakovat";
|
||||
|
||||
/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */
|
||||
"Ignore" = "Ignorovat";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Výchozí";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* coriolis.py: 'Auto' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - auto; In files: coriolis.py:74; coriolis.py:77; coriolis.py:123; coriolis.py:139; coriolis.py:145; */
|
||||
"Auto" = "Auto";
|
||||
|
||||
/* coriolis.py: 'Normal' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - normal; In files: coriolis.py:75; coriolis.py:121; coriolis.py:137; */
|
||||
"Normal" = "Normal";
|
||||
|
||||
/* coriolis.py: 'Beta' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - beta; In files: coriolis.py:76; coriolis.py:122; coriolis.py:138; */
|
||||
"Beta" = "Beta";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Help/hint for changing coriolis URLs; In files: coriolis.py:91:93; */
|
||||
"Set the URL to use with coriolis.io ship loadouts. Note that this MUST end with '/import?data='" = "Nastavte si URL pro konfiguraci lodi na coriolis.io. Adresa MUSÍ končit '/import?data='";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */
|
||||
"Normal URL" = "Normal URL";
|
||||
|
||||
/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */
|
||||
"Reset" = "Reset";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: coriolis.py:106; */
|
||||
"Beta URL" = "Beta URL";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:116; */
|
||||
"Override Beta/Normal Selection" = "Přepsat volbu Beta/Normal";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */
|
||||
"Invalid Coriolis override mode!" = "Neplatný režim přepisu Coriolis!";
|
||||
|
||||
/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */
|
||||
"EDDB Journal processing disabled. See Log." = "Zpracování EDDB deníku je deaktivováno. Zkontrolujte log.";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Chyba: Nelze se připojit k EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Odeslat data o stanici do Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:2052; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Odeslat sken a data o systému do Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:2063; */
|
||||
"Delay sending until docked" = "Pozdržet odeslání po zadokování";
|
||||
|
||||
/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */
|
||||
"EDDN journal handler disabled. See Log." = "Obsluha EDDN deníku je deaktivována. Zkontrolujte log.";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Odesílání dat do EDDN...";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Odesílat letový log a status CMDRa do EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "Přihlašovací údaje Elite Dangerous Star Map";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "Jméno CMDRa";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "API klíč";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Žádná";
|
||||
|
||||
/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */
|
||||
"EDSM Handler disabled. See Log." = "Obsluha EDSM deaktivována. Zkontrolujte log.";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Chyba: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Chyba: Nelze se připojit k EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */
|
||||
"Send flight log and Cmdr status to Inara" = "Odesílat letový log a status CMDRa na Inaru";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */
|
||||
"Inara credentials" = "Přihlašovací údaje k Inaře";
|
||||
|
||||
/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */
|
||||
"Inara disabled. See Log." = "Inara deaktivována. Zkontrolujte log.";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1650; inara.py:1663; */
|
||||
"Error: Inara {MSG}" = "Chyba: Inara {MSG}";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Nastavení";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Vyberte, která data chcete ukládat";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Obchodní data ve formátu CSV";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Obchodní data ve formátu Trade Dangerous";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Konfigurace lodi";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:383; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:370; */
|
||||
"Automatically update on docking" = "Automaticky aktualizovat při zadokování";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Cesta k souboru";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Změnit...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Procházet...";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Výstup";
|
||||
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:444; prefs.py:459; */
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:431; prefs.py:446; */
|
||||
"E:D journal file location" = "E:D umístění souboru deníku";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Klávesová zkratka";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Klávesová zkratka";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "Restartujte {APP} pro aktivaci klávesových zkratek";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} vyžaduje oprávnění pro použití klávesových zkratek";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Otevřít Předvolby systému";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Pouze pokud je Elite: Dangerous aktivní";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Přehrát zvuk";
|
||||
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:557; */
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:564; */
|
||||
"Disable Automatic Application Updates Check when in-game" = "Vypnout automatickou kontrolu aktualizací aplikace, pokud jste ve hře";
|
||||
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:570; */
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:577; */
|
||||
"Preferred websites" = "Preferované stránky";
|
||||
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:581; */
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:588; */
|
||||
"Shipyard" = "Shipyard";
|
||||
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:593; */
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:600; */
|
||||
"Use alternate URL method" = "Použít alternativní URL metodu";
|
||||
|
||||
/* prefs.py: Configuration - Label for selection of Log Level; In files: prefs.py:646; */
|
||||
/* prefs.py: Configuration - Label for selection of Log Level; In files: prefs.py:653; */
|
||||
"Log Level" = "Míra logování";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Nastavení";
|
||||
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */
|
||||
"Privacy" = "Soukromí";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:709; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:716; */
|
||||
"Normal text" = "Normální text";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:711; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:718; */
|
||||
"Highlighted text" = "Zvýrazněný text";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Jazyk";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Schéma";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Tmavé";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Průhledné";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of UI scaling; In files: prefs.py:794; */
|
||||
/* prefs.py: Appearance - Label for selection of UI scaling; In files: prefs.py:802; */
|
||||
"UI Scale Percentage" = "Procenta UI škálování";
|
||||
|
||||
/* prefs.py: Appearance - Help/hint text for UI scaling selection; In files: prefs.py:815; */
|
||||
/* prefs.py: Appearance - Help/hint text for UI scaling selection; In files: prefs.py:823; */
|
||||
"100 means Default{CR}Restart Required for{CR}changes to take effect!" = "100 je výchozí hodnota{CR}je potřeba restartovat,{CR}aby se změna projevila!";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of main window transparency; In files: prefs.py:825; */
|
||||
/* prefs.py: Appearance - Label for selection of main window transparency; In files: prefs.py:833; */
|
||||
"Main window transparency" = "Průhlednost hlavního okna";
|
||||
|
||||
/* prefs.py: Appearance - Help/hint text for Main window transparency selection; In files: prefs.py:845:848; */
|
||||
/* prefs.py: Appearance - Help/hint text for Main window transparency selection; In files: prefs.py:853:856; */
|
||||
"100 means fully opaque.{CR}Window is updated in real time" = "100 znamená plně neprůhledné.{CR}Okno se aktualizuje v reálném čase";
|
||||
|
||||
/* prefs.py: Appearance option for Windows "minimize to system tray"; In files: prefs.py:877; */
|
||||
/* prefs.py: Appearance option for Windows "minimize to system tray"; In files: prefs.py:885; */
|
||||
"Minimize to system tray" = "Minimalizovat do lišty";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Vzhled";
|
||||
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:900; */
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */
|
||||
"Plugins folder" = "Složka pluginů";
|
||||
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:907; */
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */
|
||||
"Open" = "Otevřít";
|
||||
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:915; */
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:923; */
|
||||
"Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name" = "Tip: Plugin můžete vypnout přidáním{CR}'{EXT}' do názvu jeho složky";
|
||||
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:926; */
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:934; */
|
||||
"Enabled Plugins" = "Zapnuté pluginy";
|
||||
|
||||
/* prefs.py: Plugins - Label for list of 'enabled' plugins that don't work with Python 3.x; In files: prefs.py:946; */
|
||||
/* prefs.py: Plugins - Label for list of 'enabled' plugins that don't work with Python 3.x; In files: prefs.py:954; */
|
||||
"Plugins Without Python 3.x Support:" = "Pluginy bez podpory Python 3.x:";
|
||||
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:954; */
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:962; */
|
||||
"Information on migrating plugins" = "Informace jak migrovat pluginy.";
|
||||
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:969; */
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:977; */
|
||||
"Disabled Plugins" = "Vypnuté pluginy";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Zůstatek";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Půjčka";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Elite";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Combat";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Trade";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Explorer";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "CQC";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Federation";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Empire";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Powerplay";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Mostly Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Novice";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Competent";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Expert";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Master";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Dangerous";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Deadly";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Mostly Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Peddler";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Dealer";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Merchant";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Broker";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Entrepreneur";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Tycoon";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Mostly Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Scout";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Surveyor";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Trailblazer";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Pathfinder";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Ranger";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Pioneer";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Mostly Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Amateur";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Semi Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Champion";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Hero";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Gladiator";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Recruit";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Cadet";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Midshipman";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Poddůstojník";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Chief Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Warrant Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Ensign";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "Lieutenant";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Lieutenant Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Post Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Post Captain";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "Rear Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Vice Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Admiral";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Outsider";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Serf";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Squire";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Knight";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Lord";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Baron";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Viscount";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Count";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Earl";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Marquis";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Duke";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Prince";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "King";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Rating 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Rating 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Rating 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Rating 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Rating 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Cena";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Lodě";
|
||||
+447
-417
File diff suppressed because it is too large.
Load diff
+453
-432
File diff suppressed because it is too large.
Load diff
+374
-374
File diff suppressed because it is too large.
Load diff
+334
-334
@@ -1,596 +1,596 @@
|
||||
/* Language name */
|
||||
"!Language" = "Suomi";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Lähetetään tietoja EDDN:ään...";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Virhe: ei saatu yhteyttä EDDN:ään";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Lähetä asematiedot Elite Dangerous Data Network -palveluun";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:673; load.py:682; eddn.py:1133; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Lähetä järjestelmä- ja skannaustiedot Elite Dangerous Data Network -palveluun";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:683; load.py:692; eddn.py:1144; */
|
||||
"Delay sending until docked" = "Lähetä tiedot vasta telakoitumisen jälkeen";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:197; load.py:197; edsm.py:237; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Lähetä lentoloki ja komentajatiedot EDSM:ään";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous Star Map -kirjautuminen";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "Komentajanimi";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "API avain";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Ei määritelty";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Virhe: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Virhe: ei saatu yhteyttä EDSM:ään";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:215; load.py:215; inara.py:222; */
|
||||
"Send flight log and Cmdr status to Inara" = "Lähetä lentoloki ja komentajatiedot Inaraan";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:225; load.py:225; inara.py:234; */
|
||||
"Inara credentials" = "Inaran kirjautuminen";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1316; inara.py:1328; load.py:1319; load.py:1331; inara.py:1587; inara.py:1600; */
|
||||
"Error: Inara {MSG}" = "Inaran virhe: {MSG}";
|
||||
|
||||
/* eddb.py: Journal Processing disabled due to an active killswitch; In files: load.py:99; eddb.py:100; */
|
||||
"EDDB Journal processing disabled. See Log." = "EDDB lokikirjan käsittely ei käytössä. Katso lokitiedot.";
|
||||
|
||||
/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */
|
||||
"EDDN journal handler disabled. See Log." = "EDDB lokikirjan käsittelijä ei käytössä. Katso lokitiedot.";
|
||||
|
||||
/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */
|
||||
"EDSM Handler disabled. See Log." = "ESDM käsittelijä ei käytössä. Katso lokitiedot.";
|
||||
|
||||
/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */
|
||||
"Inara disabled. See Log." = "Inara ei käytössä. Katso lokitiedot.";
|
||||
|
||||
/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: test_ast_stuff.py:2; EDMarketConnector.py:1047; */
|
||||
"CAPI: No commander data returned" = "CAPI: tietoja ei löytynyt";
|
||||
|
||||
/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */
|
||||
"Journal directory already locked" = "Journal -hakemisto on jo lukittu";
|
||||
|
||||
/* journal_lock.py: Text for when newly selected Journal directory is already locked; In files: journal_lock.py:223:224; */
|
||||
"The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this." = "Uusi Journal -hakemisto on jo lukittu.{CR}Voit joko yrittää ratkaista tämän ja yrittää uudelleen, tai jättää asian huomiotta.";
|
||||
|
||||
/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */
|
||||
"Retry" = "Yritä uudelleen";
|
||||
|
||||
/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */
|
||||
"Ignore" = "Älä huomioi";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Kopioi";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Päivitä";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Aina päällimmäisenä";
|
||||
|
||||
/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */
|
||||
"Unknown" = "Tuntematon";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Rooli";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Alus";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */
|
||||
"Suit" = "Asuste";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "Järjestelmä";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Asema";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "Tiedosto";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Muokkaa";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "Näytä";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Ikkuna";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Apua";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "Ohjelmasta {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Tarkista päivitykset...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Tallenna raakadata...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "Tila";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Tietosuojakäytäntö";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Julkaisutiedot";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Valinnat";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Lopeta";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Dokumentaatio";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Kirjaudutaan...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "Todennus onnistui";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = "Et ole telakoituneena asemalle!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "Asemalla ei ole mitään!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "Asemalla ei ole kaupankäyntiä!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Noudetaan tietoja...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Kuka olet?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Missä olet?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "Mitä alusta lennät?!";
|
||||
|
||||
/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */
|
||||
"Frontier CAPI server error" = "Frontier CAPI palvelinvirhe.";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Päivitetty viimeksi %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */
|
||||
"Fighter" = "Hävittäjä";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */
|
||||
"Gunner" = "Aseiden käyttäjä";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */
|
||||
"Helm" = "Pilotti";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "Jäähtymisaika {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1693; */
|
||||
"Shutting down..." = "Sulkeutuu...";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2008:2014; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Yksi tai useampi käyttämistäsi lisäosista ei sisällä vielä Pyhton 3.x -tukea. Tarkista tiedoston '{FILE}' > '{SETTINGS}' välilehti '{PLUGINS}' lisäosista, onko niistä uudempaa versiota saatavilla; muussa tapauksessa ota yhteyttä sen kehittäjään ja kerro, että sen lähdekoodi on päivitettävä Python 3.x -tasolle.\n\nVoit estää lisäosan toiminnan nimeämällä sen hakemiston siten, että se päättyy tekstiin '{DISABLED}'.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */
|
||||
"Plugins" = "Lisäosat";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2029; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Lisäosat ilman Python 3.x -tukea";
|
||||
|
||||
/* companion.py: Frontier CAPI didn't respond; In files: companion.py:218; */
|
||||
/* companion.py: Frontier CAPI didn't respond; In files: companion.py:226; */
|
||||
"Error: Frontier CAPI didn't respond" = "Virhe: Frontier CAPI ei vastaa.";
|
||||
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:237; */
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:245; */
|
||||
"Error: Frontier server is lagging" = "Virhe: Frontierin palvelin vastaa vanhoilla tiedoilla";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Virhe: kirjautuminen ei kelpaa";
|
||||
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:288; */
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:296; */
|
||||
"Error: Wrong Cmdr" = "Virhe: väärä komentaja";
|
||||
|
||||
/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:414; companion.py:499; */
|
||||
/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:432; companion.py:517; */
|
||||
"Error" = "Virhe";
|
||||
|
||||
/* companion.py: Frontier auth, no 'usr' section in returned data; companion.py: Frontier auth, no 'customer_id' in 'usr' section in returned data; In files: companion.py:457; companion.py:462; */
|
||||
/* companion.py: Frontier auth, no 'usr' section in returned data; companion.py: Frontier auth, no 'customer_id' in 'usr' section in returned data; In files: companion.py:475; companion.py:480; */
|
||||
"Error: Couldn't check token customer_id" = "Virhe: Ei kyetty tarkastamaan polettia customer_id";
|
||||
|
||||
/* companion.py: Frontier auth customer_id doesn't match game session FID; In files: companion.py:468; */
|
||||
/* companion.py: Frontier auth customer_id doesn't match game session FID; In files: companion.py:486; */
|
||||
"Error: customer_id doesn't match!" = "Virhe: customer_id ei löydy vastaavuutta!";
|
||||
|
||||
/* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:490; */
|
||||
/* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:508; */
|
||||
"Error: unable to get token" = "Virhe: ei kyetty saamaan polettia";
|
||||
|
||||
/* companion.py: Frontier CAPI data retrieval failed; In files: companion.py:809; */
|
||||
/* companion.py: Frontier CAPI data retrieval failed; In files: companion.py:856; */
|
||||
"Frontier CAPI query failure" = "Frontier CAPI kyselyvirhe.";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Päivitä";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Aina päällimmäisenä";
|
||||
|
||||
/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */
|
||||
"Unknown" = "Tuntematon";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Rooli";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Alus";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */
|
||||
"Suit" = "Asuste";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "Järjestelmä";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Asema";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "Tiedosto";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Muokkaa";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "Näytä";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Ikkuna";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Apua";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "Ohjelmasta {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Tarkista päivitykset...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Tallenna raakadata...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "Tila";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Dokumentaatio";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Tietosuojakäytäntö";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Julkaisutiedot";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Valinnat";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Lopeta";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Kopioi";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Kirjaudutaan...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "Todennus onnistui";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = "Et ole telakoituneena asemalle!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "Asemalla ei ole mitään!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "Asemalla ei ole kaupankäyntiä!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Noudetaan tietoja...";
|
||||
|
||||
/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */
|
||||
"CAPI: No commander data returned" = "CAPI: tietoja ei löytynyt";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Kuka olet?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Missä olet?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "Mitä alusta lennät?!";
|
||||
|
||||
/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */
|
||||
"Frontier CAPI server error" = "Frontier CAPI palvelinvirhe.";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Päivitetty viimeksi %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */
|
||||
"Fighter" = "Hävittäjä";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */
|
||||
"Gunner" = "Aseiden käyttäjä";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */
|
||||
"Helm" = "Pilotti";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "Jäähtymisaika {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1936; */
|
||||
"Shutting down..." = "Sulkeutuu...";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2253:2259; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Yksi tai useampi käyttämistäsi lisäosista ei sisällä vielä Pyhton 3.x -tukea. Tarkista tiedoston '{FILE}' > '{SETTINGS}' välilehti '{PLUGINS}' lisäosista, onko niistä uudempaa versiota saatavilla; muussa tapauksessa ota yhteyttä sen kehittäjään ja kerro, että sen lähdekoodi on päivitettävä Python 3.x -tasolle.\n\nVoit estää lisäosan toiminnan nimeämällä sen hakemiston siten, että se päättyy tekstiin '{DISABLED}'.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */
|
||||
"Plugins" = "Lisäosat";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2274; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Lisäosat ilman Python 3.x -tukea";
|
||||
|
||||
/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:208; */
|
||||
"Journal directory already locked" = "Journal -hakemisto on jo lukittu";
|
||||
|
||||
/* journal_lock.py: Text for when newly selected Journal directory is already locked; In files: journal_lock.py:225:226; */
|
||||
"The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this." = "Uusi Journal -hakemisto on jo lukittu.{CR}Voit joko yrittää ratkaista tämän ja yrittää uudelleen, tai jättää asian huomiotta.";
|
||||
|
||||
/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */
|
||||
"Retry" = "Yritä uudelleen";
|
||||
|
||||
/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */
|
||||
"Ignore" = "Älä huomioi";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Oletus";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */
|
||||
"EDDB Journal processing disabled. See Log." = "EDDB lokikirjan käsittely ei käytössä. Katso lokitiedot.";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Virhe: ei saatu yhteyttä EDDN:ään";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Lähetä asematiedot Elite Dangerous Data Network -palveluun";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:2052; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Lähetä järjestelmä- ja skannaustiedot Elite Dangerous Data Network -palveluun";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:2063; */
|
||||
"Delay sending until docked" = "Lähetä tiedot vasta telakoitumisen jälkeen";
|
||||
|
||||
/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */
|
||||
"EDDN journal handler disabled. See Log." = "EDDB lokikirjan käsittelijä ei käytössä. Katso lokitiedot.";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Lähetetään tietoja EDDN:ään...";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Lähetä lentoloki ja komentajatiedot EDSM:ään";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous Star Map -kirjautuminen";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "Komentajanimi";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "API avain";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Ei määritelty";
|
||||
|
||||
/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */
|
||||
"EDSM Handler disabled. See Log." = "ESDM käsittelijä ei käytössä. Katso lokitiedot.";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Virhe: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Virhe: ei saatu yhteyttä EDSM:ään";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */
|
||||
"Send flight log and Cmdr status to Inara" = "Lähetä lentoloki ja komentajatiedot Inaraan";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */
|
||||
"Inara credentials" = "Inaran kirjautuminen";
|
||||
|
||||
/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */
|
||||
"Inara disabled. See Log." = "Inara ei käytössä. Katso lokitiedot.";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1650; inara.py:1663; */
|
||||
"Error: Inara {MSG}" = "Inaran virhe: {MSG}";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Valinnat";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Valitse mitkä tiedot tallennetaan";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Markkinadata CSV -formaatissa";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Markkinadata Trade Dangerous -formaatissa";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Aluksen konfiguraatio";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:383; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:370; */
|
||||
"Automatically update on docking" = "Päivitä automaattisesti telakoituessa";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Tiedostosijainti";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Muuta...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Selaa...";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Tallennus";
|
||||
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:444; prefs.py:459; */
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:431; prefs.py:446; */
|
||||
"E:D journal file location" = "E:D lokikirjan tiedostosijainti";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Näppäimistöoikopolku";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Pikanäppäin";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "Käynnistä {APP} uudelleen käyttääksesi pikanäppäimiä";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} tarvitsee lupasi pikakuvakkeiden käyttämiseen";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Avaa järjestelmän asetukset";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Vain jos Elite:Dangerous on käynnissä";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Toista ääni";
|
||||
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:557; */
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:564; */
|
||||
"Disable Automatic Application Updates Check when in-game" = "Estä automaattiset päivitystarkastukset pelaamisen aikana";
|
||||
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:570; */
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:577; */
|
||||
"Preferred websites" = "Ensisijaiset sivustot";
|
||||
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:581; */
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:588; */
|
||||
"Shipyard" = "Telakka";
|
||||
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:593; */
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:600; */
|
||||
"Use alternate URL method" = "Käytä vaihtoehtoista URL-metodia";
|
||||
|
||||
/* prefs.py: Configuration - Label for selection of Log Level; In files: prefs.py:646; */
|
||||
/* prefs.py: Configuration - Label for selection of Log Level; In files: prefs.py:653; */
|
||||
"Log Level" = "Lokin syvyys";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Valinnat";
|
||||
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */
|
||||
"Privacy" = "Yksityisyys";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:709; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:716; */
|
||||
"Normal text" = "Normaali teksti";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:711; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:718; */
|
||||
"Highlighted text" = "Korostettu teksti";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Kieli";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Teema";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Tumma";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Läpinäkyvä";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of UI scaling; In files: prefs.py:794; */
|
||||
/* prefs.py: Appearance - Label for selection of UI scaling; In files: prefs.py:802; */
|
||||
"UI Scale Percentage" = "Käyttöliittymän skaalausprosentti";
|
||||
|
||||
/* prefs.py: Appearance - Help/hint text for UI scaling selection; In files: prefs.py:815; */
|
||||
/* prefs.py: Appearance - Help/hint text for UI scaling selection; In files: prefs.py:823; */
|
||||
"100 means Default{CR}Restart Required for{CR}changes to take effect!" = "100 tarkoittaa oletusta{CR}Muutosten käyttöönotto{CR}edellyttää uudelleenkäynnistystä!";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of main window transparency; In files: prefs.py:825; */
|
||||
/* prefs.py: Appearance - Label for selection of main window transparency; In files: prefs.py:833; */
|
||||
"Main window transparency" = "Pääikkunan läpinäkyvyys";
|
||||
|
||||
/* prefs.py: Appearance - Help/hint text for Main window transparency selection; In files: prefs.py:845:848; */
|
||||
/* prefs.py: Appearance - Help/hint text for Main window transparency selection; In files: prefs.py:853:856; */
|
||||
"100 means fully opaque.{CR}Window is updated in real time" = "100 tarkoittaa täysin peittävää.{CR}Ikkuna päivittyy reaaliajassa.";
|
||||
|
||||
/* prefs.py: Appearance option for Windows "minimize to system tray"; In files: prefs.py:877; */
|
||||
/* prefs.py: Appearance option for Windows "minimize to system tray"; In files: prefs.py:885; */
|
||||
"Minimize to system tray" = "Pienennä tehtäväpalkkiin";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Ulkoasu";
|
||||
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:900; */
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */
|
||||
"Plugins folder" = "Lisäosien hakemistosijainti";
|
||||
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:907; */
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */
|
||||
"Open" = "Avaa";
|
||||
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:915; */
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:923; */
|
||||
"Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name" = "Vihje: Voit poistaa lisäosan käytöstä{CR}lisäämällä '{EXT}' sen hakemistonimeen";
|
||||
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:926; */
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:934; */
|
||||
"Enabled Plugins" = "Käytössä olevat liitännäiset";
|
||||
|
||||
/* prefs.py: Plugins - Label for list of 'enabled' plugins that don't work with Python 3.x; In files: prefs.py:946; */
|
||||
/* prefs.py: Plugins - Label for list of 'enabled' plugins that don't work with Python 3.x; In files: prefs.py:954; */
|
||||
"Plugins Without Python 3.x Support:" = "Lisäosat, joissa ei ole Python 3.x -tukea:";
|
||||
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:954; */
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:962; */
|
||||
"Information on migrating plugins" = "Tietoja lisäosien siirrosta";
|
||||
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:969; */
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:977; */
|
||||
"Disabled Plugins" = "Estetyt liitännäiset";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Saldo";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Lainaa jäljellä";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Elite";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Taistelija -ranking";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Kaupankäynti -ranking";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Tutkimusmatkailija -ranking";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "CQC -ranking";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Federaation sotilasarvosi";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Imperiumin sotilasarvosi";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Valtapeli -ranking";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Mostly Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Novice";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Competent";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Expert";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Master";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Dangerous";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Deadly";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Mostly Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Peddler";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Dealer";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Merchant";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Broker";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Entrepreneur";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Tycoon";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Mostly Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Scout";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Surveyor";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Trailblazer";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Pathfinder";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Ranger";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Pioneer";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Mostly Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Amateur";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Semi Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Champion";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Hero";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Gladiator";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Recruit";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Cadet";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Midshipman";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Chief Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Warrant Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Ensign";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "Lieutenant";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Lieutenant Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Post Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Post Captain";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "Rear Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Vice Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Admiral";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Outsider";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Serf";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Squire";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Knight";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Lord";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Baron";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Viscount";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Count";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Earl";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Marquis";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Duke";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Prince";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "King";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Luokitus 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Luokitus 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Luokitus 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Luokitus 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Luokitus 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Arvo";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Alukset";
|
||||
+284
-284
@@ -1,518 +1,518 @@
|
||||
/* Language name */
|
||||
"!Language" = "Français";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Envoi des données à EDDN...";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Erreur : Connexion impossible à EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Envoyer les données de la station à Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:673; load.py:682; eddn.py:1133; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Envoyer les systèmes et les informations de scan à Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:683; load.py:692; eddn.py:1144; */
|
||||
"Delay sending until docked" = "Retarder l'envoi jusqu'à l'amarrage";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:197; load.py:197; edsm.py:237; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Envoyer le journal de vol et le statut Cmdr à EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "Informations d'identification pour Elite Dangerous Star Map";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Cmd";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "Nom du commandant";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "Clé API";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Aucun";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Erreur : EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Erreur : Connexion impossible à EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:215; load.py:215; inara.py:222; */
|
||||
"Send flight log and Cmdr status to Inara" = "Envoyer le journal de vol et le statut Cmdr à Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:225; load.py:225; inara.py:234; */
|
||||
"Inara credentials" = "Informations d'identification pour Inara";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1316; inara.py:1328; load.py:1319; load.py:1331; inara.py:1587; inara.py:1600; */
|
||||
"Error: Inara {MSG}" = "Erreur : Inara {MSG}";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Copier";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Mettre à jour";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Toujours visible";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Rôle";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Vaisseau";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */
|
||||
"Suit" = "Combinaison";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "Système";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Station";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "Fichier";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Édition";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "Présentation";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Fenêtre";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Aide";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "À propos de {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Chercher une mise à jour...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Sauvegarder les Données Brutes...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "État";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Politique de Confidentialité";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Notes de publication";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Paramètres";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Quitter";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Documentation";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Connexion en cours...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "Authentification réussie";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = "Vous n'êtes pas amarré à une station !";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "La station n'a rien du tout !";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "La station n'a pas de marché !";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Récupération des données...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Qui êtes-vous ?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Où êtes-vous ?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "Avec quoi volez-vous ?";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Dernière mise à jour à %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */
|
||||
"Fighter" = "Chasseur";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */
|
||||
"Gunner" = "Artilleur";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */
|
||||
"Helm" = "Pilote";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "Temps de recharge {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2008:2014; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Un ou plusieurs de vos plugins activés ne sont pas encore compatibles avec Python 3.x. Regardez la liste sur l'onglet '{PLUGINS}' de '{FILE}' > '{SETTINGS}'. Vous devriez vérifier s'il y a une version mise à jour, sinon alertez le développeur qu'il doit mettre à jour le code pour Python 3.x.\n\nVous pouvez désactiver un plugin en renommant son dossier pour qu'il ait '{DISABLED}' à la fin du nom.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */
|
||||
"Plugins" = "Plugins";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2029; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Plugins non compatibles avec Python 3.x";
|
||||
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:237; */
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:245; */
|
||||
"Error: Frontier server is lagging" = "Erreur : Le serveur Frontier ne répond pas";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Erreur : Identifiants invalides";
|
||||
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:288; */
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:296; */
|
||||
"Error: Wrong Cmdr" = "Erreur : Cmdr incorrect";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Mettre à jour";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Toujours visible";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Cmd";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Rôle";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Vaisseau";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */
|
||||
"Suit" = "Combinaison";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "Système";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Station";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "Fichier";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Édition";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "Présentation";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Fenêtre";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Aide";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "À propos de {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Chercher une mise à jour...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Sauvegarder les Données Brutes...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "État";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Documentation";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Politique de Confidentialité";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Notes de publication";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Paramètres";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Quitter";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Copier";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Connexion en cours...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "Authentification réussie";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = "Vous n'êtes pas amarré à une station !";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "La station n'a rien du tout !";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "La station n'a pas de marché !";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Récupération des données...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Qui êtes-vous ?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Où êtes-vous ?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "Avec quoi volez-vous ?";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Dernière mise à jour à %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */
|
||||
"Fighter" = "Chasseur";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */
|
||||
"Gunner" = "Artilleur";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */
|
||||
"Helm" = "Pilote";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "Temps de recharge {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2253:2259; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Un ou plusieurs de vos plugins activés ne sont pas encore compatibles avec Python 3.x. Regardez la liste sur l'onglet '{PLUGINS}' de '{FILE}' > '{SETTINGS}'. Vous devriez vérifier s'il y a une version mise à jour, sinon alertez le développeur qu'il doit mettre à jour le code pour Python 3.x.\n\nVous pouvez désactiver un plugin en renommant son dossier pour qu'il ait '{DISABLED}' à la fin du nom.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */
|
||||
"Plugins" = "Plugins";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2274; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Plugins non compatibles avec Python 3.x";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Par défaut";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Erreur : Connexion impossible à EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Envoyer les données de la station à Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:2052; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Envoyer les systèmes et les informations de scan à Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:2063; */
|
||||
"Delay sending until docked" = "Retarder l'envoi jusqu'à l'amarrage";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Envoi des données à EDDN...";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Envoyer le journal de vol et le statut Cmdr à EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "Informations d'identification pour Elite Dangerous Star Map";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "Nom du commandant";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "Clé API";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Aucun";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Erreur : EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Erreur : Connexion impossible à EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */
|
||||
"Send flight log and Cmdr status to Inara" = "Envoyer le journal de vol et le statut Cmdr à Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */
|
||||
"Inara credentials" = "Informations d'identification pour Inara";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1650; inara.py:1663; */
|
||||
"Error: Inara {MSG}" = "Erreur : Inara {MSG}";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Préférences";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Veuillez choisir les données à sauvegarder";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Données du marché au format CSV";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Données du marché au format Trade Dangerous";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Équipements du vaisseau";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:383; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:370; */
|
||||
"Automatically update on docking" = "Mettre à jour automatiquement à l'amarrage";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Emplacement des fichiers";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Spécifier...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Parcourir...";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Sorties";
|
||||
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:444; prefs.py:459; */
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:431; prefs.py:446; */
|
||||
"E:D journal file location" = "Emplacement du journal E:D";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Raccourci clavier";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Raccourci clavier";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "Rédémarrez {APP} pour utiliser les raccourcis";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} a besoin de permissions pour utiliser les raccourcis";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Ouvrir Préférences Système";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Seulement quand Elite: Dangerous est l'application active";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Jouer un son";
|
||||
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:557; */
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:564; */
|
||||
"Disable Automatic Application Updates Check when in-game" = "Désactiver la vérification automatique des mises à jour quand vous êtes en jeu";
|
||||
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:570; */
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:577; */
|
||||
"Preferred websites" = "Sites préférés";
|
||||
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:581; */
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:588; */
|
||||
"Shipyard" = "Chantier naval";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Configuration";
|
||||
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */
|
||||
"Privacy" = "Confidentialité";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:709; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:716; */
|
||||
"Normal text" = "Texte normal";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:711; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:718; */
|
||||
"Highlighted text" = "Texte en surbrillance";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Langue";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Thème";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Foncé";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Transparent";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Apparence";
|
||||
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:900; */
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */
|
||||
"Plugins folder" = "Répertoire des plugins";
|
||||
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:907; */
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */
|
||||
"Open" = "Ouvrir";
|
||||
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:915; */
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:923; */
|
||||
"Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name" = "Astuce : Vous pouvez désactiver un plugin en{CR}ajoutant '{EXT}' à son nom de répertoire";
|
||||
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:926; */
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:934; */
|
||||
"Enabled Plugins" = "Plugins activés";
|
||||
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:954; */
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:962; */
|
||||
"Information on migrating plugins" = "Informations sur la migration des plugins";
|
||||
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:969; */
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:977; */
|
||||
"Disabled Plugins" = "Plugins désactivés";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Solde";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Emprunt";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Élite";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Combattant";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Commerçant";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Explorateur";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "CQC";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Fédération";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Empire";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Powerplay";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "Inoffensif";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Bleu";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Novice";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Compétent";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Expert";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Vilain";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Vétéran";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Létal";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Sans-le-sou";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Mendiant";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Boutiquier";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Revendeur";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Marchand";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Courtier";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Entrepreneur";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Magnat";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Vagabond";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Touriste";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Voyageur";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Éclaireur";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Prospecteur";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Découvreur";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Navigateur";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Pionnier";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Mostly Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Amateur";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Semi Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Champion";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Hero";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Gladiator";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Recrue";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Cadet";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Matelot";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Second Maître";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Premier Maître";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Major";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Enseigne";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "Lieutenant";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Capitaine de Corvette";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Capitaine de Frégate";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Capitaine de Vaisseau";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "Contre-Amiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Vice-Amiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Amiral";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Étranger";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Serf";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Écuyer";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Chevalier";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Banneret";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Baron";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Vicomte";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Comte";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Marquis";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Duc";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Archiduc";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Prince";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "Roi";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Rang 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Rang 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Rang 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Rang 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Rang 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Valeur";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Vaisseaux";
|
||||
+273
-273
@@ -1,503 +1,503 @@
|
||||
/* Language name */
|
||||
"!Language" = "Magyar";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Adatok küldése az EDDN-nek...";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Hiba:Nem lehet kapcsolódni az EDDN-hez";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Állomás adatok küldése az EDDN-nek";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:673; load.py:682; eddn.py:1133; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Rendszer és szken adatok küldése az EDDN-nek";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:683; load.py:692; eddn.py:1144; */
|
||||
"Delay sending until docked" = "Küldés késletetése amig dokkolsz";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:197; load.py:197; edsm.py:237; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Repülési napló és Parancsnok státusz küldése az EDSM-nek";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous Csillag térkép hitelesítése";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Parancsnok";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "Parancsnok név";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "API kulcs";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Egyik sem";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Hiba:EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Hiba:nem lehet kapcsólodni az EDSM-hez";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:215; load.py:215; inara.py:222; */
|
||||
"Send flight log and Cmdr status to Inara" = "Repülési napló és Parancsnok státusz küldése az Inarának";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:225; load.py:225; inara.py:234; */
|
||||
"Inara credentials" = "Inara hitelesitő adatok";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1316; inara.py:1328; load.py:1319; load.py:1331; inara.py:1587; inara.py:1600; */
|
||||
"Error: Inara {MSG}" = "Hiba:Inara {MSG}";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Másol";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Frissítés";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Mindig felül";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Szerep";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Hajó";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "Rendszer";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Állomás";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "Fájl";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Szerkeszt";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "Nézet";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Ablak";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Segítség";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "Az {APP} névjegye";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Frissítések keresése";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Nyers adat elmentése";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "Státusz";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Adatvédelmi irányelvek";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Kiadási megjegyzések";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Beállítások";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Kilépés";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Dokumentáció";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Bejelentkezés";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "A hitelesítés sikerült";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = " Nem dokkoltál az állomáson";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "Az állomáson nincs semmi!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "Nincs piac az állomáson!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Adatok lekérése";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Ki vagy?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Hol vagy?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "Mivel repülsz?";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Utoljára frissítve %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */
|
||||
"Fighter" = "Vadászgép";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */
|
||||
"Gunner" = "Lövész";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */
|
||||
"Helm" = "Kormányos";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "Lehűl {SS} másodperc";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "Ok";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */
|
||||
"Plugins" = "Pluginok";
|
||||
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:237; */
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:245; */
|
||||
"Error: Frontier server is lagging" = "Hiba:Frontier szerver laggol";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Hiba:Érvénytelen hitelesítő adatok";
|
||||
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:288; */
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:296; */
|
||||
"Error: Wrong Cmdr" = "Hiba:Rossz parancsnok";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Frissítés";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Mindig felül";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Parancsnok";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Szerep";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Hajó";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "Rendszer";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Állomás";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "Fájl";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Szerkeszt";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "Nézet";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Ablak";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Segítség";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "Az {APP} névjegye";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Frissítések keresése";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Nyers adat elmentése";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "Státusz";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Dokumentáció";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Adatvédelmi irányelvek";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Kiadási megjegyzések";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Beállítások";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Kilépés";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Másol";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Bejelentkezés";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "A hitelesítés sikerült";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = " Nem dokkoltál az állomáson";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "Az állomáson nincs semmi!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "Nincs piac az állomáson!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Adatok lekérése";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Ki vagy?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Hol vagy?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "Mivel repülsz?";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Utoljára frissítve %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */
|
||||
"Fighter" = "Vadászgép";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */
|
||||
"Gunner" = "Lövész";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */
|
||||
"Helm" = "Kormányos";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "Lehűl {SS} másodperc";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "Ok";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */
|
||||
"Plugins" = "Pluginok";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Alap";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Hiba:Nem lehet kapcsolódni az EDDN-hez";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Állomás adatok küldése az EDDN-nek";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:2052; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Rendszer és szken adatok küldése az EDDN-nek";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:2063; */
|
||||
"Delay sending until docked" = "Küldés késletetése amig dokkolsz";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Adatok küldése az EDDN-nek...";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Repülési napló és Parancsnok státusz küldése az EDSM-nek";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous Csillag térkép hitelesítése";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "Parancsnok név";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "API kulcs";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Egyik sem";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Hiba:EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Hiba:nem lehet kapcsólodni az EDSM-hez";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */
|
||||
"Send flight log and Cmdr status to Inara" = "Repülési napló és Parancsnok státusz küldése az Inarának";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */
|
||||
"Inara credentials" = "Inara hitelesitő adatok";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1650; inara.py:1663; */
|
||||
"Error: Inara {MSG}" = "Hiba:Inara {MSG}";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Beállítások";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Kérem válassza ki a menteni kivánt adatokat.";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Piaci adat CSV fájlban";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Piaci adat Trade Dangerous fájlban";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Hajó felszerelése";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:383; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:370; */
|
||||
"Automatically update on docking" = "Automatikusan frissit dokkolásnál";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Fálj helye";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Módosítás...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Böngész";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Kimenet";
|
||||
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:444; prefs.py:459; */
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:431; prefs.py:446; */
|
||||
"E:D journal file location" = "E:D journal fájl helye";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Billentyűparancsok";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Gyorsgomb";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "Újranidítás {APP} parancsikonok használatával";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} engedély szükséges a parancsikon használatához";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Rendszerbeállítások megnyitáss";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Csak ha az Elite Dangerous fut";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Zene be";
|
||||
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:570; */
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:577; */
|
||||
"Preferred websites" = "Preferált weboldalak";
|
||||
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:581; */
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:588; */
|
||||
"Shipyard" = "Hajógyár";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Konfiguráció";
|
||||
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */
|
||||
"Privacy" = "Titkosítás";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:709; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:716; */
|
||||
"Normal text" = "Normál txt";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:711; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:718; */
|
||||
"Highlighted text" = "Kiemelt szöveg";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Nyelv";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Téma";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Sötét";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Átlárható";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Megjelenés";
|
||||
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:900; */
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */
|
||||
"Plugins folder" = "Plugin mappa";
|
||||
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:907; */
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */
|
||||
"Open" = "Nyisd ki";
|
||||
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:915; */
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:923; */
|
||||
"Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name" = "Tipp:a pluginokat kikapcsolhatod hozzà{CR}adsz a mappa nevében egy '{EXT}'";
|
||||
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:926; */
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:934; */
|
||||
"Enabled Plugins" = "Pluginok engedélyezése";
|
||||
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:969; */
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:977; */
|
||||
"Disabled Plugins" = "Plugin kikapcsolása";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Egyenleg";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Kölcsön";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Elit";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Harc";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Kereskedés";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Felfedező";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "CQC";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Föderáció";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Birodalom";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Powerplay";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "ártalmatlan";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Többnyire ártalmatlan";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Kezdő";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Képesített";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Szakértő";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Mester";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Veszélyes";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Halálos";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Nincstelen";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Többnyire nincstelen";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Házaló ügynők";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Kereskedő";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Kereskedő";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Bróker";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Vállalkozó";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Iparmágnás";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Céltalan";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Tøbnyire céltalan";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Felderítő";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Megfigyelő";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Útkereső";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Útkereső";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Vándor";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Utász";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "tehetetlen";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Többnyire tehetetlen";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Amatőr";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Fél profi";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Szakember";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Bajnok";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Hős";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Gladiátor";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Újonc";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Kadét";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Tengerészkadét";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Tizedes";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Törzs zászlós";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Tiszthelyettes";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Zászlós";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "Hadnagy";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Főhadnagy";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Ezredes";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Ellentengernagy";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "FőEllentengernagy";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Altengernagy";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Admirális";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Kivűlálló";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Jobbágy";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Földesúr";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Lovag";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Lord";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Báró";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Vicomte";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Számol";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Gróf";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Őrgróf";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Herceg";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Herceg";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "Király";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Osztákgozás 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Osztályozás 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Osztályozás 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Osztályozás 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Osztályozás 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Érték";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Hajók";
|
||||
+344
-344
@@ -1,596 +1,596 @@
|
||||
/* Language name */
|
||||
"!Language" = "Italiano";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Sto inviando i dati a EDDN...";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Errore: Non riesco a connettermi a EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Manda i dati della stazione a Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:673; load.py:682; eddn.py:1133; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Manda il sistema e i dati scansionati a EDDN";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:683; load.py:692; eddn.py:1144; */
|
||||
"Delay sending until docked" = "Ritarda l'invio fino a che si è ormeggiati";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:197; load.py:197; edsm.py:237; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Manda il flight log e lo stato Cmdr a EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "Credenziali per Elite Dangerous Star Map";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "Nome Commandante";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "API Key";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Nessuna";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Errore: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Errore: Non riesco a connettermi a EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:215; load.py:215; inara.py:222; */
|
||||
"Send flight log and Cmdr status to Inara" = "Manda il flight log e lo stato Cmdr a Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:225; load.py:225; inara.py:234; */
|
||||
"Inara credentials" = "Credenziali per Inara";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1316; inara.py:1328; load.py:1319; load.py:1331; inara.py:1587; inara.py:1600; */
|
||||
"Error: Inara {MSG}" = "Errore: Inara {MSG}";
|
||||
|
||||
/* coriolis.py: 'Auto' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - auto; In files: load.py:51; load.py:51; load.py:88; load.py:104; load.py:110; coriolis.py:52; coriolis.py:55; coriolis.py:101; coriolis.py:117; coriolis.py:123; */
|
||||
"Auto" = "Auto";
|
||||
|
||||
/* coriolis.py: 'Normal' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - normal; In files: load.py:51; load.py:88; load.py:102; coriolis.py:53; coriolis.py:99; coriolis.py:115; */
|
||||
"Normal" = "Normale";
|
||||
|
||||
/* coriolis.py: 'Beta' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - beta; In files: load.py:51; load.py:88; load.py:103; coriolis.py:54; coriolis.py:100; coriolis.py:116; */
|
||||
"Beta" = "Beta";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */
|
||||
"Normal URL" = "URL normale";
|
||||
|
||||
/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */
|
||||
"Reset" = "Reimposta";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */
|
||||
"Beta URL" = "URL Beta";
|
||||
|
||||
/* eddb.py: Journal Processing disabled due to an active killswitch; In files: load.py:99; eddb.py:100; */
|
||||
"EDDB Journal processing disabled. See Log." = "Elaborazione di EDDB Journal disabilitata. Guarda il Log.";
|
||||
|
||||
/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */
|
||||
"Inara disabled. See Log." = "Inara disabilitato. Vedi il Log.";
|
||||
|
||||
/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: test_ast_stuff.py:2; EDMarketConnector.py:1047; */
|
||||
"CAPI: No commander data returned" = "CAPI: Nessun dato sul commandante";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */
|
||||
"Override Beta/Normal Selection" = "Sovrascrivi selezione Beta/Normale";
|
||||
|
||||
/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */
|
||||
"Journal directory already locked" = "cartella Journal già bloccata";
|
||||
|
||||
/* journal_lock.py: Text for when newly selected Journal directory is already locked; In files: journal_lock.py:223:224; */
|
||||
"The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this." = "La nuova cartella dove risiede il Journal è già bloccata.{CR}Puoi provare a risolvere Riprovando, oppure scegliere di ignorare la cosa.";
|
||||
|
||||
/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */
|
||||
"Retry" = "Riprova";
|
||||
|
||||
/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */
|
||||
"Ignore" = "Ignora";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Copia";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Recupera";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Sempre in primo piano";
|
||||
|
||||
/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */
|
||||
"Unknown" = "Sconosciuto";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Ruolo";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Nave";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */
|
||||
"Suit" = "Tuta";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "Sistema";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Stazione";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "File";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Appunti";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "Vista";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Finestra";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Guida";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "Informazioni su {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Controlla aggiornamenti...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Salva i Dati Grezzi...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Informativa sulla privacy";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Note di rilascio";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Impostazioni";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Esci";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Documentazione";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Mi sto loggando...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "Autenticazione riuscita";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = "Non sei parcheggiato in nessuna stazione !";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "La Stazione non ha niente !";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "La Stazione non ha un Market !";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Sto raccogliendo i dati...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Chi sei ?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Dove sei finito ?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "Stai volando ?!";
|
||||
|
||||
/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */
|
||||
"Frontier CAPI server error" = "Errore nel server Frontier CAPI";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Ultimo aggiornamento alle %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */
|
||||
"Fighter" = "Cacciatore";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */
|
||||
"Gunner" = "Artigliere";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */
|
||||
"Helm" = "Timoniere";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "disponibile tra {SS} secondi";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1693; */
|
||||
"Shutting down..." = "Spegnimento...";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2008:2014; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Uno o più dei tuoi plugin non ha ancora il supporto per Python 3.x. Per favore guarda la lista '{PLUGINS}' nella tab a '{FILE}' > '{SETTINGS}'. Dovresti controllare se ci sono aggiornamenti, altrimenti avvisa gli sviluppatori che devono aggiornare il codice a Python 3.x.\n\nPuoi disabilitare il plugin rinominando la cartella aggiungendo '{DISABLED}' alla fine del nome.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */
|
||||
"Plugins" = "Plugins";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2029; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Plugins senza Supporto Python 3.x";
|
||||
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:237; */
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:245; */
|
||||
"Error: Frontier server is lagging" = "Errore: il server Frontier sta laggando";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Errore: Credenziali non valide";
|
||||
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:288; */
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:296; */
|
||||
"Error: Wrong Cmdr" = "Errore: Cmdr sbagliato";
|
||||
|
||||
/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:414; companion.py:499; */
|
||||
/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:432; companion.py:517; */
|
||||
"Error" = "Errore";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Recupera";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Sempre in primo piano";
|
||||
|
||||
/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */
|
||||
"Unknown" = "Sconosciuto";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Ruolo";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Nave";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */
|
||||
"Suit" = "Tuta";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "Sistema";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Stazione";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "File";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Appunti";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "Vista";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Finestra";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Guida";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "Informazioni su {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Controlla aggiornamenti...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Salva i Dati Grezzi...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Documentazione";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Informativa sulla privacy";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Note di rilascio";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Impostazioni";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Esci";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Copia";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Mi sto loggando...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "Autenticazione riuscita";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = "Non sei parcheggiato in nessuna stazione !";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "La Stazione non ha niente !";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "La Stazione non ha un Market !";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Sto raccogliendo i dati...";
|
||||
|
||||
/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */
|
||||
"CAPI: No commander data returned" = "CAPI: Nessun dato sul commandante";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Chi sei ?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Dove sei finito ?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "Stai volando ?!";
|
||||
|
||||
/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */
|
||||
"Frontier CAPI server error" = "Errore nel server Frontier CAPI";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Ultimo aggiornamento alle %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */
|
||||
"Fighter" = "Cacciatore";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */
|
||||
"Gunner" = "Artigliere";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */
|
||||
"Helm" = "Timoniere";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "disponibile tra {SS} secondi";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1936; */
|
||||
"Shutting down..." = "Spegnimento...";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2253:2259; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Uno o più dei tuoi plugin non ha ancora il supporto per Python 3.x. Per favore guarda la lista '{PLUGINS}' nella tab a '{FILE}' > '{SETTINGS}'. Dovresti controllare se ci sono aggiornamenti, altrimenti avvisa gli sviluppatori che devono aggiornare il codice a Python 3.x.\n\nPuoi disabilitare il plugin rinominando la cartella aggiungendo '{DISABLED}' alla fine del nome.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */
|
||||
"Plugins" = "Plugins";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2274; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Plugins senza Supporto Python 3.x";
|
||||
|
||||
/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:208; */
|
||||
"Journal directory already locked" = "cartella Journal già bloccata";
|
||||
|
||||
/* journal_lock.py: Text for when newly selected Journal directory is already locked; In files: journal_lock.py:225:226; */
|
||||
"The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this." = "La nuova cartella dove risiede il Journal è già bloccata.{CR}Puoi provare a risolvere Riprovando, oppure scegliere di ignorare la cosa.";
|
||||
|
||||
/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */
|
||||
"Retry" = "Riprova";
|
||||
|
||||
/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */
|
||||
"Ignore" = "Ignora";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Predefinito";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* coriolis.py: 'Auto' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - auto; In files: coriolis.py:74; coriolis.py:77; coriolis.py:123; coriolis.py:139; coriolis.py:145; */
|
||||
"Auto" = "Auto";
|
||||
|
||||
/* coriolis.py: 'Normal' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - normal; In files: coriolis.py:75; coriolis.py:121; coriolis.py:137; */
|
||||
"Normal" = "Normale";
|
||||
|
||||
/* coriolis.py: 'Beta' label for Coriolis site override selection; coriolis.py: Coriolis normal/beta selection - beta; In files: coriolis.py:76; coriolis.py:122; coriolis.py:138; */
|
||||
"Beta" = "Beta";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */
|
||||
"Normal URL" = "URL normale";
|
||||
|
||||
/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */
|
||||
"Reset" = "Reimposta";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: coriolis.py:106; */
|
||||
"Beta URL" = "URL Beta";
|
||||
|
||||
/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:116; */
|
||||
"Override Beta/Normal Selection" = "Sovrascrivi selezione Beta/Normale";
|
||||
|
||||
/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */
|
||||
"EDDB Journal processing disabled. See Log." = "Elaborazione di EDDB Journal disabilitata. Guarda il Log.";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Errore: Non riesco a connettermi a EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Manda i dati della stazione a Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:2052; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Manda il sistema e i dati scansionati a EDDN";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:2063; */
|
||||
"Delay sending until docked" = "Ritarda l'invio fino a che si è ormeggiati";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Sto inviando i dati a EDDN...";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Manda il flight log e lo stato Cmdr a EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "Credenziali per Elite Dangerous Star Map";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "Nome Commandante";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "API Key";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Nessuna";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Errore: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Errore: Non riesco a connettermi a EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */
|
||||
"Send flight log and Cmdr status to Inara" = "Manda il flight log e lo stato Cmdr a Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */
|
||||
"Inara credentials" = "Credenziali per Inara";
|
||||
|
||||
/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */
|
||||
"Inara disabled. See Log." = "Inara disabilitato. Vedi il Log.";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1650; inara.py:1663; */
|
||||
"Error: Inara {MSG}" = "Errore: Inara {MSG}";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Preferenze";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Si prega di scegliere che dati salvare";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Market data in formato CSV";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Market data in formato Trade Dangerous";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Equipaggiamento della nave";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:383; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:370; */
|
||||
"Automatically update on docking" = "Auto-aggiornamento all'ormeggio";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Percorso del file";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Cambia...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Sfoglia...";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Output";
|
||||
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:444; prefs.py:459; */
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:431; prefs.py:446; */
|
||||
"E:D journal file location" = "locazione del file E:D journal";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Scorciatoia di tastiera";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Hotkey";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "Riavvia {APP} per usare le scorciatoie";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} ha bisogno dei permessi per usare le scorciatoie";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Apri Preferenze di Sistema";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Solo quando “Elite: Dangerous” è in primo piano";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Notifica sonora";
|
||||
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:557; */
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:564; */
|
||||
"Disable Automatic Application Updates Check when in-game" = "Disabilita gli aggiornamenti automatici quando sei in-game";
|
||||
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:570; */
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:577; */
|
||||
"Preferred websites" = "Sito web preferito";
|
||||
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:581; */
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:588; */
|
||||
"Shipyard" = "Spazioporto";
|
||||
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:593; */
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:600; */
|
||||
"Use alternate URL method" = "Usare metodo URL alternativo";
|
||||
|
||||
/* prefs.py: Configuration - Label for selection of Log Level; In files: prefs.py:646; */
|
||||
/* prefs.py: Configuration - Label for selection of Log Level; In files: prefs.py:653; */
|
||||
"Log Level" = "Livello di Log";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Configurazione";
|
||||
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */
|
||||
"Privacy" = "Dati personali";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:709; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:716; */
|
||||
"Normal text" = "Testo normale";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:711; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:718; */
|
||||
"Highlighted text" = "Testo evidenziato";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Lingua";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Tema";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Scuro";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Trasparente";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of UI scaling; In files: prefs.py:794; */
|
||||
/* prefs.py: Appearance - Label for selection of UI scaling; In files: prefs.py:802; */
|
||||
"UI Scale Percentage" = "Percentuale zoom della UI";
|
||||
|
||||
/* prefs.py: Appearance - Help/hint text for UI scaling selection; In files: prefs.py:815; */
|
||||
/* prefs.py: Appearance - Help/hint text for UI scaling selection; In files: prefs.py:823; */
|
||||
"100 means Default{CR}Restart Required for{CR}changes to take effect!" = "100 significa Default{CR}Riavvio Richiesto per{CR}applicare i cambiamenti!";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of main window transparency; In files: prefs.py:825; */
|
||||
/* prefs.py: Appearance - Label for selection of main window transparency; In files: prefs.py:833; */
|
||||
"Main window transparency" = "Trasparenza della finestra principale";
|
||||
|
||||
/* prefs.py: Appearance - Help/hint text for Main window transparency selection; In files: prefs.py:845:848; */
|
||||
/* prefs.py: Appearance - Help/hint text for Main window transparency selection; In files: prefs.py:853:856; */
|
||||
"100 means fully opaque.{CR}Window is updated in real time" = "100 stà per completamente opaco.{CR}Finestra è aggiornata in tempo reale";
|
||||
|
||||
/* prefs.py: Appearance option for Windows "minimize to system tray"; In files: prefs.py:877; */
|
||||
/* prefs.py: Appearance option for Windows "minimize to system tray"; In files: prefs.py:885; */
|
||||
"Minimize to system tray" = "Riduci a icona nel Vassoio di sistema";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Aspetto";
|
||||
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:900; */
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */
|
||||
"Plugins folder" = "Cartella dei plugins";
|
||||
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:907; */
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */
|
||||
"Open" = "Apri";
|
||||
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:915; */
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:923; */
|
||||
"Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name" = "Suggerimento: è possibile disabilitare un plugin {CR}aggiungendo '{EXT}' nel nome della sua cartella";
|
||||
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:926; */
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:934; */
|
||||
"Enabled Plugins" = "Plugin abilitati";
|
||||
|
||||
/* prefs.py: Plugins - Label for list of 'enabled' plugins that don't work with Python 3.x; In files: prefs.py:946; */
|
||||
/* prefs.py: Plugins - Label for list of 'enabled' plugins that don't work with Python 3.x; In files: prefs.py:954; */
|
||||
"Plugins Without Python 3.x Support:" = "Plugin senza il supporto a Python 3.x :";
|
||||
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:954; */
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:962; */
|
||||
"Information on migrating plugins" = "Informazioni sulla migrazione dei plugins";
|
||||
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:969; */
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:977; */
|
||||
"Disabled Plugins" = "Plugin disabilitati";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Saldo";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Prestito";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Elite";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Combat";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Trade";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Explorer";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "CQC";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Federazione";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Impero";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Powerplay";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Mostly Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Novice";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Competent";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Expert";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Master";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Dangerous";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Deadly";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Mostly Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Peddler";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Dealer";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Merchant";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Broker";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Entrepreneur";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Tycoon";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Mostly Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Scout";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Surveyor";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Trailblazer";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Pathfinder";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Ranger";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Pioneer";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Mostly Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Amateur";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Semi Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Champion";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Hero";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Gladiator";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Recruit";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Cadet";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Midshipman";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Chief Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Warrant Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Ensign";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "Lieutenant";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Lieutenant Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Post Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Post Captain";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "Rear Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Vice Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Admiral";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Outsider";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Serf";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Squire";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Knight";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Lord";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Baron";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Viscount";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Count";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Earl";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Marquis";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Duke";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Prince";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "King";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Rating 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Rating 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Rating 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Rating 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Rating 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Valore";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Navi";
|
||||
+453
-429
File diff suppressed because it is too large.
Load diff
+395
-395
File diff suppressed because it is too large.
Load diff
+258
-258
@@ -1,482 +1,482 @@
|
||||
/* Language name */
|
||||
"!Language" = "Latviešu";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Sūta datus uz EDDN...";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Kļūda: Nevar savienoties ar EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Sūtīt stacijas datus uz Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:673; load.py:682; eddn.py:1133; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Sūtīt stacijas datus uz Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:683; load.py:692; eddn.py:1144; */
|
||||
"Delay sending until docked" = "Aizkavēt sūtīšanu līdz nosēšanai";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous zvaigžņu kartes informācija";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "Komandiera vārds";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "API atslēga";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Neviens";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Kļūda: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Kļūda: Nevar savienoties ar EDSM";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Kopēt";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Atjaunināt";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Vienmēr virspusē";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Loma";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Kuģis";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "Sistēma";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Stacija";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "Fails";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Labot";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "Skats";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Logs";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Palīdzība";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "Par {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Pārbaudīt atjauninājumus...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Saglabāt sākotnējos datus...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "Statuss";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Privātuma politika";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Informācija par laidienu";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Iestatījumi";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Iziet";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Dokumentācija";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Autorizējas...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "Autentifikācija sekmīga";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = "Jūs neesat stacijā!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "Stacijā nekā nav!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "Stacijā nav tirgus!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Iegūst datus...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Kas tu esi?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Kur tu esi?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "Ar ko tu lido?";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Pēdējo reizi atjaunināts %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */
|
||||
"Fighter" = "Cīnītājs";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */
|
||||
"Gunner" = "Ložmetējnieks";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */
|
||||
"Helm" = "Stūre";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "Atskaite {SS}";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "Labi";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */
|
||||
"Plugins" = "Spraudņi";
|
||||
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:237; */
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:245; */
|
||||
"Error: Frontier server is lagging" = "Kļūda: Frontier serveris aizkavējas";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Kļūda: Nederīga lietotāja informācija";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Atjaunināt";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Vienmēr virspusē";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Loma";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Kuģis";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "Sistēma";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Stacija";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "Fails";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Labot";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "Skats";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Logs";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Palīdzība";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "Par {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Pārbaudīt atjauninājumus...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Saglabāt sākotnējos datus...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "Statuss";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Dokumentācija";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Privātuma politika";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Informācija par laidienu";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Iestatījumi";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Iziet";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Kopēt";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Autorizējas...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "Autentifikācija sekmīga";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = "Jūs neesat stacijā!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "Stacijā nekā nav!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "Stacijā nav tirgus!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Iegūst datus...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Kas tu esi?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Kur tu esi?";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "Ar ko tu lido?";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Pēdējo reizi atjaunināts %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */
|
||||
"Fighter" = "Cīnītājs";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */
|
||||
"Gunner" = "Ložmetējnieks";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */
|
||||
"Helm" = "Stūre";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "Atskaite {SS}";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "Labi";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */
|
||||
"Plugins" = "Spraudņi";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Noklusējuma";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Kļūda: Nevar savienoties ar EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Sūtīt stacijas datus uz Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:2052; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Sūtīt stacijas datus uz Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:2063; */
|
||||
"Delay sending until docked" = "Aizkavēt sūtīšanu līdz nosēšanai";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Sūta datus uz EDDN...";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous zvaigžņu kartes informācija";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "Komandiera vārds";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "API atslēga";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Neviens";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Kļūda: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Kļūda: Nevar savienoties ar EDSM";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Iestatījumi";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Lūdzu izvēlaties kādus datus saglabāt";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Tirgus dati CSV formātā";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Tirgus dati Trade Dangerous formātā";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Kuģa loadout";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:383; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:370; */
|
||||
"Automatically update on docking" = "Automtiski atjaunoties nosēžoties.";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Faila atrašanās vieta";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Mainīt...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Pārlūkot...";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Izvade";
|
||||
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:444; prefs.py:459; */
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:431; prefs.py:446; */
|
||||
"E:D journal file location" = "E:D žurnāla faila atrašanās vieta";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Ātrais taustiņš";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Ātrais taustiņš";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "Restartējiet {APP} lai izmantotu īssceļus";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} vajag atļaujas lai izmantotu īssceļus";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Atvērt sistēmas iestatījumus";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Tikai kad Elite: Dangerous ir aktīvā aplikācija";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Atskaņot skaņu";
|
||||
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:581; */
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:588; */
|
||||
"Shipyard" = "Kuģu būvētava";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Konfigurācija";
|
||||
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */
|
||||
"Privacy" = "Privātums";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:709; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:716; */
|
||||
"Normal text" = "Normālais teksts";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:711; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:718; */
|
||||
"Highlighted text" = "Izceltais teksts";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Valoda";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Dizains";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Tumša";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Caurspīdīga";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Izskats";
|
||||
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:900; */
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */
|
||||
"Plugins folder" = "Spraudņu mape";
|
||||
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:907; */
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */
|
||||
"Open" = "Atvērt";
|
||||
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:926; */
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:934; */
|
||||
"Enabled Plugins" = "Iespējoti Spraudņi";
|
||||
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:969; */
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:977; */
|
||||
"Disabled Plugins" = "Atspējoti Spraudņi";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Bilance";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Aizdevums";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Elite";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Combat";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Trade";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Explorer";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "CQC";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Federation";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Empire";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Powerplay";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "Nekaitīgs";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Mostly Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Novice";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Competent";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Expert";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Master";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Dangerous";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Deadly";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Mostly Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Peddler";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Dealer";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Merchant";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Broker";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Entrepreneur";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Tycoon";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Mostly Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Scout";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Surveyor";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Trailblazer";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Pathfinder";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Ranger";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Pioneer";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "Bezpalīdzīgs";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Mostly Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Amateur";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Semi Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Champion";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Varonis";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Gladiators";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Recruit";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Cadet";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Midshipman";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Chief Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Warrant Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Ensign";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "Leitnants";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Lieutenant Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Post Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Post Captain";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "Rear Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Vice Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Admiral";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Outsider";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Serf";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Squire";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Bruņinieks";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Lord";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Baron";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Viscount";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Count";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Earl";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Marquis";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Duke";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Prince";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "Karalis";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Rating 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Rating 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Rating 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Rating 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Rating 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Vērtība";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Kuģi";
|
||||
+282
-282
@@ -1,518 +1,518 @@
|
||||
/* Language name */
|
||||
"!Language" = "Nederlands";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Bezig data te versturen naar EDDN...";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Fout: Kan geen verbinding maken met EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Stuur station gegevens naar het Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:673; load.py:682; eddn.py:1133; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Stuur systeem en scan gegevens naar het Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:683; load.py:692; eddn.py:1144; */
|
||||
"Delay sending until docked" = "Stel verzending uit tot na het docken";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:197; load.py:197; edsm.py:237; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Stuur vlucht logboek en Cmdr status naar EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous Star Map inlog gegevens";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "Commander naam";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "API Key";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Geen";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Fout: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Fout: Kan geen verbinding maken met EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:215; load.py:215; inara.py:222; */
|
||||
"Send flight log and Cmdr status to Inara" = "Stuur vlucht logboek en Cmdr status naar Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:225; load.py:225; inara.py:234; */
|
||||
"Inara credentials" = "Inara inlog gegevens";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1316; inara.py:1328; load.py:1319; load.py:1331; inara.py:1587; inara.py:1600; */
|
||||
"Error: Inara {MSG}" = "Fout: Inara {MSG}";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Kopieëren";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Bijwerken";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Altijd op voorgrond";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Rol";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Schip";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "Systeem";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Station";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "Bestand";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Bewerken";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "Beeld";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Venster";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Help";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "Over {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Controleren op updates...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Sla onbewerkte gegevens op...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Privacybeleid";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Release opmerkingen";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Instellingen";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Afsluiten";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Documentatie";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Bezig met inloggen...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "Authenticatie voltooid";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = "Je bent niet gedockt in een station!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "Station heeft helemaal niets!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "Station heeft geen markt!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Data wordt opgehaald...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Wie ben je?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Waar ben je?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "Waar vlieg je in?!";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Voor het laatst bijgewerkt om %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */
|
||||
"Fighter" = "Gevechtsvlieger";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */
|
||||
"Gunner" = "Schutter";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */
|
||||
"Helm" = "Stuurman";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "wachtperiode {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2008:2014; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Een of meer ingeschakelde plugins hebben nog geen Python 3.x ondersteuning. Kijk op de lijst op de '{PLUGINS}' tab van '{FILE}' > '{SETTINGS}'. Check of er een bijgewerkte versie beschikbaar is. Laat anders de developer weten dat ze de code moeten updaten voor Python 3.x.\n\nJe kan de plugin uitschakelen door het mapje te hernoemen met '{DISABLED}' aan het eind van de naam.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */
|
||||
"Plugins" = "Plugins";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2029; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMS: Plugins zonder Python 3.x ondersteuning";
|
||||
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:237; */
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:245; */
|
||||
"Error: Frontier server is lagging" = "Fout: Frontier server is vertraagd";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Fout: Ongeldige inlog gegevens";
|
||||
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:288; */
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:296; */
|
||||
"Error: Wrong Cmdr" = "Fout: Verkeerde Cmdr";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Bijwerken";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Altijd op voorgrond";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Rol";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Schip";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "Systeem";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Station";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "Bestand";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Bewerken";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "Beeld";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Venster";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Help";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "Over {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Controleren op updates...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Sla onbewerkte gegevens op...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Documentatie";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Privacybeleid";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Release opmerkingen";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Instellingen";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Afsluiten";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Kopieëren";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Bezig met inloggen...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "Authenticatie voltooid";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = "Je bent niet gedockt in een station!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "Station heeft helemaal niets!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "Station heeft geen markt!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Data wordt opgehaald...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Wie ben je?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Waar ben je?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "Waar vlieg je in?!";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Voor het laatst bijgewerkt om %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */
|
||||
"Fighter" = "Gevechtsvlieger";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */
|
||||
"Gunner" = "Schutter";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */
|
||||
"Helm" = "Stuurman";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "wachtperiode {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2253:2259; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Een of meer ingeschakelde plugins hebben nog geen Python 3.x ondersteuning. Kijk op de lijst op de '{PLUGINS}' tab van '{FILE}' > '{SETTINGS}'. Check of er een bijgewerkte versie beschikbaar is. Laat anders de developer weten dat ze de code moeten updaten voor Python 3.x.\n\nJe kan de plugin uitschakelen door het mapje te hernoemen met '{DISABLED}' aan het eind van de naam.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */
|
||||
"Plugins" = "Plugins";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2274; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMS: Plugins zonder Python 3.x ondersteuning";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Standaard";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Fout: Kan geen verbinding maken met EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Stuur station gegevens naar het Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:2052; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Stuur systeem en scan gegevens naar het Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:2063; */
|
||||
"Delay sending until docked" = "Stel verzending uit tot na het docken";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Bezig data te versturen naar EDDN...";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Stuur vlucht logboek en Cmdr status naar EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous Star Map inlog gegevens";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "Commander naam";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "API Key";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Geen";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Fout: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Fout: Kan geen verbinding maken met EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */
|
||||
"Send flight log and Cmdr status to Inara" = "Stuur vlucht logboek en Cmdr status naar Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */
|
||||
"Inara credentials" = "Inara inlog gegevens";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1650; inara.py:1663; */
|
||||
"Error: Inara {MSG}" = "Fout: Inara {MSG}";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Preferences";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Welke gegevens wilt u opslaan?";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Markt data in CSV bestand formaat";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Markt data in Trade Dangerous bestand formaat";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Schip inrichting";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:383; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:370; */
|
||||
"Automatically update on docking" = "Automatisch bijwerken na de landing";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Bestand locatie";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Wijzigen...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Bladeren...";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Uitvoer";
|
||||
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:444; prefs.py:459; */
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:431; prefs.py:446; */
|
||||
"E:D journal file location" = "E:D journaal bestand locatie";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Toetscombinaties";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Hotkey";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "{APP} heropstarten om toetscombinaties te gebruiken";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} heeft toestemming nodig om toetscombinaties te gebruiken";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Open Systeemvoorkeuren";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Alleen wanneer Elite: Dangerous de actieve applicatie is";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Geluid afspelen";
|
||||
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:557; */
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:564; */
|
||||
"Disable Automatic Application Updates Check when in-game" = "Schakel Automatische update check uit wanneer in-game";
|
||||
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:570; */
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:577; */
|
||||
"Preferred websites" = "Voorkeur websites";
|
||||
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:581; */
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:588; */
|
||||
"Shipyard" = "Scheepswerf";
|
||||
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:593; */
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:600; */
|
||||
"Use alternate URL method" = "Gebruik andere URL methode";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Configuratie";
|
||||
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */
|
||||
"Privacy" = "Privacy";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:709; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:716; */
|
||||
"Normal text" = "Normale tekst";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:711; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:718; */
|
||||
"Highlighted text" = "Gemarkeerde tekst";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Taal";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Thema";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Donker";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Transparent";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Vormgeving";
|
||||
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:900; */
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */
|
||||
"Plugins folder" = "Plugins map";
|
||||
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:907; */
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */
|
||||
"Open" = "Openen";
|
||||
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:915; */
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:923; */
|
||||
"Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name" = "Tip: Je kan een plugin deactiveren door '{EXT}'{CR}toe te voegen aan de map naam";
|
||||
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:926; */
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:934; */
|
||||
"Enabled Plugins" = "Geactiveerde plugins";
|
||||
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:954; */
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:962; */
|
||||
"Information on migrating plugins" = "Informatie over plugins migreren";
|
||||
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:969; */
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:977; */
|
||||
"Disabled Plugins" = "Gedeactiveerde plugins";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Balans";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Lening";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Elite";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Gevechts rang";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Handels rang";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Ontdekkingsreiziger rang";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "CQC";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Federation";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Empire";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Powerplay";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Mostly Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Novice";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Competent";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Expert";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Master";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Dangerous";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Deadly";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Mostly Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Peddler";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Dealer";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Merchant";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Broker";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Entrepreneur";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Tycoon";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Mostly Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Scout";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Surveyor";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Trailblazer";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Pathfinder";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Ranger";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Pioneer";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Mostly Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Amateur";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Semi Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Champion";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Hero";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Gladiator";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Recruit";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Cadet";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Midshipman";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Chief Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Warrant Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Ensign";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "Lieutenant";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Lieutenant Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Post Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Post Captain";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "Rear Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Vice Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Admiral";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Outsider";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Serf";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Squire";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Knight";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Lord";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Baron";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Viscount";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Count";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Earl";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Marquis";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Duke";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Prince";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "King";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Rating 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Rating 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Rating 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Rating 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Rating 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Waarde";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Schepen";
|
||||
+420
-426
File diff suppressed because it is too large.
Load diff
+454
-430
File diff suppressed because it is too large.
Load diff
+453
-429
File diff suppressed because it is too large.
Load diff
+453
-429
File diff suppressed because it is too large.
Load diff
+230
-230
@@ -1,434 +1,434 @@
|
||||
/* Language name */
|
||||
"!Language" = "Slovenščina";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Pošiljam podatke na EDDN";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Napaka: povezava z EDDN ni mogoča";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Pošlji podatke postaje na EDDN";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "EDStarMap uporabniški podatki";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "Commander ime";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "API ključ";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Brez";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Napaka: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Napaka: Povezava z EDSM ni mogoča";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Kopiraj";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Osveži";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Vedno na vrhu";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Vloga";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Ladja";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "Sistem";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Postaja";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "Datoteka";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Uredi";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "Pogled";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Okno";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Pomoč";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "O {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Preveri posodobitve...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Shrani Izvirne Podatke...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Pravilnik o zasebnosti";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Opombe ob izdaji";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Nastavitve";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Izhod";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Dokumentacija";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Prijava v teku... ";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "Preverjanje pristnosti je bilo uspešno";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = "Nahajš se v postaji!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "Postaja nima ničesar";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "Postaja nima trga";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Nalagam podatke...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Kdo si";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Kje se nahajaš";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "S čim letiš";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Zadnja osvežitev podatkov %H:%M:%S ";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "Posodobitev v {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "Potrdi";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Napaka: napačno uporabniški ime ali geslo";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Osveži";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Vedno na vrhu";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Vloga";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Ladja";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "Sistem";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Postaja";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "Datoteka";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Uredi";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "Pogled";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Okno";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Pomoč";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "O {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Preveri posodobitve...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Shrani Izvirne Podatke...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Dokumentacija";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Pravilnik o zasebnosti";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Opombe ob izdaji";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Nastavitve";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Izhod";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Kopiraj";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Prijava v teku... ";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "Preverjanje pristnosti je bilo uspešno";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = "Nahajš se v postaji!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "Postaja nima ničesar";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "Postaja nima trga";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Nalagam podatke...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Kdo si";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Kje se nahajaš";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "S čim letiš";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Zadnja osvežitev podatkov %H:%M:%S ";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "Posodobitev v {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "Potrdi";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Privzeta";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Napaka: povezava z EDDN ni mogoča";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Pošlji podatke postaje na EDDN";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Pošiljam podatke na EDDN";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "EDStarMap uporabniški podatki";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "Commander ime";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "API ključ";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Brez";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Napaka: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Napaka: Povezava z EDSM ni mogoča";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Nastavitve";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Izberite podatke, ki jih želite shraniti";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Podatki trga v CSV formatu";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Podatki trga v Trade Dangerous formatu";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Oprema ladje";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Lokacija datoteke";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Spremeni...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Prebrskaj...";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Izpis";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Bližnjica";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Bližnjica";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "Ponovno poženi {APP} za uporabo bližnjic";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} potrebuje dovoljenja za uporabo bližnjic";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Odpri sistemske nastavitve";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Samo ko je Elite:Dangerous aktivna aplikacija ";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Sproži zvok";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Konfiguracija";
|
||||
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */
|
||||
"Privacy" = "Privatno";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Jezik";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Tema";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Temno";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Prosojno";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Videz";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Ravnotežje";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Posojilo";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Elite";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Combat";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Trgovanje";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Explorer";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "CQC";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Federacija";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Cesarstvo";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Igra moči";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Mostly Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Novice";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Competent";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Expert";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Master";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Dangerous";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Deadly";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Peniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Mostly peniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Peddler";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Dealer";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Merchant";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Broker";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Enterpreneur";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Tycoon";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Mostly Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Scout";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Surveyor";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Trailblazer";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Pathfinder";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Ranger";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Pioneer";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Mostly Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Amateur";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Semi Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Champion";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Hero";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Gladiator";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Recruit";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Cadet";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Midshipman";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Chief Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Warrant Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Ensign";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "LIeutenant";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Lieutenant Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Post Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Post Captain";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "Read Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Vice Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Admiral";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Outsider";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Serif";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Squire";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Knight";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Lord";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Baron";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Viscount";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Count";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Earl";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Marquis";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Duke";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Prince";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "King";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Ocena 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Ocena 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Ocena 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Ocena 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Ocena 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Vrednost";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Ladje";
|
||||
+423
-429
File diff suppressed because it is too large.
Load diff
+453
-429
File diff suppressed because it is too large.
Load diff
+280
-280
@@ -1,512 +1,512 @@
|
||||
/* Language name */
|
||||
"!Language" = "Svenska";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Skickar data till EDDN...";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Fel: Kan inte ansluta till EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Skicka stationsdata till Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:673; load.py:682; eddn.py:1133; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Skicka system och scan-data till Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:683; load.py:692; eddn.py:1144; */
|
||||
"Delay sending until docked" = "Skicka bara uppdateringar till EDDN när du är dockad";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:197; load.py:197; edsm.py:237; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Skicka flight log-data och Cmdr-status till EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous Star Map användaruppgifter";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "CMDR namn";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "API Nyckel";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Ingen";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Fel: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Fel: Kan inte ansluta till EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:215; load.py:215; inara.py:222; */
|
||||
"Send flight log and Cmdr status to Inara" = "Skicka flight log-data och Cmdr-status till Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:225; load.py:225; inara.py:234; */
|
||||
"Inara credentials" = "Inara autentiseringsuppgifter";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1316; inara.py:1328; load.py:1319; load.py:1331; inara.py:1587; inara.py:1600; */
|
||||
"Error: Inara {MSG}" = "Fel: Inara {MSG}";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Kopiera";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Uppdatera";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Alltid överst";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Roll";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Skepp";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "System";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Station";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "Fil";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Ändra";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "View";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Fönster";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Hjälp";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "Om {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Sök efter uppdateringar...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Lagra rådata...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Integritetspolicy";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Versionsinformation";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Inställningar";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Avsluta";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Dokumentation";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Loggar in...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "Autentisering lyckad";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = "Du är inte dockad vid en station!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "Stationen är tom!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "Stationen har ingen marknad!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Hämtar data...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Vem är du? (felmeddelande)";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Vart är du? (felmeddelande)";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "Okänt skepp? (felmeddelande)";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Senaste uppdatering: %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */
|
||||
"Fighter" = "Fighter";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */
|
||||
"Gunner" = "Gunner";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */
|
||||
"Helm" = "Helm";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "Vänta {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2008:2014; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "En eller flera aktiverade plugins har inte stöd för Python 3.x. Var vänlig kontrollera listan med plugins under fliken '{PLUGINS}' under '{FILE}' > '{SETTINGS}'. Kontrollera om det finns en nyare version tillgänglig eller informera utvecklaren.\n\nDu kan också avaktivera din plugin genom att ändra slutet av namnet på mappen till '{DISABLED}'";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */
|
||||
"Plugins" = "Plugins";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2029; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Plugins utan stöd för Python 3.x";
|
||||
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:237; */
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:245; */
|
||||
"Error: Frontier server is lagging" = "Fel: Frontier lag på server";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Fel: ogiltligt användarnamn eller lösenord";
|
||||
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:288; */
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:296; */
|
||||
"Error: Wrong Cmdr" = "Fel: Fel användare. Har du flera konton eller en gammal API-nyckel från ett nollställt konto?";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Uppdatera";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Alltid överst";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Cmdr";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Roll";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Skepp";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "System";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Station";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "Fil";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Ändra";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "View";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Fönster";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Hjälp";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "Om {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Sök efter uppdateringar...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Lagra rådata...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "Status";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Dokumentation";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Integritetspolicy";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Versionsinformation";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Inställningar";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Avsluta";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Kopiera";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Loggar in...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "Autentisering lyckad";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = "Du är inte dockad vid en station!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "Stationen är tom!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "Stationen har ingen marknad!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Hämtar data...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Vem är du? (felmeddelande)";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Vart är du? (felmeddelande)";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "Okänt skepp? (felmeddelande)";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Senaste uppdatering: %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */
|
||||
"Fighter" = "Fighter";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */
|
||||
"Gunner" = "Gunner";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */
|
||||
"Helm" = "Helm";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "Vänta {SS}s";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "OK";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2253:2259; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "En eller flera aktiverade plugins har inte stöd för Python 3.x. Var vänlig kontrollera listan med plugins under fliken '{PLUGINS}' under '{FILE}' > '{SETTINGS}'. Kontrollera om det finns en nyare version tillgänglig eller informera utvecklaren.\n\nDu kan också avaktivera din plugin genom att ändra slutet av namnet på mappen till '{DISABLED}'";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */
|
||||
"Plugins" = "Plugins";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2274; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Plugins utan stöd för Python 3.x";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Standard";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Fel: Kan inte ansluta till EDDN";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Skicka stationsdata till Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:2052; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Skicka system och scan-data till Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:2063; */
|
||||
"Delay sending until docked" = "Skicka bara uppdateringar till EDDN när du är dockad";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Skickar data till EDDN...";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Skicka flight log-data och Cmdr-status till EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "Elite Dangerous Star Map användaruppgifter";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "CMDR namn";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "API Nyckel";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Ingen";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Fel: EDSM {MSG}";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Fel: Kan inte ansluta till EDSM";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */
|
||||
"Send flight log and Cmdr status to Inara" = "Skicka flight log-data och Cmdr-status till Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */
|
||||
"Inara credentials" = "Inara autentiseringsuppgifter";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1650; inara.py:1663; */
|
||||
"Error: Inara {MSG}" = "Fel: Inara {MSG}";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Inställningar";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Välj vilket data som skall lagras";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Marknadsdata i CSV-formaterad fil";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Marknadsdata i Trade Dangerous-formaterad fil";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Översikt av skepp";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:383; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:370; */
|
||||
"Automatically update on docking" = "Automatisk uppdatering vid dockning";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Filsökväg";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Ändra...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Bläddra...";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Exportdata";
|
||||
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:444; prefs.py:459; */
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:431; prefs.py:446; */
|
||||
"E:D journal file location" = "E:D journal-fil sökväg";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Genväg, tangentbord";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Snabbkommando";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "Starta om {APP} för att använda genvägar";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} behöver rättigheter för att använda genvägar";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Öppna systeminställningar";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Bara när: Elite Dangerous är det aktiva programmet";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Spela ljud";
|
||||
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:557; */
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:564; */
|
||||
"Disable Automatic Application Updates Check when in-game" = "Leta inte efter programuppdateringar när spelet körs";
|
||||
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:570; */
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:577; */
|
||||
"Preferred websites" = "Föredragna webbsidor";
|
||||
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:581; */
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:588; */
|
||||
"Shipyard" = "Översikt av skepp";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Konfiguration";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:709; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:716; */
|
||||
"Normal text" = "Normal text";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:711; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:718; */
|
||||
"Highlighted text" = "Markerad text";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Språk";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Tema";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Mörk";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Transparent";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Utseende";
|
||||
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:900; */
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */
|
||||
"Plugins folder" = "Mapp för plugins";
|
||||
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:907; */
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */
|
||||
"Open" = "Öppna";
|
||||
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:915; */
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:923; */
|
||||
"Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name" = "Tips: du kan avaktivera en plugin genom{CR}att lägga till '{EXT}' på slutet av mappens namn";
|
||||
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:926; */
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:934; */
|
||||
"Enabled Plugins" = "Aktiverade plugins";
|
||||
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:954; */
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:962; */
|
||||
"Information on migrating plugins" = "Information om migrering av plugins";
|
||||
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:969; */
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:977; */
|
||||
"Disabled Plugins" = "Avaktiverade plugins";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Balance";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Lån";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Elite";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Combat";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Trade";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Explorer";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "CQC";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Federation";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Empire";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Powerplay";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Mostly Harmless";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Novice";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Competent";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Expert";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Master";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Dangerous";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Deadly";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Mostly Penniless";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Peddler";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Dealer";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Merchant";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Broker";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Entrepreneur";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Tycoon";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Mostly Aimless";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Scout";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Surveyor";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Trailblazer";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Pathfinder";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Ranger";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Pioneer";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Mostly Helpless";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Amatör";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Semi Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Professional";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Champion";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Hero";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Gladiator";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Recruit";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Cadet";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Midshipman";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Chief Petty Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Warrant Officer";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Ensign";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "Lieutenant";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Lieutenant Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Post Commander";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Post Captain";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "Rear Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Vice Admiral";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Admiral";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Outsider";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Serf";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Squire";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Knight";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Lord";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Baron";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Viscount";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Count";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Earl";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Marquis";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Duke";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Prince";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "King";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Rating 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Rating 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Rating 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Rating 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Rating 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Värde";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Skepp";
|
||||
+317
-317
@@ -1,575 +1,575 @@
|
||||
/* Language name */
|
||||
"!Language" = "Українська";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:212; eddn.py:584; eddn.py:925; load.py:215; load.py:593; load.py:940; eddn.py:252; eddn.py:699; eddn.py:1439; */
|
||||
"Sending data to EDDN..." = "Відправка даних до EDDN...";
|
||||
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:257; eddn.py:864; eddn.py:898; eddn.py:937; load.py:260; load.py:878; load.py:913; load.py:952; eddn.py:316; eddn.py:1375; eddn.py:1410; eddn.py:1451; */
|
||||
"Error: Can't connect to EDDN" = "Помилка: Немає зв'язку з EDDN!";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:663; load.py:672; eddn.py:1122; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Надсилати дані станцій до Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:673; load.py:682; eddn.py:1133; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Відправляти систему і результати сканування в Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:683; load.py:692; eddn.py:1144; */
|
||||
"Delay sending until docked" = "Відкласти відправку даних до стикування";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:197; load.py:197; edsm.py:237; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Відправляти дані бортового журналу до EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:206; load.py:206; edsm.py:247; */
|
||||
"Elite Dangerous Star Map credentials" = "Дані Elite Dangerous Star Map";
|
||||
|
||||
/* edsm.py: Game Commander name label in EDSM settings; theme.py: Label for commander name in main window; EDMarketConnector.py: Label for commander name in main window; stats.py: Cmdr stats; In files: edsm.py:216; load.py:216; edsm.py:258; theme.py:227; EDMarketConnector.py:822; stats.py:59; */
|
||||
"Cmdr" = "Км-др";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */
|
||||
"Commander Name" = "Ім`я пілота";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:230; inara.py:233; load.py:230; load.py:233; edsm.py:274; inara.py:243; */
|
||||
"API Key" = "API Ключ";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:256; load.py:256; edsm.py:301; prefs.py:520; prefs.py:1174; prefs.py:1207; stats.py:156; stats.py:175; stats.py:194; stats.py:211; */
|
||||
"None" = "Нічого";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:622; edsm.py:724; load.py:627; load.py:729; edsm.py:747; edsm.py:875; */
|
||||
"Error: EDSM {MSG}" = "Помилка: EDSM {MSG}!";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:658; edsm.py:720; load.py:663; load.py:725; edsm.py:784; edsm.py:870; */
|
||||
"Error: Can't connect to EDSM" = "Помилка: Немає з`єднання з EDSM!";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:215; load.py:215; inara.py:222; */
|
||||
"Send flight log and Cmdr status to Inara" = "Відправляти дані бортового журналу до Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:225; load.py:225; inara.py:234; */
|
||||
"Inara credentials" = "Обліковий запис Inara";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1316; inara.py:1328; load.py:1319; load.py:1331; inara.py:1587; inara.py:1600; */
|
||||
"Error: Inara {MSG}" = "Помилка: Inara {MSG}";
|
||||
|
||||
/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: test_ast_stuff.py:2; EDMarketConnector.py:1047; */
|
||||
"CAPI: No commander data returned" = "CAPI: Не отримано данних пілота";
|
||||
|
||||
/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */
|
||||
"Journal directory already locked" = "Каталог журналу вже заблокований";
|
||||
|
||||
/* journal_lock.py: Text for when newly selected Journal directory is already locked; In files: journal_lock.py:223:224; */
|
||||
"The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this." = "Нове розташування каталогу журналів уже заблоковано. {CR} Ви можете спробувати вирішити це, а потім повторити спробу, або Ігнорувати це.";
|
||||
|
||||
/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */
|
||||
"Retry" = "Повторна спроба";
|
||||
|
||||
/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */
|
||||
"Ignore" = "Ігнорувати";
|
||||
|
||||
/* ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; In files: ttkHyperlinkLabel.py:42; EDMarketConnector.py:866; */
|
||||
"Copy" = "Копіювати";
|
||||
|
||||
/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */
|
||||
"Update" = "Оновлення";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:612; prefs.py:867; */
|
||||
"Always on top" = "Поверх інших вікон";
|
||||
|
||||
/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */
|
||||
"Unknown" = "Невідомо";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:824; EDMarketConnector.py:1279; */
|
||||
"Role" = "Посада";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:824; EDMarketConnector.py:1289; EDMarketConnector.py:1312; stats.py:409; */
|
||||
"Ship" = "Корабель";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */
|
||||
"Suit" = "Костюм";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:826; prefs.py:607; stats.py:411; */
|
||||
"System" = "Система";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:827; prefs.py:625; prefs.py:762; stats.py:412; */
|
||||
"Station" = "Станція";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:830; EDMarketConnector.py:845; EDMarketConnector.py:848; EDMarketConnector.py:2019; */
|
||||
"File" = "Файл";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */
|
||||
"Edit" = "Редагувати";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */
|
||||
"View" = "Вид";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */
|
||||
"Window" = "Вікно";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */
|
||||
"Help" = "Довідка";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:837; EDMarketConnector.py:863; EDMarketConnector.py:1566; */
|
||||
"About {APP}" = "Про {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */
|
||||
"Check for Updates..." = "Перевірка оновлень...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */
|
||||
"Save Raw Data..." = "Зберегти необроблені дані...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */
|
||||
"Status" = "Статус";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */
|
||||
"Privacy Policy" = "Політика конфіденційності";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */
|
||||
"Release Notes" = "Інформація про реліз";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */
|
||||
"Settings" = "Налаштування";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */
|
||||
"Exit" = "Вихід";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */
|
||||
"Documentation" = "Документація";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */
|
||||
"Logging in..." = "Вхід в...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */
|
||||
"Authentication successful" = "Автентифікацію пройдено успішно";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:919; */
|
||||
"You're not docked at a station!" = "Ви не стиковані з станцією!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:927; */
|
||||
"Station doesn't have anything!" = "На станції немає нічого!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */
|
||||
"Station doesn't have a market!" = "На станції немає ринку!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */
|
||||
"Fetching data..." = "Отримання даних...";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1051; stats.py:335; */
|
||||
"Who are you?!" = "Хто ти?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1057; stats.py:345; */
|
||||
"Where are you?!" = "Де ми?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1064; stats.py:353; */
|
||||
"What are you flying?!" = "На чому летимо?!";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */
|
||||
"Last updated at %H:%M:%S" = "Останнє оновлення було %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */
|
||||
"Fighter" = "Винищувач";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */
|
||||
"Gunner" = "Стрілець";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */
|
||||
"Helm" = "Керівник";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */
|
||||
"cooldown {SS}s" = "очікування {SS} сек";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1626; prefs.py:306; */
|
||||
"OK" = "Згода";
|
||||
|
||||
/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1693; */
|
||||
"Shutting down..." = "Закриття...";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2008:2014; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Один або кілька увімкнених плагінів ще не підтримують Python 3.x. Перегляньте список на вкладці '{PLUGINS}' в '{FILE}' > '{SETTINGS}'. Ви повинні перевірити, чи є в наявності оновлена версія, інакше повідомити розробника плагіну про те, що їм потрібно оновити код для Python 3.x.\n\nВи можете відключити плагін, перейменувавши його папку додавши '{DISABLED}' в кінці назви.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */
|
||||
"Plugins" = "Плагіни";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2029; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Плагіни без підтримки Python 3.x!";
|
||||
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:237; */
|
||||
/* companion.py: Frontier CAPI data doesn't agree with latest Journal game location; In files: companion.py:245; */
|
||||
"Error: Frontier server is lagging" = "Помилка: З`єднання з сервером гри з затримками!";
|
||||
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:263; */
|
||||
/* companion.py: Generic "something went wrong with Frontier Auth" error; In files: companion.py:271; */
|
||||
"Error: Invalid Credentials" = "Помилка: Невірні облікові дані!";
|
||||
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:288; */
|
||||
/* companion.py: Frontier CAPI authorisation not for currently game-active commander; In files: companion.py:296; */
|
||||
"Error: Wrong Cmdr" = "Помилка! Не той обліковий запис!";
|
||||
|
||||
/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:414; companion.py:499; */
|
||||
/* companion.py: Generic error prefix - following text is from Frontier auth service; In files: companion.py:432; companion.py:517; */
|
||||
"Error" = "Помилка";
|
||||
|
||||
/* companion.py: Frontier auth, no 'usr' section in returned data; companion.py: Frontier auth, no 'customer_id' in 'usr' section in returned data; In files: companion.py:457; companion.py:462; */
|
||||
/* companion.py: Frontier auth, no 'usr' section in returned data; companion.py: Frontier auth, no 'customer_id' in 'usr' section in returned data; In files: companion.py:475; companion.py:480; */
|
||||
"Error: Couldn't check token customer_id" = "Помилка: Не вдалося перевірити токен customer_id";
|
||||
|
||||
/* companion.py: Frontier auth customer_id doesn't match game session FID; In files: companion.py:468; */
|
||||
/* companion.py: Frontier auth customer_id doesn't match game session FID; In files: companion.py:486; */
|
||||
"Error: customer_id doesn't match!" = "Error: customer_id не співпадає!";
|
||||
|
||||
/* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:490; */
|
||||
/* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:508; */
|
||||
"Error: unable to get token" = "Помилка: не вдалося отримати токен";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:194; prefs.py:468; prefs.py:702; prefs.py:735; */
|
||||
/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1748; */
|
||||
"Update" = "Оновлення";
|
||||
|
||||
/* EDMarketConnector.py: Appearance - Label for checkbox to select if application always on top; prefs.py: Appearance - Label for checkbox to select if application always on top; In files: EDMarketConnector.py:710; prefs.py:875; */
|
||||
"Always on top" = "Поверх інших вікон";
|
||||
|
||||
/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */
|
||||
"Unknown" = "Невідомо";
|
||||
|
||||
/* EDMarketConnector.py: Label for commander name in main window; edsm.py: Game Commander name label in EDSM settings; stats.py: Cmdr stats; theme.py: Label for commander name in main window; In files: EDMarketConnector.py:913; edsm.py:332; stats.py:57; theme.py:290; */
|
||||
"Cmdr" = "Км-др";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: Multicrew role label in main window; In files: EDMarketConnector.py:915; EDMarketConnector.py:1487; */
|
||||
"Role" = "Посада";
|
||||
|
||||
/* EDMarketConnector.py: 'Ship' or multi-crew role label in main window, as applicable; EDMarketConnector.py: 'Ship' label in main UI; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:915; EDMarketConnector.py:1497; EDMarketConnector.py:1520; stats.py:405; */
|
||||
"Ship" = "Корабель";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */
|
||||
"Suit" = "Костюм";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'System' line in main UI; prefs.py: Configuration - Label for selection of 'System' provider website; stats.py: Main window; In files: EDMarketConnector.py:917; prefs.py:614; stats.py:407; */
|
||||
"System" = "Система";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Station' line in main UI; prefs.py: Configuration - Label for selection of 'Station' provider website; prefs.py: Appearance - Example 'Normal' text; stats.py: Status dialog subtitle; In files: EDMarketConnector.py:918; prefs.py:632; prefs.py:770; stats.py:408; */
|
||||
"Station" = "Станція";
|
||||
|
||||
/* EDMarketConnector.py: 'File' menu title on OSX; EDMarketConnector.py: 'File' menu title; EDMarketConnector.py: 'File' menu; In files: EDMarketConnector.py:921; EDMarketConnector.py:939; EDMarketConnector.py:942; EDMarketConnector.py:2264; */
|
||||
"File" = "Файл";
|
||||
|
||||
/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */
|
||||
"Edit" = "Редагувати";
|
||||
|
||||
/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */
|
||||
"View" = "Вид";
|
||||
|
||||
/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */
|
||||
"Window" = "Вікно";
|
||||
|
||||
/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */
|
||||
"Help" = "Довідка";
|
||||
|
||||
/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1804; */
|
||||
"About {APP}" = "Про {APP}";
|
||||
|
||||
/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */
|
||||
"Check for Updates..." = "Перевірка оновлень...";
|
||||
|
||||
/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */
|
||||
"Save Raw Data..." = "Зберегти необроблені дані...";
|
||||
|
||||
/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */
|
||||
"Status" = "Статус";
|
||||
|
||||
/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */
|
||||
"Documentation" = "Документація";
|
||||
|
||||
/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */
|
||||
"Privacy Policy" = "Політика конфіденційності";
|
||||
|
||||
/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */
|
||||
"Release Notes" = "Інформація про реліз";
|
||||
|
||||
/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */
|
||||
"Settings" = "Налаштування";
|
||||
|
||||
/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */
|
||||
"Exit" = "Вихід";
|
||||
|
||||
/* EDMarketConnector.py: Label for 'Copy' as in 'Copy and Paste'; ttkHyperlinkLabel.py: Label for 'Copy' as in 'Copy and Paste'; In files: EDMarketConnector.py:962; ttkHyperlinkLabel.py:53; */
|
||||
"Copy" = "Копіювати";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */
|
||||
"Logging in..." = "Вхід в...";
|
||||
|
||||
/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */
|
||||
"Authentication successful" = "Автентифікацію пройдено успішно";
|
||||
|
||||
/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1025; */
|
||||
"You're not docked at a station!" = "Ви не стиковані з станцією!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Either no market or no modules data for station from Frontier CAPI; In files: EDMarketConnector.py:1033; */
|
||||
"Station doesn't have anything!" = "На станції немає нічого!";
|
||||
|
||||
/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */
|
||||
"Station doesn't have a market!" = "На станції немає ринку!";
|
||||
|
||||
/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */
|
||||
"Fetching data..." = "Отримання даних...";
|
||||
|
||||
/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */
|
||||
"CAPI: No commander data returned" = "CAPI: Не отримано данних пілота";
|
||||
|
||||
/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1246; stats.py:333; */
|
||||
"Who are you?!" = "Хто ти?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1252; stats.py:341; */
|
||||
"Where are you?!" = "Де ми?!";
|
||||
|
||||
/* EDMarketConnector.py: We don't know what ship the commander is in, when we should; stats.py: Unknown ship; In files: EDMarketConnector.py:1259; stats.py:349; */
|
||||
"What are you flying?!" = "На чому летимо?!";
|
||||
|
||||
/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */
|
||||
"Last updated at %H:%M:%S" = "Останнє оновлення було %H:%M:%S";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */
|
||||
"Fighter" = "Винищувач";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */
|
||||
"Gunner" = "Стрілець";
|
||||
|
||||
/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */
|
||||
"Helm" = "Керівник";
|
||||
|
||||
/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */
|
||||
"cooldown {SS}s" = "очікування {SS} сек";
|
||||
|
||||
/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1864; prefs.py:292; */
|
||||
"OK" = "Згода";
|
||||
|
||||
/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1936; */
|
||||
"Shutting down..." = "Закриття...";
|
||||
|
||||
/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2253:2259; */
|
||||
"One or more of your enabled plugins do not yet have support for Python 3.x. Please see the list on the '{PLUGINS}' tab of '{FILE}' > '{SETTINGS}'. You should check if there is an updated version available, else alert the developer that they need to update the code for Python 3.x.\r\n\r\nYou can disable a plugin by renaming its folder to have '{DISABLED}' on the end of the name." = "Один або кілька увімкнених плагінів ще не підтримують Python 3.x. Перегляньте список на вкладці '{PLUGINS}' в '{FILE}' > '{SETTINGS}'. Ви повинні перевірити, чи є в наявності оновлена версія, інакше повідомити розробника плагіну про те, що їм потрібно оновити код для Python 3.x.\n\nВи можете відключити плагін, перейменувавши його папку додавши '{DISABLED}' в кінці назви.";
|
||||
|
||||
/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */
|
||||
"Plugins" = "Плагіни";
|
||||
|
||||
/* EDMarketConnector.py: Popup window title for list of 'enabled' plugins that don't work with Python 3.x; In files: EDMarketConnector.py:2274; */
|
||||
"EDMC: Plugins Without Python 3.x Support" = "EDMC: Плагіни без підтримки Python 3.x!";
|
||||
|
||||
/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:208; */
|
||||
"Journal directory already locked" = "Каталог журналу вже заблокований";
|
||||
|
||||
/* journal_lock.py: Text for when newly selected Journal directory is already locked; In files: journal_lock.py:225:226; */
|
||||
"The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this." = "Нове розташування каталогу журналів уже заблоковано. {CR} Ви можете спробувати вирішити це, а потім повторити спробу, або Ігнорувати це.";
|
||||
|
||||
/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */
|
||||
"Retry" = "Повторна спроба";
|
||||
|
||||
/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */
|
||||
"Ignore" = "Ігнорувати";
|
||||
|
||||
/* l10n.py: The system default language choice in Settings > Appearance; prefs.py: Settings > Configuration - Label on 'reset journal files location to default' button; prefs.py: The system default language choice in Settings > Appearance; prefs.py: Label for 'Default' theme radio button; In files: l10n.py:193; prefs.py:455; prefs.py:709; prefs.py:742; */
|
||||
"Default" = "Стандартне налаштування";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:251; */
|
||||
/* eddn.py: Error while trying to send data to EDDN; In files: eddn.py:458; eddn.py:2413; eddn.py:2451; eddn.py:2519; */
|
||||
"Error: Can't connect to EDDN" = "Помилка: Немає зв'язку з EDDN!";
|
||||
|
||||
/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */
|
||||
"Send station data to the Elite Dangerous Data Network" = "Надсилати дані станцій до Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: Enable EDDN support for system and other scan data checkbox label; In files: eddn.py:2052; */
|
||||
"Send system and scan data to the Elite Dangerous Data Network" = "Відправляти систему і результати сканування в Elite Dangerous Data Network";
|
||||
|
||||
/* eddn.py: EDDN delay sending until docked option is on, this message notes that a send was skipped due to this; In files: eddn.py:2063; */
|
||||
"Delay sending until docked" = "Відкласти відправку даних до стикування";
|
||||
|
||||
/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */
|
||||
"Sending data to EDDN..." = "Відправка даних до EDDN...";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */
|
||||
"Send flight log and Cmdr status to EDSM" = "Відправляти дані бортового журналу до EDSM";
|
||||
|
||||
/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */
|
||||
"Elite Dangerous Star Map credentials" = "Дані Elite Dangerous Star Map";
|
||||
|
||||
/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */
|
||||
"Commander Name" = "Ім`я пілота";
|
||||
|
||||
/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */
|
||||
"API Key" = "API Ключ";
|
||||
|
||||
/* edsm.py: We have no data on the current commander; prefs.py: No hotkey/shortcut set; stats.py: No rank; In files: edsm.py:394; prefs.py:527; prefs.py:1157; prefs.py:1190; stats.py:154; stats.py:173; stats.py:192; stats.py:209; */
|
||||
"None" = "Нічого";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */
|
||||
"Error: EDSM {MSG}" = "Помилка: EDSM {MSG}!";
|
||||
|
||||
/* edsm.py: EDSM Plugin - Error connecting to EDSM API; In files: edsm.py:953; edsm.py:1043; */
|
||||
"Error: Can't connect to EDSM" = "Помилка: Немає з`єднання з EDSM!";
|
||||
|
||||
/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */
|
||||
"Send flight log and Cmdr status to Inara" = "Відправляти дані бортового журналу до Inara";
|
||||
|
||||
/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */
|
||||
"Inara credentials" = "Обліковий запис Inara";
|
||||
|
||||
/* inara.py: INARA API returned some kind of error (error message will be contained in {MSG}); In files: inara.py:1650; inara.py:1663; */
|
||||
"Error: Inara {MSG}" = "Помилка: Inara {MSG}";
|
||||
|
||||
/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */
|
||||
"Preferences" = "Уподобання";
|
||||
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:348; */
|
||||
/* prefs.py: Settings > Output - choosing what data to save to files; In files: prefs.py:335; */
|
||||
"Please choose what data to save" = "Оберіть дані які буде збережено";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:354; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:341; */
|
||||
"Market data in CSV format file" = "Ринкові дані у форматі CSV файлу";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:363; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:350; */
|
||||
"Market data in Trade Dangerous format file" = "Ринкові дані у форматі Trade Dangerous файлу";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:373; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:360; */
|
||||
"Ship loadout" = "Технічні дані корабля";
|
||||
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:383; */
|
||||
/* prefs.py: Settings > Output option; In files: prefs.py:370; */
|
||||
"Automatically update on docking" = "Автоматичне оновлювання при стикуванні зі станцією";
|
||||
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:392; prefs.py:411; */
|
||||
/* prefs.py: Settings > Output - Label for "where files are located"; In files: prefs.py:379; prefs.py:398; */
|
||||
"File location" = "Розташування файлу";
|
||||
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:400; prefs.py:450; */
|
||||
/* prefs.py: macOS Preferences - files location selection button; In files: prefs.py:387; prefs.py:437; */
|
||||
"Change..." = "Внесення змін...";
|
||||
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:403; prefs.py:453; */
|
||||
/* prefs.py: NOT-macOS Settings - files location selection button; prefs.py: NOT-macOS Setting - files location selection button; In files: prefs.py:390; prefs.py:440; */
|
||||
"Browse..." = "Перегляд...";
|
||||
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:418; */
|
||||
/* prefs.py: Label for 'Output' Settings/Preferences tab; In files: prefs.py:405; */
|
||||
"Output" = "Вивід";
|
||||
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:444; prefs.py:459; */
|
||||
/* prefs.py: Settings > Configuration - Label for Journal files location; In files: prefs.py:431; prefs.py:446; */
|
||||
"E:D journal file location" = "Розташування файлу-журналу E:D";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */
|
||||
"Keyboard shortcut" = "Сполучення клавіш";
|
||||
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:486; */
|
||||
/* prefs.py: Hotkey/Shortcut settings prompt on Windows; In files: prefs.py:492; */
|
||||
"Hotkey" = "Гаряча клавіша";
|
||||
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:495; */
|
||||
/* prefs.py: macOS Preferences > Configuration - restart the app message; In files: prefs.py:501; */
|
||||
"Re-start {APP} to use shortcuts" = "Перезавантажте {APP} для використання ярликів";
|
||||
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:504; */
|
||||
/* prefs.py: macOS - Configuration - need to grant the app permission for keyboard shortcuts; In files: prefs.py:510; */
|
||||
"{APP} needs permission to use shortcuts" = "{APP} необхідні дозволи для використання ярликів";
|
||||
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:509; */
|
||||
/* prefs.py: Shortcut settings button on OSX; In files: prefs.py:515; */
|
||||
"Open System Preferences" = "Відкрити налаштування системи";
|
||||
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:531; */
|
||||
/* prefs.py: Configuration - Act on hotkey only when ED is in foreground; In files: prefs.py:538; */
|
||||
"Only when Elite: Dangerous is the active app" = "Тільки тоді, коли Elite: Dangerous є активним додатком";
|
||||
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:542; */
|
||||
/* prefs.py: Configuration - play sound when hotkey used; In files: prefs.py:549; */
|
||||
"Play sound" = "Грати звук";
|
||||
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:557; */
|
||||
/* prefs.py: Configuration - disable checks for app updates when in-game; In files: prefs.py:564; */
|
||||
"Disable Automatic Application Updates Check when in-game" = "Вимкнути автоматичні перевірки оновлення додатку, коли в грі";
|
||||
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:570; */
|
||||
/* prefs.py: Label for preferred shipyard, system and station 'providers'; In files: prefs.py:577; */
|
||||
"Preferred websites" = "Обрані веб-сайти";
|
||||
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:581; */
|
||||
/* prefs.py: Label for Shipyard provider selection; In files: prefs.py:588; */
|
||||
"Shipyard" = "Корабельна верф";
|
||||
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:593; */
|
||||
/* prefs.py: Label for checkbox to utilise alternative Coriolis URL method; In files: prefs.py:600; */
|
||||
"Use alternate URL method" = "Використовувати альтернативний URL-метод";
|
||||
|
||||
/* prefs.py: Configuration - Label for selection of Log Level; In files: prefs.py:646; */
|
||||
/* prefs.py: Configuration - Label for selection of Log Level; In files: prefs.py:653; */
|
||||
"Log Level" = "Рівень подробиць журналу";
|
||||
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:674; */
|
||||
/* prefs.py: Label for 'Configuration' tab in Settings; In files: prefs.py:681; */
|
||||
"Configuration" = "Конфігурація";
|
||||
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */
|
||||
/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */
|
||||
"Privacy" = "Конфіденційність";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:709; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'normal' text colour; In files: prefs.py:716; */
|
||||
"Normal text" = "Нормальний текст";
|
||||
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:711; */
|
||||
/* prefs.py: Label for Settings > Appeareance > selection of 'highlightes' text colour; In files: prefs.py:718; */
|
||||
"Highlighted text" = "Виділений текст";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:720; */
|
||||
/* prefs.py: Appearance - Label for selection of application display language; In files: prefs.py:727; */
|
||||
"Language" = "Мова";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:730; */
|
||||
/* prefs.py: Label for Settings > Appearance > Theme selection; In files: prefs.py:737; */
|
||||
"Theme" = "Тема";
|
||||
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:741; */
|
||||
/* prefs.py: Label for 'Dark' theme radio button; In files: prefs.py:749; */
|
||||
"Dark" = "Темний";
|
||||
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:748; */
|
||||
/* prefs.py: Label for 'Transparent' theme radio button; In files: prefs.py:756; */
|
||||
"Transparent" = "Прозора";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of UI scaling; In files: prefs.py:794; */
|
||||
/* prefs.py: Appearance - Label for selection of UI scaling; In files: prefs.py:802; */
|
||||
"UI Scale Percentage" = "Відсоток шкали інтерфейсу користувача";
|
||||
|
||||
/* prefs.py: Appearance - Help/hint text for UI scaling selection; In files: prefs.py:815; */
|
||||
/* prefs.py: Appearance - Help/hint text for UI scaling selection; In files: prefs.py:823; */
|
||||
"100 means Default{CR}Restart Required for{CR}changes to take effect!" = "100 означає, що {CR} потрібно перезапустити за замовчуванням, щоб зміни вступили в силу {CR}!";
|
||||
|
||||
/* prefs.py: Appearance - Label for selection of main window transparency; In files: prefs.py:825; */
|
||||
/* prefs.py: Appearance - Label for selection of main window transparency; In files: prefs.py:833; */
|
||||
"Main window transparency" = "Прозорість головного вікна";
|
||||
|
||||
/* prefs.py: Appearance - Help/hint text for Main window transparency selection; In files: prefs.py:845:848; */
|
||||
/* prefs.py: Appearance - Help/hint text for Main window transparency selection; In files: prefs.py:853:856; */
|
||||
"100 means fully opaque.{CR}Window is updated in real time" = "100 означає повністю непрозоре. {CR} Вікно буде оновлюватись в режимі реального часу";
|
||||
|
||||
/* prefs.py: Appearance option for Windows "minimize to system tray"; In files: prefs.py:877; */
|
||||
/* prefs.py: Appearance option for Windows "minimize to system tray"; In files: prefs.py:885; */
|
||||
"Minimize to system tray" = "Згорнути програму";
|
||||
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:885; */
|
||||
/* prefs.py: Label for Settings > Appearance tab; In files: prefs.py:893; */
|
||||
"Appearance" = "Зовнішній вигляд";
|
||||
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:900; */
|
||||
/* prefs.py: Label for location of third-party plugins folder; In files: prefs.py:908; */
|
||||
"Plugins folder" = "Сховище плагінів";
|
||||
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:907; */
|
||||
/* prefs.py: Label on button used to open a filesystem folder; In files: prefs.py:915; */
|
||||
"Open" = "Відкрити";
|
||||
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:915; */
|
||||
/* prefs.py: Tip/label about how to disable plugins; In files: prefs.py:923; */
|
||||
"Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name" = "Підказка: Ви можете відключити плагін через {CR} додання '{EXT}' до назви папки";
|
||||
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:926; */
|
||||
/* prefs.py: Label on list of enabled plugins; In files: prefs.py:934; */
|
||||
"Enabled Plugins" = "Увімкнені плагіни";
|
||||
|
||||
/* prefs.py: Plugins - Label for list of 'enabled' plugins that don't work with Python 3.x; In files: prefs.py:946; */
|
||||
/* prefs.py: Plugins - Label for list of 'enabled' plugins that don't work with Python 3.x; In files: prefs.py:954; */
|
||||
"Plugins Without Python 3.x Support:" = "Плагіни без підтримки Python 3.x:";
|
||||
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:954; */
|
||||
/* prefs.py: Plugins - Label on URL to documentation about migrating plugins from Python 2.7; In files: prefs.py:962; */
|
||||
"Information on migrating plugins" = "Інформація про міграцію плагінів";
|
||||
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:969; */
|
||||
/* prefs.py: Lable on list of user-disabled plugins; In files: prefs.py:977; */
|
||||
"Disabled Plugins" = "Вимкнені плагіни";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:60; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:58; */
|
||||
"Balance" = "Баланс";
|
||||
|
||||
/* stats.py: Cmdr stats; In files: stats.py:61; */
|
||||
/* stats.py: Cmdr stats; In files: stats.py:59; */
|
||||
"Loan" = "Борг";
|
||||
|
||||
/* stats.py: Top rank; In files: stats.py:65; */
|
||||
/* stats.py: Top rank; In files: stats.py:63; */
|
||||
"Elite" = "Еліта";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
/* stats.py: Ranking; In files: stats.py:74; */
|
||||
"Combat" = "Бойовий";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:77; */
|
||||
/* stats.py: Ranking; In files: stats.py:75; */
|
||||
"Trade" = "Торговий";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:78; */
|
||||
/* stats.py: Ranking; In files: stats.py:76; */
|
||||
"Explorer" = "Дослідницький";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
/* stats.py: Ranking; In files: stats.py:79; */
|
||||
"CQC" = "Близький бій (CQC)";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
/* stats.py: Ranking; In files: stats.py:80; */
|
||||
"Federation" = "Федерація";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:83; */
|
||||
/* stats.py: Ranking; In files: stats.py:81; */
|
||||
"Empire" = "Імперія";
|
||||
|
||||
/* stats.py: Ranking; In files: stats.py:84; */
|
||||
/* stats.py: Ranking; In files: stats.py:82; */
|
||||
"Powerplay" = "Змагання";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
/* stats.py: Combat rank; In files: stats.py:91; */
|
||||
"Harmless" = "Безпечний";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
/* stats.py: Combat rank; In files: stats.py:92; */
|
||||
"Mostly Harmless" = "Здебільшого Безпечний";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
/* stats.py: Combat rank; In files: stats.py:93; */
|
||||
"Novice" = "Новачок";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:96; */
|
||||
/* stats.py: Combat rank; In files: stats.py:94; */
|
||||
"Competent" = "Компетентний";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
/* stats.py: Combat rank; In files: stats.py:95; */
|
||||
"Expert" = "Експерт";
|
||||
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:98; stats.py:178; */
|
||||
/* stats.py: Combat rank; stats.py: Empire rank; In files: stats.py:96; stats.py:176; */
|
||||
"Master" = "Майстер";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:99; */
|
||||
/* stats.py: Combat rank; In files: stats.py:97; */
|
||||
"Dangerous" = "Небезпечний";
|
||||
|
||||
/* stats.py: Combat rank; In files: stats.py:100; */
|
||||
/* stats.py: Combat rank; In files: stats.py:98; */
|
||||
"Deadly" = "Убивчий";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
/* stats.py: Trade rank; In files: stats.py:101; */
|
||||
"Penniless" = "Злидень";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
/* stats.py: Trade rank; In files: stats.py:102; */
|
||||
"Mostly Penniless" = "Здебільшого Нужденний";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
/* stats.py: Trade rank; In files: stats.py:103; */
|
||||
"Peddler" = "Штовхач";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
/* stats.py: Trade rank; In files: stats.py:104; */
|
||||
"Dealer" = "Дилер";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
/* stats.py: Trade rank; In files: stats.py:105; */
|
||||
"Merchant" = "Торговець";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
/* stats.py: Trade rank; In files: stats.py:106; */
|
||||
"Broker" = "Брокер";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:109; */
|
||||
/* stats.py: Trade rank; In files: stats.py:107; */
|
||||
"Entrepreneur" = "Підприємець";
|
||||
|
||||
/* stats.py: Trade rank; In files: stats.py:110; */
|
||||
/* stats.py: Trade rank; In files: stats.py:108; */
|
||||
"Tycoon" = "Магнат";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:111; */
|
||||
"Aimless" = "Безцільний";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:112; */
|
||||
"Mostly Aimless" = "Здебільшого Безцільний";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:113; */
|
||||
"Scout" = "Розвідник";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:114; */
|
||||
"Surveyor" = "Геодезист";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:115; */
|
||||
"Trailblazer" = "Новатор";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:116; */
|
||||
"Pathfinder" = "Слідопит";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:119; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:117; */
|
||||
"Ranger" = "Рейнджер";
|
||||
|
||||
/* stats.py: Explorer rank; In files: stats.py:120; */
|
||||
/* stats.py: Explorer rank; In files: stats.py:118; */
|
||||
"Pioneer" = "Піонер";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
/* stats.py: CQC rank; In files: stats.py:142; */
|
||||
"Helpless" = "Безпорадний";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
/* stats.py: CQC rank; In files: stats.py:143; */
|
||||
"Mostly Helpless" = "Здебільшого Безпомічний";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
/* stats.py: CQC rank; In files: stats.py:144; */
|
||||
"Amateur" = "Аматор";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
/* stats.py: CQC rank; In files: stats.py:145; */
|
||||
"Semi Professional" = "Напів-професійний";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
/* stats.py: CQC rank; In files: stats.py:146; */
|
||||
"Professional" = "Професійний";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
/* stats.py: CQC rank; In files: stats.py:147; */
|
||||
"Champion" = "Чемпіон";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:150; */
|
||||
/* stats.py: CQC rank; In files: stats.py:148; */
|
||||
"Hero" = "Герой";
|
||||
|
||||
/* stats.py: CQC rank; In files: stats.py:151; */
|
||||
/* stats.py: CQC rank; In files: stats.py:149; */
|
||||
"Gladiator" = "Гладіатор";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
/* stats.py: Federation rank; In files: stats.py:155; */
|
||||
"Recruit" = "Рекрут";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
/* stats.py: Federation rank; In files: stats.py:156; */
|
||||
"Cadet" = "Кадет";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
/* stats.py: Federation rank; In files: stats.py:157; */
|
||||
"Midshipman" = "Гардемарин";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
/* stats.py: Federation rank; In files: stats.py:158; */
|
||||
"Petty Officer" = "Унтер Офіцер";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
/* stats.py: Federation rank; In files: stats.py:159; */
|
||||
"Chief Petty Officer" = "Старший Унтер Офіцер";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
/* stats.py: Federation rank; In files: stats.py:160; */
|
||||
"Warrant Officer" = "Старший сержант";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
/* stats.py: Federation rank; In files: stats.py:161; */
|
||||
"Ensign" = "Прапорщик";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
/* stats.py: Federation rank; In files: stats.py:162; */
|
||||
"Lieutenant" = "Лейтенант";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
/* stats.py: Federation rank; In files: stats.py:163; */
|
||||
"Lieutenant Commander" = "Капітан III рангу";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
/* stats.py: Federation rank; In files: stats.py:164; */
|
||||
"Post Commander" = "Капітан II рангу";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
/* stats.py: Federation rank; In files: stats.py:165; */
|
||||
"Post Captain" = "Капітан I рангу";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
/* stats.py: Federation rank; In files: stats.py:166; */
|
||||
"Rear Admiral" = "Контр-адмірал";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:169; */
|
||||
/* stats.py: Federation rank; In files: stats.py:167; */
|
||||
"Vice Admiral" = "Віце-адмірал";
|
||||
|
||||
/* stats.py: Federation rank; In files: stats.py:170; */
|
||||
/* stats.py: Federation rank; In files: stats.py:168; */
|
||||
"Admiral" = "Адмірал";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:176; */
|
||||
/* stats.py: Empire rank; In files: stats.py:174; */
|
||||
"Outsider" = "Чужинець";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
/* stats.py: Empire rank; In files: stats.py:175; */
|
||||
"Serf" = "Кріпак";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
/* stats.py: Empire rank; In files: stats.py:177; */
|
||||
"Squire" = "Зброєносець";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
/* stats.py: Empire rank; In files: stats.py:178; */
|
||||
"Knight" = "Лицар";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
/* stats.py: Empire rank; In files: stats.py:179; */
|
||||
"Lord" = "Пан";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
/* stats.py: Empire rank; In files: stats.py:180; */
|
||||
"Baron" = "Барон";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
/* stats.py: Empire rank; In files: stats.py:181; */
|
||||
"Viscount" = "Віконт";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
/* stats.py: Empire rank; In files: stats.py:182; */
|
||||
"Count" = "Граф";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
/* stats.py: Empire rank; In files: stats.py:183; */
|
||||
"Earl" = "Дворянин";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
/* stats.py: Empire rank; In files: stats.py:184; */
|
||||
"Marquis" = "Маркіз";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
/* stats.py: Empire rank; In files: stats.py:185; */
|
||||
"Duke" = "Герцог";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:188; */
|
||||
/* stats.py: Empire rank; In files: stats.py:186; */
|
||||
"Prince" = "Принц";
|
||||
|
||||
/* stats.py: Empire rank; In files: stats.py:189; */
|
||||
/* stats.py: Empire rank; In files: stats.py:187; */
|
||||
"King" = "Цар";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
/* stats.py: Power rank; In files: stats.py:193; */
|
||||
"Rating 1" = "Рейтинг 1";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
/* stats.py: Power rank; In files: stats.py:194; */
|
||||
"Rating 2" = "Рейтинг 2";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
/* stats.py: Power rank; In files: stats.py:195; */
|
||||
"Rating 3" = "Рейтинг 3";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:198; */
|
||||
/* stats.py: Power rank; In files: stats.py:196; */
|
||||
"Rating 4" = "Рейтинг 4";
|
||||
|
||||
/* stats.py: Power rank; In files: stats.py:199; */
|
||||
/* stats.py: Power rank; In files: stats.py:197; */
|
||||
"Rating 5" = "Рейтинг 5";
|
||||
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:413; */
|
||||
/* stats.py: Status dialog subtitle - CR value of ship; In files: stats.py:409; */
|
||||
"Value" = "Вартість";
|
||||
|
||||
/* stats.py: Status dialog title; In files: stats.py:422; */
|
||||
/* stats.py: Status dialog title; In files: stats.py:418; */
|
||||
"Ships" = "Кораблі";
|
||||
+420
-426
File diff suppressed because it is too large.
Load diff
@@ -337,4 +337,3 @@ 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.
|
||||
|
||||
+157
-72
@@ -99,8 +99,8 @@ liable to change without notice.
|
||||
`from prefs import prefsVersion` - to allow for versioned preferences.
|
||||
|
||||
`from companion import CAPIData, SERVER_LIVE, SERVER_LEGACY, SERVER_BETA` -
|
||||
`CAPIData` is the actual type of `data` as passed into `cmdr_data()` and
|
||||
`cmdr_data_legacy()`.
|
||||
`CAPIData` is the actual type of `data` as passed into `cmdr_data()`,
|
||||
`cmdr_data_legacy()` and `capi_fleetcarrier()`.
|
||||
See [Commander Data from Frontier CAPI](#commander-data-from-frontier-capi))
|
||||
for further information.
|
||||
|
||||
@@ -561,9 +561,9 @@ See [Avoiding potential pitfalls](#avoiding-potential-pitfalls).
|
||||
### Events
|
||||
|
||||
Once you have created your plugin and EDMarketConnector has loaded it there
|
||||
are four other functions you can define to be notified by EDMarketConnector
|
||||
are five other functions you can define to be notified by EDMarketConnector
|
||||
when something happens: `journal_entry()`, `journal_entry_cqc()`,
|
||||
`dashboard_entry()` and `cmdr_data()`.
|
||||
`dashboard_entry()`, `cmdr_data()` and `capi_fleetcarrier()`.
|
||||
|
||||
Your events all get called on the main Tkinter loop so be sure not to block for
|
||||
very long or the app will appear to freeze. If you have a long running
|
||||
@@ -606,55 +606,63 @@ This gets called when EDMarketConnector sees a new entry in the game's journal.
|
||||
|
||||
Content of `state` (updated to the current journal entry):
|
||||
|
||||
| Field | Type | Description |
|
||||
| :------------------- | :-------------------------: |:----------------------------------------------------------------------------------------------------------------|
|
||||
| `GameLanguage` | `Optional[str]` | `language` value from `Fileheader` event. |
|
||||
| `GameVersion` | `Optional[str]` | `version` value from `Fileheader` event. |
|
||||
| `GameBuild` | `Optional[str]` | `build` value from `Fileheader` event. |
|
||||
| `Captain` | `Optional[str]` | Name of the commander who's crew you're on, if any |
|
||||
| `Cargo` | `dict` | Current cargo. Note that this will be totals, and any mission specific duplicates will be counted together |
|
||||
| `CargoJSON` | `dict` | content of cargo.json as of last read. |
|
||||
| `Credits` | `int` | Current credits balance |
|
||||
| `FID` | `str` | Frontier commander ID |
|
||||
| `Horizons` | `bool` | From `LoadGame` event. |
|
||||
| `Odyssey` | `bool` | From `LoadGame` event. `False` if not present, else the event value. |
|
||||
| `Loan` | `Optional[int]` | Current loan amount, if any |
|
||||
| `Raw` | `dict` | Current raw engineering materials |
|
||||
| `Manufactured` | `dict` | Current manufactured engineering materials |
|
||||
| `Encoded` | `dict` | Current encoded engineering materials |
|
||||
| `Component` | `dict` | Current component materials |
|
||||
| `Engineers` | `dict` | Current Raw engineering materials |
|
||||
| `Rank` | `Dict[str, Tuple[int, int]` | Current ranks, each entry is a tuple of the current rank, and age |
|
||||
| `Statistics` | `dict` | Contents of a Journal Statistics event, ie, data shown in the stats panel. See the Journal manual for more info |
|
||||
| `Role` | `Optional[str]` | Current role if in multi-crew, one of `Idle`, `FireCon`, `FighterCon` |
|
||||
| `Friends` | `set` | Currently online friend |
|
||||
| `ShipID` | `int` | Frontier ID of current ship |
|
||||
| `ShipIdent` | `str` | Current user-set ship ID |
|
||||
| `ShipName` | `str` | Current user-set ship name |
|
||||
| `ShipType` | `str` | Internal name for the current ship type |
|
||||
| `HullValue` | `int` | Current ship value, excluding modules |
|
||||
| `ModulesValue` | `int` | Value of the current ship's modules |
|
||||
| `Rebuy` | `int` | Current ship's rebuy cost |
|
||||
| `Modules` | `dict` | Currently fitted modules |
|
||||
| `NavRoute` | `dict` | Last plotted multi-hop route[1] |
|
||||
| `ModuleInfo` | `dict` | Last loaded ModulesInfo.json data |
|
||||
| `IsDocked` | `bool` | Whether the Cmdr is currently docked *in their own ship*. |
|
||||
| `OnFoot` | `bool` | Whether the Cmdr is on foot |
|
||||
| `Component` | `dict` | 'Component' MicroResources in Odyssey, `int` count each. |
|
||||
| `Item` | `dict` | 'Item' MicroResources in Odyssey, `int` count each. |
|
||||
| `Consumable` | `dict` | 'Consumable' MicroResources in Odyssey, `int` count each. |
|
||||
| `Data` | `dict` | 'Data' MicroResources in Odyssey, `int` count each. |
|
||||
| `BackPack` | `dict` | `dict` of Odyssey MicroResources in backpack. |
|
||||
| `BackpackJSON` | `dict` | Content of Backpack.json as of last read. |
|
||||
| `ShipLockerJSON` | `dict` | Content of ShipLocker.json as of last read. |
|
||||
| `SuitCurrent` | `dict` | CAPI-returned data of currently worn suit. NB: May be `None` if no data. |
|
||||
| `Suits` | `dict`[2] | CAPI-returned data of owned suits. NB: May be `None` if no data. |
|
||||
| `SuitLoadoutCurrent` | `dict` | CAPI-returned data of current Suit Loadout. NB: May be `None` if no data. |
|
||||
| `SuitLoadouts` | `dict`[2] | CAPI-returned data of all Suit Loadouts. NB: May be `None` if no data. |
|
||||
| `Taxi` | `Optional[bool]` | Whether or not we're currently in a taxi. NB: This is best effort with what the journals provide. |
|
||||
| `Dropship` | `Optional[bool]` | Whether or not the above taxi is a Dropship |
|
||||
| `Body` | `Optional[str]` | The body we're currently on / in the SOI of |
|
||||
| `BodyType` | `Optional[str]` | The type of body that `Body` refers to |
|
||||
| Field | Type | Description |
|
||||
|:----------------------|:---------------------------:|:----------------------------------------------------------------------------------------------------------------|
|
||||
| `GameLanguage` | `Optional[str]` | `language` value from `Fileheader` event. |
|
||||
| `GameVersion` | `Optional[str]` | `version` value from `Fileheader` event. |
|
||||
| `GameBuild` | `Optional[str]` | `build` value from `Fileheader` event. |
|
||||
| `Captain`[3] | `Optional[str]` | Name of the commander who's crew you're on, if any |
|
||||
| `Cargo` | `dict` | Current cargo. Note that this will be totals, and any mission specific duplicates will be counted together |
|
||||
| `CargoJSON` | `dict` | content of cargo.json as of last read. |
|
||||
| `Credits` | `int` | Current credits balance |
|
||||
| `FID` | `str` | Frontier commander ID |
|
||||
| `Horizons` | `bool` | From `LoadGame` event. |
|
||||
| `Odyssey` | `bool` | From `LoadGame` event. `False` if not present, else the event value. |
|
||||
| `Loan` | `Optional[int]` | Current loan amount, if any |
|
||||
| `Raw` | `dict` | Current raw engineering materials |
|
||||
| `Manufactured` | `dict` | Current manufactured engineering materials |
|
||||
| `Encoded` | `dict` | Current encoded engineering materials |
|
||||
| `Component` | `dict` | Current component materials |
|
||||
| `Engineers` | `dict` | Current Raw engineering materials |
|
||||
| `Rank` | `Dict[str, Tuple[int, int]` | Current ranks, each entry is a tuple of the current rank, and age |
|
||||
| `Statistics` | `dict` | Contents of a Journal Statistics event, ie, data shown in the stats panel. See the Journal manual for more info |
|
||||
| `Role` | `Optional[str]` | Current role if in multi-crew, one of `Idle`, `FireCon`, `FighterCon` |
|
||||
| `Friends` | `set` | Currently online friend |
|
||||
| `ShipID` | `int` | Frontier ID of current ship |
|
||||
| `ShipIdent` | `str` | Current user-set ship ID |
|
||||
| `ShipName` | `str` | Current user-set ship name |
|
||||
| `ShipType` | `str` | Internal name for the current ship type |
|
||||
| `HullValue` | `int` | Current ship value, excluding modules |
|
||||
| `ModulesValue` | `int` | Value of the current ship's modules |
|
||||
| `Rebuy` | `int` | Current ship's rebuy cost |
|
||||
| `Modules` | `dict` | Currently fitted modules |
|
||||
| `NavRoute` | `dict` | Last plotted multi-hop route[1] |
|
||||
| `ModuleInfo` | `dict` | Last loaded ModulesInfo.json data |
|
||||
| `IsDocked` | `bool` | Whether the Cmdr is currently docked *in their own ship*. |
|
||||
| `OnFoot`[3] | `bool` | Whether the Cmdr is on foot |
|
||||
| `Component` | `dict` | 'Component' MicroResources in Odyssey, `int` count each. |
|
||||
| `Item` | `dict` | 'Item' MicroResources in Odyssey, `int` count each. |
|
||||
| `Consumable` | `dict` | 'Consumable' MicroResources in Odyssey, `int` count each. |
|
||||
| `Data` | `dict` | 'Data' MicroResources in Odyssey, `int` count each. |
|
||||
| `BackPack` | `dict` | `dict` of Odyssey MicroResources in backpack. |
|
||||
| `BackpackJSON` | `dict` | Content of Backpack.json as of last read. |
|
||||
| `ShipLockerJSON` | `dict` | Content of ShipLocker.json as of last read. |
|
||||
| `SuitCurrent` | `dict` | CAPI-returned data of currently worn suit. NB: May be `None` if no data. |
|
||||
| `Suits` | `dict`[2] | CAPI-returned data of owned suits. NB: May be `None` if no data. |
|
||||
| `SuitLoadoutCurrent` | `dict` | CAPI-returned data of current Suit Loadout. NB: May be `None` if no data. |
|
||||
| `SuitLoadouts` | `dict`[2] | CAPI-returned data of all Suit Loadouts. NB: May be `None` if no data. |
|
||||
| `Taxi` | `Optional[bool]` | Whether or not we're currently in a taxi. NB: This is best effort with what the journals provide. |
|
||||
| `Dropship` | `Optional[bool]` | Whether or not the above taxi is a Dropship |
|
||||
| `SystemAddress`[3] | `Optional[int]` | Unique [ID64](http://disc.thargoid.space/ID64) of the star system we're currently in |
|
||||
| `SystemName`[3] | `Optional[str]` | Name of the star system we're currently in |
|
||||
| `SystemPopulation`[3] | `Optional[int]` | Population of the star system we're currently in |
|
||||
| `StarPos`[3] | `Optional[tuple[float]]` | Galaxy co-ordinates of the system we're currently in |
|
||||
| `Body`[3][4] | `Optional[str]` | Name of the body we're currently on / in the SOI of |
|
||||
| `BodyID`[3][4] | `Optional[int]` | ID of the body we're currently on / in the SOI of |
|
||||
| `BodyType`[3][4] | `Optional[str]` | The type of body that `Body` refers to |
|
||||
| `StationName`[3] | `Optional[str]` | Name of the station we're docked at, if applicable |
|
||||
| `MarketID`[3] | `Optional[str]` | MarketID of the station we're docked at, if applicable |
|
||||
| `StationType`[3] | `Optional[str]` | Type of the station we're docked at, if applicable |
|
||||
|
||||
[1] - Contents of `NavRoute` not changed if a `NavRouteClear` event is seen,
|
||||
but plugins will see the `NavRouteClear` event.
|
||||
@@ -676,6 +684,31 @@ least one member is missing, so the indices are not contiguous). We choose to
|
||||
always convert to the integer-keyed `dict` form so that code utilising the data
|
||||
is simpler.
|
||||
|
||||
[3] - Forced to `None` if the player joins another player's ship in remote
|
||||
multi-crew.
|
||||
|
||||
[4] - There are some caveats with the Body data. Firstly the name and ID
|
||||
can be for the orbital station or fleet carrier the player is docked at.
|
||||
Check 'BodyType' before using the values.
|
||||
|
||||
Secondly there is an issue with close-orbiting binary bodies. If the player:
|
||||
|
||||
1. Enters Orbital Cruise around a Body an 'ApproachBody' event is emitted
|
||||
and the tracking will update to reflect this.
|
||||
2. If the player then flies *in Orbital Cruise without entering Supercruise
|
||||
proper* to the close-orbiting binary partner of the Body then *there is no
|
||||
new 'ApproachBody' event to indicate the new Body's details*. **Thus this
|
||||
tracking will incorrectly indicate the first Body still**.
|
||||
|
||||
So, before making use of any of this Body state a plugin should:
|
||||
|
||||
1. Have a `dashboard_entry()` method and track the Body name present in its
|
||||
data.
|
||||
2. Cross-check that Body name with `state['Body']` before making use of any
|
||||
of `state'`s Body data.
|
||||
|
||||
See `plugins/eddn.py` for an example of this in `export_journal_codexentry()`.
|
||||
|
||||
New in version 4.1.6:
|
||||
|
||||
`CargoJSON` contains the raw data from the last read of `Cargo.json` passed
|
||||
@@ -765,13 +798,26 @@ re-start EDMarketConnector. That will be present when plugins are invoked
|
||||
with the synthetic `StartUp` event. NB: Might just be a `NavRouteClear` event
|
||||
if that's what was in the file.
|
||||
|
||||
New in version 5.8.0:
|
||||
|
||||
`StarPos`, `SystemAddress`, `SystemName` and `SystemPopulation` have been
|
||||
added to the `state` dictionary. Best efforts data pertaining to the star
|
||||
system the player is in.
|
||||
|
||||
`BodyID` and `BodyType` have been added to the `state` dictionary. These
|
||||
now track in the same manner as prior core EDDN plugin code. Check the
|
||||
documentation above for some caveats. Do not just blindly use this data, or
|
||||
the 'Body' name value.
|
||||
|
||||
`StationName`, `MarketID`, and `StationType` added to the `state` dictionary.
|
||||
|
||||
___
|
||||
|
||||
##### Synthetic Events
|
||||
|
||||
A special "StartUp" entry is sent if EDMarketConnector is started while the
|
||||
game is already running. In this case you won't receive initial events such as
|
||||
"LoadGame", "Rank", "Location", etc. However the `state` dictionary will
|
||||
"LoadGame", "Rank", "Location", etc. However, the `state` dictionary will
|
||||
reflect the cumulative effect of these missed events.
|
||||
|
||||
**NB: Any of the values in this might be `None` if the Cmdr has loaded into
|
||||
@@ -908,12 +954,11 @@ constants.
|
||||
|
||||
---
|
||||
|
||||
### Commander Data from Frontier CAPI
|
||||
If a plugin has a `cmdr_data()` function it gets called when the application
|
||||
has just fetched fresh Cmdr and station data from Frontier's servers, **but not
|
||||
for the Legacy galaxy**. See `cmdr_data_legacy()` below for Legacy data
|
||||
handling.
|
||||
### Data from Frontier CAPI
|
||||
|
||||
#### Commander, Market and Shipyard Data
|
||||
|
||||
If a plugin has a `cmdr_data()` function it gets called when the application has just fetched fresh CMDR, station and shipyard data from Frontier's CAPI servers, **but not for the Legacy galaxy**. See `cmdr_data_legacy()` below for Legacy data handling.
|
||||
```python
|
||||
from companion import CAPIData, SERVER_LIVE, SERVER_LEGACY, SERVER_BETA
|
||||
|
||||
@@ -941,19 +986,59 @@ def cmdr_data(data, is_beta):
|
||||
| :-------- | :--------------: | :------------------------------------------------------------------------------------------------------- |
|
||||
| `data` | `CAPIData` | `/profile` API response, with `/market` and `/shipyard` added under the keys `marketdata` and `shipdata` |
|
||||
| `is_beta` | `bool` | If the game is currently in beta |
|
||||
`CAPIData` is a class, which you can `from companion import CAPIDATA`, and is
|
||||
based on `UserDict`. The actual data from CAPI queries is thus accessible
|
||||
via python's normal `data['key']` syntax. However, being a class, it can also
|
||||
have extra properties, such as `source_host`, as shown above. Plugin authors
|
||||
are free to use *that* property, **but MUST NOT rely on any other extra
|
||||
properties present in `CAPIData`, they are for internal use only.**
|
||||
|
||||
#### Fleet Carrier Data
|
||||
|
||||
If a plugin has a `capi_fleetcarrier()` function it gets called when the application has just fetched fresh Fleetcarrier data from Frontier's CAPI servers. This is done when `CarrierBuy`or `CarrierStats` events are detected in the Player Journal. To avoid flooding Frontier's CAPI server, a throttle is applied to ensure a significant interval between requests (currently 15 mins). Also be aware that calls to the `/fleetcarrier` CAPI endpoint have been reported to take a very long time to return, potentially up to 20 minutes. Delays in responses from this endpoint could delay other CAPI queries.
|
||||
|
||||
```python
|
||||
from companion import CAPIData, SERVER_LIVE, SERVER_LEGACY, SERVER_BETA
|
||||
|
||||
def capi_fleetcarrier(data):
|
||||
"""
|
||||
We have new data on our Fleet Carrier
|
||||
"""
|
||||
if data.get('name') is None or data['name'].get('callsign') is None:
|
||||
raise ValueError("this isn't possible")
|
||||
|
||||
logger.info(data['name']['callsign'])
|
||||
|
||||
# Determining source galaxy for the data
|
||||
if data.source_host == SERVER_LIVE:
|
||||
...
|
||||
|
||||
elif data.source_host == SERVER_BETA:
|
||||
...
|
||||
|
||||
elif data.source_host == SERVER_LEGACY:
|
||||
...
|
||||
```
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| :-------- | :--------------: | :------------------------------------------------------------------------------------------------------- |
|
||||
| `data` | `CAPIData` | `/fleetcarrier` API response |
|
||||
|
||||
#### CAPIData and Available Properties
|
||||
|
||||
`CAPIData` is a class, which you can `from companion import CAPIDATA`, and is based on `UserDict`. The actual data from CAPI queries is thus accessible via python's normal `data['key']` syntax. However, being a class, it can also have extra properties, such as `source_host`, as shown in the code example above.
|
||||
|
||||
Plugin authors are free to use the following properties of `CAPIData`, **but MUST NOT rely on any other extra properties, they are for internal use only.**
|
||||
|
||||
| Property | Type | Description |
|
||||
| :------------- | :--------------: | :------------------------------------------------------------------------------------------------------- |
|
||||
| `data` | `Dict` | The data returned by the CAPI query. For the `cmdr_data()` callback, if the player is docked at a station, and the relevant services are available then the `lastStarport` key's value will have been augmented with `/market` and/or `/shipyard` data. **Do not assume this will always be the case**. |
|
||||
| `source_host` | `str` | `SERVER_LIVE` \| `SERVER_BETA` \| `SERVER_LEGACY` the current galaxy mode. |
|
||||
| `request_cmdr` | `str` | The name of the active CMDR _at the point the request was made_. In the case of a CAPI request taking a long time to return, the user may have switched CMDR during the request, so this may be different to the current CMDR. |
|
||||
|
||||
See [this documentation](https://github.com/Athanasius/fd-api/blob/main/docs/FrontierDevelopments-CAPI-endpoints.md) for details of the expected content structure and data for CAPI queries.
|
||||
|
||||
If there is a killswitch in effect for some of the CAPI endpoints, then the
|
||||
data passed to this function might not be as complete as you expect. Code
|
||||
defensively.
|
||||
|
||||
#### CAPI data for Legacy
|
||||
When CAPI data has been retrieved from the separate CAPI host for the Legacy
|
||||
galaxy, because the Journal gameversion indicated the player is playing/last
|
||||
played in that galaxy, a different function will be called,
|
||||
`cmdr_data_legacy()`.
|
||||
|
||||
When CAPI data has been retrieved from the separate CAPI host for the Legacy galaxy, because the Journal gameversion indicated the player is playing / last played in that galaxy, a different function will be called, `cmdr_data_legacy()`. Note that there is no legacy equivalent to `capi_fleetcarrier()`, so always use the `source_host` property to determine the user's galaxy.
|
||||
|
||||
```python
|
||||
def cmdr_data_legacy(data, is_beta):
|
||||
@@ -1073,7 +1158,7 @@ time after the corresponding `journal_entry()` event.
|
||||
## Error messages
|
||||
|
||||
You can display an error in EDMarketConnector's status area by returning a
|
||||
string from your `journal_entry()`, `dashboard_entry()` or `cmdr_data()`
|
||||
string from your `journal_entry()`, `dashboard_entry()`, `cmdr_data()` or `capi_fleetcarrier()`
|
||||
function, or asynchronously (e.g. from a "worker" thread that is performing a
|
||||
long-running operation) by calling `plug.show_error()`. Either method will
|
||||
cause the "bad" sound to be played (unless the user has muted sound).
|
||||
@@ -1099,7 +1184,7 @@ _ = functools.partial(l10n.Translations.translate, context=__file__)
|
||||
Wrap each string that needs translating with the `_()` function, e.g.:
|
||||
|
||||
```python
|
||||
status["text"] = _('Happy!') # Main window status
|
||||
somewidget["text"] = _("Happy!")
|
||||
```
|
||||
|
||||
If you display localized strings in EDMarketConnector's main window you should
|
||||
@@ -1302,7 +1387,7 @@ versions of EDMarketConnector:
|
||||
`Settings` > `Plugins` tab.
|
||||
|
||||
- Check that callback functions `plugin_prefs`, `prefs_changed`,
|
||||
`journal_entry`, `dashboard_entry` and `cmdr_data`, if used, are declared
|
||||
`journal_entry`, `dashboard_entry`, `cmdr_data` and `capi_fleetcarrier`, if used, are declared
|
||||
with the correct number of arguments. Older versions of this app were
|
||||
tolerant of missing arguments in these function declarations.
|
||||
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ def addmodules(data): # noqa: C901, CCR001
|
||||
if not data['lastStarport'].get('modules'):
|
||||
return
|
||||
|
||||
outfile = 'outfitting.csv'
|
||||
outfile = pathlib.Path('outfitting.csv')
|
||||
modules = {}
|
||||
fields = ('id', 'symbol', 'category', 'name', 'mount', 'guidance', 'ship', 'class', 'rating', 'entitlement')
|
||||
|
||||
|
||||
+123
-33
@@ -28,6 +28,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, OrderedDic
|
||||
import requests
|
||||
|
||||
import config as conf_module
|
||||
import killswitch
|
||||
import protocol
|
||||
from config import config, user_agent
|
||||
from edmc_data import companion_category_map as category_map
|
||||
@@ -45,7 +46,9 @@ else:
|
||||
|
||||
|
||||
capi_query_cooldown = 60 # Minimum time between (sets of) CAPI queries
|
||||
capi_fleetcarrier_query_cooldown = 60 * 15 # Minimum time between CAPI fleetcarrier queries
|
||||
capi_default_requests_timeout = 10
|
||||
capi_fleetcarrier_requests_timeout = 60
|
||||
auth_timeout = 30 # timeout for initial auth
|
||||
|
||||
# Used by both class Auth and Session
|
||||
@@ -65,7 +68,8 @@ class CAPIData(UserDict):
|
||||
self,
|
||||
data: Union[str, Dict[str, Any], 'CAPIData', None] = None,
|
||||
source_host: Optional[str] = None,
|
||||
source_endpoint: Optional[str] = None
|
||||
source_endpoint: Optional[str] = None,
|
||||
request_cmdr: Optional[str] = None
|
||||
) -> None:
|
||||
if data is None:
|
||||
super().__init__()
|
||||
@@ -80,6 +84,7 @@ class CAPIData(UserDict):
|
||||
|
||||
self.source_host = source_host
|
||||
self.source_endpoint = source_endpoint
|
||||
self.request_cmdr = request_cmdr
|
||||
|
||||
if source_endpoint is None:
|
||||
return
|
||||
@@ -325,6 +330,14 @@ class Auth(object):
|
||||
"""
|
||||
logger.debug(f'Trying for "{self.cmdr}"')
|
||||
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
||||
if should_return:
|
||||
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
||||
return None
|
||||
|
||||
self.verifier = None
|
||||
cmdrs = config.get_list('cmdrs', default=[])
|
||||
logger.debug(f'Cmdrs: {cmdrs}')
|
||||
@@ -393,9 +406,11 @@ class Auth(object):
|
||||
return None
|
||||
|
||||
def authorize(self, payload: str) -> str: # noqa: CCR001
|
||||
"""Handle oAuth authorization callback.
|
||||
"""
|
||||
Handle oAuth authorization callback.
|
||||
|
||||
:return: access token if successful, otherwise raises CredentialsError.
|
||||
:return: access token if successful
|
||||
:raises CredentialsError
|
||||
"""
|
||||
logger.debug('Checking oAuth authorization callback')
|
||||
if '?' not in payload:
|
||||
@@ -593,7 +608,7 @@ class EDMCCAPIFailedRequest(EDMCCAPIReturn):
|
||||
):
|
||||
super().__init__(query_time=query_time, play_sound=play_sound, auto_update=auto_update)
|
||||
self.message: str = message # User-friendly reason for failure.
|
||||
self.exception: int = exception # Exception that recipient should raise.
|
||||
self.exception: Exception = exception # Exception that recipient should raise.
|
||||
|
||||
|
||||
class Session(object):
|
||||
@@ -604,6 +619,8 @@ class Session(object):
|
||||
FRONTIER_CAPI_PATH_PROFILE = '/profile'
|
||||
FRONTIER_CAPI_PATH_MARKET = '/market'
|
||||
FRONTIER_CAPI_PATH_SHIPYARD = '/shipyard'
|
||||
FRONTIER_CAPI_PATH_FLEETCARRIER = '/fleetcarrier'
|
||||
|
||||
# This is a dummy value, to signal to Session.capi_query_worker that we
|
||||
# the 'station' triplet of queries.
|
||||
_CAPI_PATH_STATION = '_edmc_station'
|
||||
@@ -611,7 +628,7 @@ class Session(object):
|
||||
def __init__(self) -> None:
|
||||
self.state = Session.STATE_INIT
|
||||
self.credentials: Optional[Dict[str, Any]] = None
|
||||
self.requests_session: Optional[requests.Session] = None
|
||||
self.requests_session = requests.Session()
|
||||
self.auth: Optional[Auth] = None
|
||||
self.retrying = False # Avoid infinite loop when successful auth / unsuccessful query
|
||||
self.tk_master: Optional[tk.Tk] = None
|
||||
@@ -644,9 +661,9 @@ class Session(object):
|
||||
def start_frontier_auth(self, access_token: str) -> None:
|
||||
"""Start an oAuth2 session."""
|
||||
logger.debug('Starting session')
|
||||
self.requests_session = requests.Session()
|
||||
self.requests_session.headers['Authorization'] = f'Bearer {access_token}'
|
||||
self.requests_session.headers['User-Agent'] = user_agent
|
||||
|
||||
self.state = Session.STATE_OK
|
||||
|
||||
def login(self, cmdr: Optional[str] = None, is_beta: Optional[bool] = None) -> bool:
|
||||
@@ -655,6 +672,14 @@ class Session(object):
|
||||
|
||||
:return: True if login succeeded, False if re-authorization initiated.
|
||||
"""
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('capi.auth', {})
|
||||
if should_return:
|
||||
logger.warning('capi.auth has been disabled via killswitch. Returning.')
|
||||
return False
|
||||
|
||||
if not Auth.CLIENT_ID:
|
||||
logger.error('self.CLIENT_ID is None')
|
||||
raise CredentialsError('cannot login without a valid Client ID')
|
||||
@@ -680,7 +705,7 @@ class Session(object):
|
||||
|
||||
else:
|
||||
logger.debug('changed account or retrying login during auth')
|
||||
self.close()
|
||||
self.reinit_session()
|
||||
self.credentials = credentials
|
||||
|
||||
self.state = Session.STATE_INIT
|
||||
@@ -720,22 +745,30 @@ class Session(object):
|
||||
raise # Bad thing happened
|
||||
|
||||
def close(self) -> None:
|
||||
"""Close Frontier authorization session."""
|
||||
"""Close the `request.Session()."""
|
||||
try:
|
||||
self.requests_session.close()
|
||||
|
||||
except Exception as e:
|
||||
logger.debug('Frontier Auth: closing', exc_info=e)
|
||||
|
||||
def reinit_session(self, reopen: bool = True) -> None:
|
||||
"""
|
||||
Re-initialise the session's `request.Session()`.
|
||||
|
||||
:param reopen: Whether to open a new session.
|
||||
"""
|
||||
self.state = Session.STATE_INIT
|
||||
if self.requests_session:
|
||||
try:
|
||||
self.requests_session.close()
|
||||
self.close()
|
||||
|
||||
except Exception as e:
|
||||
logger.debug('Frontier Auth: closing', exc_info=e)
|
||||
|
||||
self.requests_session = None
|
||||
if reopen:
|
||||
self.requests_session = requests.Session()
|
||||
|
||||
def invalidate(self) -> None:
|
||||
"""Invalidate Frontier authorization credentials."""
|
||||
logger.debug('Forcing a full re-authentication')
|
||||
# Force a full re-authentication
|
||||
self.close()
|
||||
self.reinit_session()
|
||||
Auth.invalidate(self.credentials['cmdr']) # type: ignore
|
||||
######################################################################
|
||||
|
||||
@@ -759,9 +792,17 @@ class Session(object):
|
||||
:param timeout: requests query timeout to use.
|
||||
:return: The resulting CAPI data, of type CAPIData.
|
||||
"""
|
||||
capi_data: CAPIData
|
||||
capi_data: CAPIData = CAPIData()
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('capi.request.' + capi_endpoint, {})
|
||||
if should_return:
|
||||
logger.warning(f"capi.request.{capi_endpoint} has been disabled by killswitch. Returning.")
|
||||
return capi_data
|
||||
|
||||
try:
|
||||
logger.trace_if('capi.worker', 'Sending HTTP request...')
|
||||
logger.trace_if('capi.worker', f'Sending HTTP request for {capi_endpoint} ...')
|
||||
if conf_module.capi_pretend_down:
|
||||
raise ServerConnectionError(f'Pretending CAPI down: {capi_endpoint}')
|
||||
|
||||
@@ -778,7 +819,7 @@ class Session(object):
|
||||
# r.status_code = 401
|
||||
# raise requests.HTTPError
|
||||
capi_json = r.json()
|
||||
capi_data = CAPIData(capi_json, capi_host, capi_endpoint)
|
||||
capi_data = CAPIData(capi_json, capi_host, capi_endpoint, monitor.cmdr)
|
||||
self.capi_raw_data.record_endpoint(
|
||||
capi_endpoint, r.content.decode(encoding='utf-8'),
|
||||
datetime.datetime.utcnow()
|
||||
@@ -841,6 +882,10 @@ class Session(object):
|
||||
"""
|
||||
station_data = capi_single_query(capi_host, self.FRONTIER_CAPI_PATH_PROFILE, timeout=timeout)
|
||||
|
||||
if not station_data.get('commander'):
|
||||
# If even this doesn't exist, probably killswitched.
|
||||
return station_data
|
||||
|
||||
if not station_data['commander'].get('docked') and not monitor.state['OnFoot']:
|
||||
return station_data
|
||||
|
||||
@@ -881,6 +926,10 @@ class Session(object):
|
||||
|
||||
if services.get('commodities'):
|
||||
market_data = capi_single_query(capi_host, self.FRONTIER_CAPI_PATH_MARKET, timeout=timeout)
|
||||
if not market_data.get('id'):
|
||||
# Probably killswitched
|
||||
return station_data
|
||||
|
||||
if last_starport_id != int(market_data['id']):
|
||||
logger.warning(f"{last_starport_id!r} != {int(market_data['id'])!r}")
|
||||
raise ServerLagging()
|
||||
@@ -891,6 +940,10 @@ class Session(object):
|
||||
|
||||
if services.get('outfitting') or services.get('shipyard'):
|
||||
shipyard_data = capi_single_query(capi_host, self.FRONTIER_CAPI_PATH_SHIPYARD, timeout=timeout)
|
||||
if not shipyard_data.get('id'):
|
||||
# Probably killswitched
|
||||
return station_data
|
||||
|
||||
if last_starport_id != int(shipyard_data['id']):
|
||||
logger.warning(f"{last_starport_id!r} != {int(shipyard_data['id'])!r}")
|
||||
raise ServerLagging()
|
||||
@@ -918,6 +971,10 @@ class Session(object):
|
||||
if query.endpoint == self._CAPI_PATH_STATION:
|
||||
capi_data = capi_station_queries(query.capi_host)
|
||||
|
||||
elif query.endpoint == self.FRONTIER_CAPI_PATH_FLEETCARRIER:
|
||||
capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_FLEETCARRIER,
|
||||
timeout=capi_fleetcarrier_requests_timeout)
|
||||
|
||||
else:
|
||||
capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_PROFILE)
|
||||
|
||||
@@ -946,7 +1003,8 @@ class Session(object):
|
||||
# event too, so assume it will be polling the response queue.
|
||||
if query.tk_response_event is not None:
|
||||
logger.trace_if('capi.worker', 'Sending <<CAPIResponse>>')
|
||||
self.tk_master.event_generate('<<CAPIResponse>>')
|
||||
if self.tk_master is not None:
|
||||
self.tk_master.event_generate('<<CAPIResponse>>')
|
||||
|
||||
logger.info('CAPI worker thread DONE')
|
||||
|
||||
@@ -988,6 +1046,35 @@ class Session(object):
|
||||
auto_update=auto_update
|
||||
)
|
||||
)
|
||||
|
||||
def fleetcarrier(
|
||||
self, query_time: int, tk_response_event: str | None = None,
|
||||
play_sound: bool = False, auto_update: bool = False
|
||||
) -> None:
|
||||
"""
|
||||
Perform CAPI query for fleetcarrier data.
|
||||
|
||||
:param query_time: When this query was initiated.
|
||||
:param tk_response_event: Name of tk event to generate when response queued.
|
||||
:param play_sound: Whether the app should play a sound on error.
|
||||
:param auto_update: Whether this request was triggered automatically.
|
||||
"""
|
||||
capi_host = self.capi_host_for_galaxy()
|
||||
if not capi_host:
|
||||
return
|
||||
|
||||
# Ask the thread worker to perform a fleetcarrier query
|
||||
logger.trace_if('capi.worker', 'Enqueueing fleetcarrier request')
|
||||
self.capi_request_queue.put(
|
||||
EDMCCAPIRequest(
|
||||
capi_host=capi_host,
|
||||
endpoint=self.FRONTIER_CAPI_PATH_FLEETCARRIER,
|
||||
tk_response_event=tk_response_event,
|
||||
query_time=query_time,
|
||||
play_sound=play_sound,
|
||||
auto_update=auto_update
|
||||
)
|
||||
)
|
||||
######################################################################
|
||||
|
||||
######################################################################
|
||||
@@ -1038,24 +1125,27 @@ class Session(object):
|
||||
def dump_capi_data(self, data: CAPIData) -> None:
|
||||
"""Dump CAPI data to file for examination."""
|
||||
if os.path.isdir('dump'):
|
||||
try:
|
||||
system = data['lastSystem']['name']
|
||||
file_name: str = ""
|
||||
if data.source_endpoint == self.FRONTIER_CAPI_PATH_FLEETCARRIER:
|
||||
file_name += f"FleetCarrier.{data['name']['callsign']}"
|
||||
|
||||
except (KeyError, ValueError):
|
||||
system = '<unknown system>'
|
||||
else:
|
||||
try:
|
||||
file_name += data['lastSystem']['name']
|
||||
|
||||
try:
|
||||
if data['commander'].get('docked'):
|
||||
station = f'.{data["lastStarport"]["name"]}'
|
||||
except (KeyError, ValueError):
|
||||
file_name += 'unknown system'
|
||||
|
||||
else:
|
||||
station = ''
|
||||
try:
|
||||
if data['commander'].get('docked'):
|
||||
file_name += f'.{data["lastStarport"]["name"]}'
|
||||
|
||||
except (KeyError, ValueError):
|
||||
station = '<unknown station>'
|
||||
except (KeyError, ValueError):
|
||||
file_name += '.unknown station'
|
||||
|
||||
timestamp = time.strftime('%Y-%m-%dT%H.%M.%S', time.localtime())
|
||||
with open(f'dump/{system}{station}.{timestamp}.json', 'wb') as h:
|
||||
file_name += time.strftime('.%Y-%m-%dT%H.%M.%S', time.localtime())
|
||||
file_name += '.json'
|
||||
with open(f'dump/{file_name}', 'wb') as h:
|
||||
h.write(json.dumps(data, cls=CAPIDataEncoder,
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
|
||||
+14
-11
@@ -40,7 +40,7 @@ import sys
|
||||
import traceback
|
||||
import warnings
|
||||
from abc import abstractmethod
|
||||
from typing import Any, Callable, List, Optional, Type, TypeVar, Union
|
||||
from typing import Any, Callable, Optional, Type, TypeVar
|
||||
|
||||
import semantic_version
|
||||
|
||||
@@ -52,17 +52,17 @@ appcmdname = 'EDMC'
|
||||
# <https://semver.org/#semantic-versioning-specification-semver>
|
||||
# Major.Minor.Patch(-prerelease)(+buildmetadata)
|
||||
# NB: Do *not* import this, use the functions appversion() and appversion_nobuild()
|
||||
_static_appversion = '5.7.0'
|
||||
_static_appversion = '5.8.0'
|
||||
_cached_version: Optional[semantic_version.Version] = None
|
||||
copyright = '© 2015-2019 Jonathan Harris, 2020-2022 EDCD'
|
||||
copyright = '© 2015-2019 Jonathan Harris, 2020-2023 EDCD'
|
||||
|
||||
update_feed = 'https://raw.githubusercontent.com/EDCD/EDMarketConnector/releases/edmarketconnector.xml'
|
||||
update_interval = 8*60*60
|
||||
# Providers marked to be in debug mode. Generally this is expected to switch to sending data to a log file
|
||||
debug_senders: List[str] = []
|
||||
debug_senders: list[str] = []
|
||||
# TRACE logging code that should actually be used. Means not spamming it
|
||||
# *all* if only interested in some things.
|
||||
trace_on: List[str] = []
|
||||
trace_on: list[str] = []
|
||||
|
||||
capi_pretend_down: bool = False
|
||||
capi_debug_access_token: Optional[str] = None
|
||||
@@ -293,7 +293,7 @@ class AbstractConfig(abc.ABC):
|
||||
|
||||
@staticmethod
|
||||
def _suppress_call(
|
||||
func: Callable[..., _T], exceptions: Union[Type[BaseException], List[Type[BaseException]]] = Exception,
|
||||
func: Callable[..., _T], exceptions: Type[BaseException] | list[Type[BaseException]] = Exception,
|
||||
*args: Any, **kwargs: Any
|
||||
) -> Optional[_T]:
|
||||
if exceptions is None:
|
||||
@@ -307,7 +307,10 @@ class AbstractConfig(abc.ABC):
|
||||
|
||||
return None
|
||||
|
||||
def get(self, key: str, default: Union[list, str, bool, int] = None) -> Union[list, str, bool, int]:
|
||||
def get(
|
||||
self, key: str,
|
||||
default: list | str | bool | int | None = None
|
||||
) -> list | str | bool | int | None:
|
||||
"""
|
||||
Return the data for the requested key, or a default.
|
||||
|
||||
@@ -334,7 +337,7 @@ class AbstractConfig(abc.ABC):
|
||||
return default # type: ignore
|
||||
|
||||
@abstractmethod
|
||||
def get_list(self, key: str, *, default: list = None) -> list:
|
||||
def get_list(self, key: str, *, default: list | None = None) -> list:
|
||||
"""
|
||||
Return the list referred to by the given key if it exists, or the default.
|
||||
|
||||
@@ -343,7 +346,7 @@ class AbstractConfig(abc.ABC):
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def get_str(self, key: str, *, default: str = None) -> str:
|
||||
def get_str(self, key: str, *, default: str | None = None) -> str:
|
||||
"""
|
||||
Return the string referred to by the given key if it exists, or the default.
|
||||
|
||||
@@ -356,7 +359,7 @@ class AbstractConfig(abc.ABC):
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def get_bool(self, key: str, *, default: bool = None) -> bool:
|
||||
def get_bool(self, key: str, *, default: bool | None = None) -> bool:
|
||||
"""
|
||||
Return the bool referred to by the given key if it exists, or the default.
|
||||
|
||||
@@ -396,7 +399,7 @@ class AbstractConfig(abc.ABC):
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def set(self, key: str, val: Union[int, str, List[str], bool]) -> None:
|
||||
def set(self, key: str, val: int | str | list[str] | bool) -> None:
|
||||
"""
|
||||
Set the given key's data to the given value.
|
||||
|
||||
|
||||
+9
-10
@@ -3,7 +3,6 @@ import os
|
||||
import pathlib
|
||||
import sys
|
||||
from configparser import ConfigParser
|
||||
from typing import List, Optional, Union
|
||||
|
||||
from config import AbstractConfig, appname, logger
|
||||
|
||||
@@ -18,7 +17,7 @@ class LinuxConfig(AbstractConfig):
|
||||
__unescape_lut = {'\\': '\\', 'n': '\n', ';': ';', 'r': '\r', '#': '#'}
|
||||
__escape_lut = {'\\': '\\', '\n': 'n', ';': ';', '\r': 'r'}
|
||||
|
||||
def __init__(self, filename: Optional[str] = None) -> None:
|
||||
def __init__(self, filename: str | None = None) -> None:
|
||||
super().__init__()
|
||||
# http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
|
||||
xdg_data_home = pathlib.Path(os.getenv('XDG_DATA_HOME', default='~/.local/share')).expanduser()
|
||||
@@ -42,7 +41,7 @@ class LinuxConfig(AbstractConfig):
|
||||
|
||||
self.filename.parent.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
self.config: Optional[ConfigParser] = ConfigParser(comment_prefixes=('#',), interpolation=None)
|
||||
self.config: ConfigParser | None = ConfigParser(comment_prefixes=('#',), interpolation=None)
|
||||
self.config.read(self.filename) # read() ignores files that dont exist
|
||||
|
||||
# Ensure that our section exists. This is here because configparser will happily create files for us, but it
|
||||
@@ -85,7 +84,7 @@ class LinuxConfig(AbstractConfig):
|
||||
:param s: str - The string to unescape.
|
||||
:return: str - The unescaped string.
|
||||
"""
|
||||
out: List[str] = []
|
||||
out: list[str] = []
|
||||
i = 0
|
||||
while i < len(s):
|
||||
c = s[i]
|
||||
@@ -107,7 +106,7 @@ class LinuxConfig(AbstractConfig):
|
||||
|
||||
return "".join(out)
|
||||
|
||||
def __raw_get(self, key: str) -> Optional[str]:
|
||||
def __raw_get(self, key: str) -> str | None:
|
||||
"""
|
||||
Get a raw data value from the config file.
|
||||
|
||||
@@ -119,7 +118,7 @@ class LinuxConfig(AbstractConfig):
|
||||
|
||||
return self.config[self.SECTION].get(key)
|
||||
|
||||
def get_str(self, key: str, *, default: str = None) -> str:
|
||||
def get_str(self, key: str, *, default: str | None = None) -> str:
|
||||
"""
|
||||
Return the string referred to by the given key if it exists, or the default.
|
||||
|
||||
@@ -134,7 +133,7 @@ class LinuxConfig(AbstractConfig):
|
||||
|
||||
return self.__unescape(data)
|
||||
|
||||
def get_list(self, key: str, *, default: list = None) -> list:
|
||||
def get_list(self, key: str, *, default: list | None = None) -> list:
|
||||
"""
|
||||
Return the list referred to by the given key if it exists, or the default.
|
||||
|
||||
@@ -168,7 +167,7 @@ class LinuxConfig(AbstractConfig):
|
||||
except ValueError as e:
|
||||
raise ValueError(f'requested {key=} as int cannot be converted to int') from e
|
||||
|
||||
def get_bool(self, key: str, *, default: bool = None) -> bool:
|
||||
def get_bool(self, key: str, *, default: bool | None = None) -> bool:
|
||||
"""
|
||||
Return the bool referred to by the given key if it exists, or the default.
|
||||
|
||||
@@ -183,7 +182,7 @@ class LinuxConfig(AbstractConfig):
|
||||
|
||||
return bool(int(data))
|
||||
|
||||
def set(self, key: str, val: Union[int, str, List[str]]) -> None:
|
||||
def set(self, key: str, val: int | str | list[str]) -> None:
|
||||
"""
|
||||
Set the given key's data to the given value.
|
||||
|
||||
@@ -192,7 +191,7 @@ class LinuxConfig(AbstractConfig):
|
||||
if self.config is None:
|
||||
raise ValueError('attempt to use a closed config')
|
||||
|
||||
to_set: Optional[str] = None
|
||||
to_set: str | None = None
|
||||
if isinstance(val, bool):
|
||||
to_set = str(int(val))
|
||||
|
||||
|
||||
+6
-5
@@ -8,7 +8,7 @@ import sys
|
||||
import uuid
|
||||
import winreg
|
||||
from ctypes.wintypes import DWORD, HANDLE
|
||||
from typing import List, Optional, Union
|
||||
from typing import List, Literal, Optional, Union
|
||||
|
||||
from config import AbstractConfig, applongname, appname, logger, update_interval
|
||||
|
||||
@@ -142,7 +142,7 @@ class WinConfig(AbstractConfig):
|
||||
logger.warning(f'registry key {key=} returned unknown type {_type=} {value=}')
|
||||
return None
|
||||
|
||||
def get_str(self, key: str, *, default: str = None) -> str:
|
||||
def get_str(self, key: str, *, default: str | None = None) -> str:
|
||||
"""
|
||||
Return the string referred to by the given key if it exists, or the default.
|
||||
|
||||
@@ -157,7 +157,7 @@ class WinConfig(AbstractConfig):
|
||||
|
||||
return res
|
||||
|
||||
def get_list(self, key: str, *, default: list = None) -> list:
|
||||
def get_list(self, key: str, *, default: list | None = None) -> list:
|
||||
"""
|
||||
Return the list referred to by the given key if it exists, or the default.
|
||||
|
||||
@@ -187,7 +187,7 @@ class WinConfig(AbstractConfig):
|
||||
|
||||
return res
|
||||
|
||||
def get_bool(self, key: str, *, default: bool = None) -> bool:
|
||||
def get_bool(self, key: str, *, default: bool | None = None) -> bool:
|
||||
"""
|
||||
Return the bool referred to by the given key if it exists, or the default.
|
||||
|
||||
@@ -205,7 +205,8 @@ class WinConfig(AbstractConfig):
|
||||
|
||||
Implements :meth:`AbstractConfig.set`.
|
||||
"""
|
||||
reg_type = None
|
||||
# These are the types that winreg.REG_* below resolve to.
|
||||
reg_type: Literal[1] | Literal[4] | Literal[7]
|
||||
if isinstance(val, str):
|
||||
reg_type = winreg.REG_SZ
|
||||
winreg.SetValueEx(self.__reg_handle, key, REG_RESERVED_ALWAYS_ZERO, winreg.REG_SZ, val)
|
||||
|
||||
File renamed without changes.
+1
-1
@@ -167,7 +167,7 @@ class Dashboard(FileSystemEventHandler):
|
||||
# Can get on_modified events when the file is emptied
|
||||
self.process(event.src_path if not event.is_directory else None)
|
||||
|
||||
def process(self, logfile: str = None) -> None:
|
||||
def process(self, logfile: str | None = None) -> None:
|
||||
"""
|
||||
Process the contents of current Status.json file.
|
||||
|
||||
|
||||
+10
-3
@@ -119,10 +119,17 @@ JSON primitives and their python equivalents
|
||||
json compound types (`object -- {}` and `array -- []`) may be set.
|
||||
|
||||
### Testing
|
||||
You can supply a custom killswitches file for testing against
|
||||
EDMarketConnector:
|
||||
```bash
|
||||
python EDMarketConnector.py --killswitches-file <filename>
|
||||
```
|
||||
This will be relative to the CWD of the process.
|
||||
|
||||
Killswitch files can be tested using the script in `scripts/killswitch_test.py`.
|
||||
Providing a file as an argument or `-` for stdin will output the behaviour of
|
||||
the provided file, including indicating typos, if applicable.
|
||||
Alternatively, killswitch files can be independently tested using the script in
|
||||
`scripts/killswitch_test.py`. Providing a file as an argument or `-` for stdin
|
||||
will output the behaviour of the provided file, including indicating typos, if
|
||||
applicable.
|
||||
|
||||
### Versions
|
||||
|
||||
|
||||
+11
-9
@@ -191,15 +191,17 @@ that it's actually included in the installer.
|
||||
Before you create a new install each time you should:
|
||||
|
||||
1. Ensure the data sourced from coriolis.io is up to date and works:
|
||||
1. Update the `coriolis-data` repo. **NB: You will need 'npm' installed for
|
||||
this.**
|
||||
1. `cd coriolis-data`
|
||||
1. `git pull`
|
||||
1. `npm install` - to check it's worked.
|
||||
1. Run `coriolis.py` to update `modules.p` and `ships.p`
|
||||
1. XXX: Test ?
|
||||
1. `git commit` the changes to the repo and the `.p` files.
|
||||
1. Ensure translations are up to date, see [Translations.md](Translations.md).
|
||||
2. Update the `coriolis-data` repo. **NB: You will need 'npm' installed for
|
||||
this.**
|
||||
1. `cd coriolis-data`
|
||||
2. `git pull`
|
||||
3. `npm install` - to check it's worked.
|
||||
3. Run `coriolis-update-files.py` to update `modules.p` and `ships.p`. **NB:
|
||||
The submodule might have been updated by a GitHub workflow/PR/merge, so
|
||||
be sure to perform this step for every build.**
|
||||
4. XXX: Test ?
|
||||
5. `git commit` the changes to the repo and the `.p` files.
|
||||
6. Ensure translations are up to date, see [Translations.md](Translations.md).
|
||||
|
||||
# Preparing to Package
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ this is to include an XML-format .manifest file at build time.
|
||||
|
||||
## Build time
|
||||
|
||||
We specify .manifest files in setup.py.
|
||||
We specify .manifest files in `Build-exe-and-msi.py`.
|
||||
|
||||
## Editing or changing a manifest
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class ClickCounter:
|
||||
|
||||
def __init__(self) -> None:
|
||||
# Be sure to use names that wont collide in our config variables
|
||||
self.click_count: Optional[tk.StringVar] = tk.StringVar(value=str(config.get_int('click_counter_count')))
|
||||
self.click_count = tk.StringVar(value=str(config.get_int('click_counter_count')))
|
||||
logger.info("ClickCounter instantiated")
|
||||
|
||||
def on_load(self) -> str:
|
||||
@@ -99,8 +99,8 @@ class ClickCounter:
|
||||
)
|
||||
button.grid(row=current_row)
|
||||
current_row += 1
|
||||
nb.Label(frame, text="Count:").grid(row=current_row, sticky=tk.W)
|
||||
nb.Label(frame, textvariable=self.click_count).grid(row=current_row, column=1)
|
||||
tk.Label(frame, text="Count:").grid(row=current_row, sticky=tk.W)
|
||||
tk.Label(frame, textvariable=self.click_count).grid(row=current_row, column=1)
|
||||
return frame
|
||||
|
||||
|
||||
|
||||
@@ -13,19 +13,6 @@ from SubA import SubA
|
||||
|
||||
from config import appname, appversion, config
|
||||
|
||||
# For compatibility with pre-5.0.0
|
||||
if not hasattr(config, 'get_int'):
|
||||
config.get_int = config.getint
|
||||
|
||||
if not hasattr(config, 'get_str'):
|
||||
config.get_str = config.get
|
||||
|
||||
if not hasattr(config, 'get_bool'):
|
||||
config.get_bool = lambda key: bool(config.getint(key))
|
||||
|
||||
if not hasattr(config, 'get_list'):
|
||||
config.get_list = config.get
|
||||
|
||||
# This could also be returned from plugin_start3()
|
||||
plugin_name = os.path.basename(os.path.dirname(__file__))
|
||||
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ def export(data, filename=None) -> None: # noqa: C901, CCR001
|
||||
if not v:
|
||||
continue
|
||||
|
||||
module: __Module = outfitting.lookup(v['module'], ship_map)
|
||||
module: __Module | None = outfitting.lookup(v['module'], ship_map)
|
||||
if not module:
|
||||
continue
|
||||
|
||||
|
||||
@@ -1,703 +0,0 @@
|
||||
"""Handle keyboard input for manual update triggering."""
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import abc
|
||||
import pathlib
|
||||
import sys
|
||||
import tkinter as tk
|
||||
from abc import abstractmethod
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
from config import config
|
||||
from EDMCLogging import get_main_logger
|
||||
|
||||
logger = get_main_logger()
|
||||
|
||||
|
||||
class AbstractHotkeyMgr(abc.ABC):
|
||||
"""Abstract root class of all platforms specific HotKeyMgr."""
|
||||
|
||||
@abstractmethod
|
||||
def register(self, root, keycode, modifiers) -> None:
|
||||
"""Register the hotkey handler."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def unregister(self) -> None:
|
||||
"""Unregister the hotkey handling."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def play_good(self) -> None:
|
||||
"""Play the 'good' sound."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def play_bad(self) -> None:
|
||||
"""Play the 'bad' sound."""
|
||||
pass
|
||||
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
|
||||
import objc
|
||||
from AppKit import (
|
||||
NSAlternateKeyMask, NSApplication, NSBeep, NSClearLineFunctionKey, NSCommandKeyMask, NSControlKeyMask,
|
||||
NSDeleteFunctionKey, NSDeviceIndependentModifierFlagsMask, NSEvent, NSF1FunctionKey, NSF35FunctionKey,
|
||||
NSFlagsChanged, NSKeyDown, NSKeyDownMask, NSKeyUp, NSNumericPadKeyMask, NSShiftKeyMask, NSSound, NSWorkspace
|
||||
)
|
||||
|
||||
|
||||
class MacHotkeyMgr(AbstractHotkeyMgr):
|
||||
"""Hot key management."""
|
||||
|
||||
POLL = 250
|
||||
# https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/#//apple_ref/doc/constant_group/Function_Key_Unicodes
|
||||
DISPLAY = {
|
||||
0x03: u'⌅', 0x09: u'⇥', 0xd: u'↩', 0x19: u'⇤', 0x1b: u'esc', 0x20: u'⏘', 0x7f: u'⌫',
|
||||
0xf700: u'↑', 0xf701: u'↓', 0xf702: u'←', 0xf703: u'→',
|
||||
0xf727: u'Ins',
|
||||
0xf728: u'⌦', 0xf729: u'↖', 0xf72a: u'Fn', 0xf72b: u'↘',
|
||||
0xf72c: u'⇞', 0xf72d: u'⇟', 0xf72e: u'PrtScr', 0xf72f: u'ScrollLock',
|
||||
0xf730: u'Pause', 0xf731: u'SysReq', 0xf732: u'Break', 0xf733: u'Reset',
|
||||
0xf739: u'⌧',
|
||||
}
|
||||
(ACQUIRE_INACTIVE, ACQUIRE_ACTIVE, ACQUIRE_NEW) = range(3)
|
||||
|
||||
def __init__(self):
|
||||
self.MODIFIERMASK = NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask \
|
||||
| NSNumericPadKeyMask
|
||||
self.root = None
|
||||
|
||||
self.keycode = 0
|
||||
self.modifiers = 0
|
||||
self.activated = False
|
||||
self.observer = None
|
||||
|
||||
self.acquire_key = 0
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
|
||||
self.tkProcessKeyEvent_old = None
|
||||
|
||||
self.snd_good = NSSound.alloc().initWithContentsOfFile_byReference_(
|
||||
pathlib.Path(config.respath_path) / 'snd_good.wav', False
|
||||
)
|
||||
self.snd_bad = NSSound.alloc().initWithContentsOfFile_byReference_(
|
||||
pathlib.Path(config.respath_path) / 'snd_bad.wav', False
|
||||
)
|
||||
|
||||
def register(self, root: tk.Tk, keycode, modifiers) -> None:
|
||||
"""
|
||||
Register current hotkey for monitoring.
|
||||
|
||||
:param root: parent window.
|
||||
:param keycode: Key to monitor.
|
||||
:param modifiers: Any modifiers to take into account.
|
||||
"""
|
||||
self.root = root
|
||||
self.keycode = keycode
|
||||
self.modifiers = modifiers
|
||||
self.activated = False
|
||||
|
||||
if keycode:
|
||||
if not self.observer:
|
||||
self.root.after_idle(self._observe)
|
||||
self.root.after(MacHotkeyMgr.POLL, self._poll)
|
||||
|
||||
# Monkey-patch tk (tkMacOSXKeyEvent.c)
|
||||
if not self.tkProcessKeyEvent_old:
|
||||
sel = b'tkProcessKeyEvent:'
|
||||
cls = NSApplication.sharedApplication().class__() # type: ignore
|
||||
self.tkProcessKeyEvent_old = NSApplication.sharedApplication().methodForSelector_(sel) # type: ignore
|
||||
newmethod = objc.selector( # type: ignore
|
||||
self.tkProcessKeyEvent,
|
||||
selector=self.tkProcessKeyEvent_old.selector,
|
||||
signature=self.tkProcessKeyEvent_old.signature
|
||||
)
|
||||
objc.classAddMethod(cls, sel, newmethod) # type: ignore
|
||||
|
||||
def tkProcessKeyEvent(self, cls, the_event): # noqa: N802
|
||||
"""
|
||||
Monkey-patch tk (tkMacOSXKeyEvent.c).
|
||||
|
||||
- workaround crash on OSX 10.9 & 10.10 on seeing a composing character
|
||||
- notice when modifier key state changes
|
||||
- keep a copy of NSEvent.charactersIgnoringModifiers, which is what we need for the hotkey
|
||||
|
||||
(Would like to use a decorator but need to ensure the application is created before this is installed)
|
||||
:param cls: ???
|
||||
:param the_event: tk event
|
||||
:return: ???
|
||||
"""
|
||||
if self.acquire_state:
|
||||
if the_event.type() == NSFlagsChanged:
|
||||
self.acquire_key = the_event.modifierFlags() & NSDeviceIndependentModifierFlagsMask
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_NEW
|
||||
# suppress the event by not chaining the old function
|
||||
return the_event
|
||||
|
||||
elif the_event.type() in (NSKeyDown, NSKeyUp):
|
||||
c = the_event.charactersIgnoringModifiers()
|
||||
self.acquire_key = (c and ord(c[0]) or 0) | \
|
||||
(the_event.modifierFlags() & NSDeviceIndependentModifierFlagsMask)
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_NEW
|
||||
# suppress the event by not chaining the old function
|
||||
return the_event
|
||||
|
||||
# replace empty characters with charactersIgnoringModifiers to avoid crash
|
||||
elif the_event.type() in (NSKeyDown, NSKeyUp) and not the_event.characters():
|
||||
the_event = NSEvent.keyEventWithType_location_modifierFlags_timestamp_windowNumber_context_characters_charactersIgnoringModifiers_isARepeat_keyCode_( # noqa: E501
|
||||
# noqa: E501
|
||||
the_event.type(),
|
||||
the_event.locationInWindow(),
|
||||
the_event.modifierFlags(),
|
||||
the_event.timestamp(),
|
||||
the_event.windowNumber(),
|
||||
the_event.context(),
|
||||
the_event.charactersIgnoringModifiers(),
|
||||
the_event.charactersIgnoringModifiers(),
|
||||
the_event.isARepeat(),
|
||||
the_event.keyCode()
|
||||
)
|
||||
return self.tkProcessKeyEvent_old(cls, the_event)
|
||||
|
||||
def _observe(self):
|
||||
# Must be called after root.mainloop() so that the app's message loop has been created
|
||||
self.observer = NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSKeyDownMask, self._handler)
|
||||
|
||||
def _poll(self):
|
||||
if config.shutting_down:
|
||||
return
|
||||
|
||||
# No way of signalling to Tkinter from within the callback handler block that doesn't
|
||||
# cause Python to crash, so poll.
|
||||
if self.activated:
|
||||
self.activated = False
|
||||
self.root.event_generate('<<Invoke>>', when="tail")
|
||||
|
||||
if self.keycode or self.modifiers:
|
||||
self.root.after(MacHotkeyMgr.POLL, self._poll)
|
||||
|
||||
def unregister(self) -> None:
|
||||
"""Remove hotkey registration."""
|
||||
self.keycode = None
|
||||
self.modifiers = None
|
||||
|
||||
if sys.platform == 'darwin': # noqa: C901
|
||||
@objc.callbackFor(NSEvent.addGlobalMonitorForEventsMatchingMask_handler_)
|
||||
def _handler(self, event) -> None:
|
||||
# use event.charactersIgnoringModifiers to handle composing characters like Alt-e
|
||||
if ((event.modifierFlags() & self.MODIFIERMASK) == self.modifiers
|
||||
and ord(event.charactersIgnoringModifiers()[0]) == self.keycode):
|
||||
if config.get_int('hotkey_always'):
|
||||
self.activated = True
|
||||
|
||||
else: # Only trigger if game client is front process
|
||||
front = NSWorkspace.sharedWorkspace().frontmostApplication()
|
||||
if front and front.bundleIdentifier() == 'uk.co.frontier.EliteDangerous':
|
||||
self.activated = True
|
||||
|
||||
def acquire_start(self) -> None:
|
||||
"""Start acquiring hotkey state via polling."""
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_ACTIVE
|
||||
self.root.after_idle(self._acquire_poll)
|
||||
|
||||
def acquire_stop(self) -> None:
|
||||
"""Stop acquiring hotkey state."""
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
|
||||
def _acquire_poll(self) -> None:
|
||||
"""Perform a poll of current hotkey state."""
|
||||
if config.shutting_down:
|
||||
return
|
||||
|
||||
# No way of signalling to Tkinter from within the monkey-patched event handler that doesn't
|
||||
# cause Python to crash, so poll.
|
||||
if self.acquire_state:
|
||||
if self.acquire_state == MacHotkeyMgr.ACQUIRE_NEW:
|
||||
# Abuse tkEvent's keycode field to hold our acquired key & modifier
|
||||
self.root.event_generate('<KeyPress>', keycode=self.acquire_key)
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_ACTIVE
|
||||
self.root.after(50, self._acquire_poll)
|
||||
|
||||
def fromevent(self, event) -> Optional[Union[bool, Tuple]]:
|
||||
"""
|
||||
Return configuration (keycode, modifiers) or None=clear or False=retain previous.
|
||||
|
||||
:param event: tk event ?
|
||||
:return: False to retain previous, None to not use, else (keycode, modifiers)
|
||||
"""
|
||||
(keycode, modifiers) = (event.keycode & 0xffff, event.keycode & 0xffff0000) # Set by _acquire_poll()
|
||||
if (keycode
|
||||
and not (modifiers & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask))):
|
||||
if keycode == 0x1b: # Esc = retain previous
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
return False
|
||||
|
||||
# BkSp, Del, Clear = clear hotkey
|
||||
elif keycode in [0x7f, ord(NSDeleteFunctionKey), ord(NSClearLineFunctionKey)]:
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
return None
|
||||
|
||||
# don't allow keys needed for typing in System Map
|
||||
elif keycode in [0x13, 0x20, 0x2d] or 0x61 <= keycode <= 0x7a:
|
||||
NSBeep()
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
return None
|
||||
|
||||
return (keycode, modifiers)
|
||||
|
||||
def display(self, keycode, modifiers) -> str:
|
||||
"""
|
||||
Return displayable form of given hotkey + modifiers.
|
||||
|
||||
:param keycode:
|
||||
:param modifiers:
|
||||
:return: string form
|
||||
"""
|
||||
text = ''
|
||||
if modifiers & NSControlKeyMask:
|
||||
text += u'⌃'
|
||||
|
||||
if modifiers & NSAlternateKeyMask:
|
||||
text += u'⌥'
|
||||
|
||||
if modifiers & NSShiftKeyMask:
|
||||
text += u'⇧'
|
||||
|
||||
if modifiers & NSCommandKeyMask:
|
||||
text += u'⌘'
|
||||
|
||||
if (modifiers & NSNumericPadKeyMask) and keycode <= 0x7f:
|
||||
text += u'№'
|
||||
|
||||
if not keycode:
|
||||
pass
|
||||
|
||||
elif ord(NSF1FunctionKey) <= keycode <= ord(NSF35FunctionKey):
|
||||
text += f'F{keycode + 1 - ord(NSF1FunctionKey)}'
|
||||
|
||||
elif keycode in MacHotkeyMgr.DISPLAY: # specials
|
||||
text += MacHotkeyMgr.DISPLAY[keycode]
|
||||
|
||||
elif keycode < 0x20: # control keys
|
||||
text += chr(keycode + 0x40)
|
||||
|
||||
elif keycode < 0xf700: # key char
|
||||
text += chr(keycode).upper()
|
||||
|
||||
else:
|
||||
text += u'⁈'
|
||||
|
||||
return text
|
||||
|
||||
def play_good(self):
|
||||
"""Play the 'good' sound."""
|
||||
self.snd_good.play()
|
||||
|
||||
def play_bad(self):
|
||||
"""Play the 'bad' sound."""
|
||||
self.snd_bad.play()
|
||||
|
||||
|
||||
if sys.platform == 'win32':
|
||||
|
||||
import atexit
|
||||
import ctypes
|
||||
import threading
|
||||
import winsound
|
||||
from ctypes.wintypes import DWORD, HWND, LONG, LPWSTR, MSG, ULONG, WORD
|
||||
|
||||
RegisterHotKey = ctypes.windll.user32.RegisterHotKey
|
||||
UnregisterHotKey = ctypes.windll.user32.UnregisterHotKey
|
||||
MOD_ALT = 0x0001
|
||||
MOD_CONTROL = 0x0002
|
||||
MOD_SHIFT = 0x0004
|
||||
MOD_WIN = 0x0008
|
||||
MOD_NOREPEAT = 0x4000
|
||||
|
||||
GetMessage = ctypes.windll.user32.GetMessageW
|
||||
TranslateMessage = ctypes.windll.user32.TranslateMessage
|
||||
DispatchMessage = ctypes.windll.user32.DispatchMessageW
|
||||
PostThreadMessage = ctypes.windll.user32.PostThreadMessageW
|
||||
WM_QUIT = 0x0012
|
||||
WM_HOTKEY = 0x0312
|
||||
WM_APP = 0x8000
|
||||
WM_SND_GOOD = WM_APP + 1
|
||||
WM_SND_BAD = WM_APP + 2
|
||||
|
||||
GetKeyState = ctypes.windll.user32.GetKeyState
|
||||
MapVirtualKey = ctypes.windll.user32.MapVirtualKeyW
|
||||
VK_BACK = 0x08
|
||||
VK_CLEAR = 0x0c
|
||||
VK_RETURN = 0x0d
|
||||
VK_SHIFT = 0x10
|
||||
VK_CONTROL = 0x11
|
||||
VK_MENU = 0x12
|
||||
VK_CAPITAL = 0x14
|
||||
VK_MODECHANGE = 0x1f
|
||||
VK_ESCAPE = 0x1b
|
||||
VK_SPACE = 0x20
|
||||
VK_DELETE = 0x2e
|
||||
VK_LWIN = 0x5b
|
||||
VK_RWIN = 0x5c
|
||||
VK_NUMPAD0 = 0x60
|
||||
VK_DIVIDE = 0x6f
|
||||
VK_F1 = 0x70
|
||||
VK_F24 = 0x87
|
||||
VK_OEM_MINUS = 0xbd
|
||||
VK_NUMLOCK = 0x90
|
||||
VK_SCROLL = 0x91
|
||||
VK_PROCESSKEY = 0xe5
|
||||
VK_OEM_CLEAR = 0xfe
|
||||
|
||||
GetForegroundWindow = ctypes.windll.user32.GetForegroundWindow
|
||||
GetWindowText = ctypes.windll.user32.GetWindowTextW
|
||||
GetWindowText.argtypes = [HWND, LPWSTR, ctypes.c_int]
|
||||
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
|
||||
|
||||
def window_title(h) -> str:
|
||||
"""
|
||||
Determine the title for a window.
|
||||
|
||||
:param h: Window handle.
|
||||
:return: Window title.
|
||||
"""
|
||||
if h:
|
||||
title_length = GetWindowTextLength(h) + 1
|
||||
buf = ctypes.create_unicode_buffer(title_length)
|
||||
if GetWindowText(h, buf, title_length):
|
||||
return buf.value
|
||||
|
||||
return ''
|
||||
|
||||
class MOUSEINPUT(ctypes.Structure):
|
||||
"""Mouse Input structure."""
|
||||
|
||||
_fields_ = [
|
||||
('dx', LONG),
|
||||
('dy', LONG),
|
||||
('mouseData', DWORD),
|
||||
('dwFlags', DWORD),
|
||||
('time', DWORD),
|
||||
('dwExtraInfo', ctypes.POINTER(ULONG))
|
||||
]
|
||||
|
||||
class KEYBDINPUT(ctypes.Structure):
|
||||
"""Keyboard Input structure."""
|
||||
|
||||
_fields_ = [
|
||||
('wVk', WORD),
|
||||
('wScan', WORD),
|
||||
('dwFlags', DWORD),
|
||||
('time', DWORD),
|
||||
('dwExtraInfo', ctypes.POINTER(ULONG))
|
||||
]
|
||||
|
||||
class HARDWAREINPUT(ctypes.Structure):
|
||||
"""Hardware Input structure."""
|
||||
|
||||
_fields_ = [
|
||||
('uMsg', DWORD),
|
||||
('wParamL', WORD),
|
||||
('wParamH', WORD)
|
||||
]
|
||||
|
||||
class INPUTUNION(ctypes.Union):
|
||||
"""Input union."""
|
||||
|
||||
_fields_ = [
|
||||
('mi', MOUSEINPUT),
|
||||
('ki', KEYBDINPUT),
|
||||
('hi', HARDWAREINPUT)
|
||||
]
|
||||
|
||||
class INPUT(ctypes.Structure):
|
||||
"""Input structure."""
|
||||
|
||||
_fields_ = [
|
||||
('type', DWORD),
|
||||
('union', INPUTUNION)
|
||||
]
|
||||
|
||||
SendInput = ctypes.windll.user32.SendInput
|
||||
SendInput.argtypes = [ctypes.c_uint, ctypes.POINTER(INPUT), ctypes.c_int]
|
||||
|
||||
INPUT_MOUSE = 0
|
||||
INPUT_KEYBOARD = 1
|
||||
INPUT_HARDWARE = 2
|
||||
|
||||
|
||||
class WindowsHotkeyMgr(AbstractHotkeyMgr):
|
||||
"""Hot key management."""
|
||||
|
||||
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
|
||||
# Limit ourselves to symbols in Windows 7 Segoe UI
|
||||
DISPLAY = {
|
||||
0x03: 'Break', 0x08: 'Bksp', 0x09: u'↹', 0x0c: 'Clear', 0x0d: u'↵', 0x13: 'Pause',
|
||||
0x14: u'Ⓐ', 0x1b: 'Esc',
|
||||
0x20: u'⏘', 0x21: 'PgUp', 0x22: 'PgDn', 0x23: 'End', 0x24: 'Home',
|
||||
0x25: u'←', 0x26: u'↑', 0x27: u'→', 0x28: u'↓',
|
||||
0x2c: 'PrtScn', 0x2d: 'Ins', 0x2e: 'Del', 0x2f: 'Help',
|
||||
0x5d: u'▤', 0x5f: u'☾',
|
||||
0x90: u'➀', 0x91: 'ScrLk',
|
||||
0xa6: u'⇦', 0xa7: u'⇨', 0xa9: u'⊗', 0xab: u'☆', 0xac: u'⌂', 0xb4: u'✉',
|
||||
}
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.root: tk.Tk = None # type: ignore
|
||||
self.thread: threading.Thread = None # type: ignore
|
||||
with open(pathlib.Path(config.respath) / 'snd_good.wav', 'rb') as sg:
|
||||
self.snd_good = sg.read()
|
||||
with open(pathlib.Path(config.respath) / 'snd_bad.wav', 'rb') as sb:
|
||||
self.snd_bad = sb.read()
|
||||
atexit.register(self.unregister)
|
||||
|
||||
def register(self, root: tk.Tk, keycode, modifiers) -> None:
|
||||
"""Register the hotkey handler."""
|
||||
self.root = root
|
||||
|
||||
if self.thread:
|
||||
logger.debug('Was already registered, unregistering...')
|
||||
self.unregister()
|
||||
|
||||
if keycode or modifiers:
|
||||
logger.debug('Creating thread worker...')
|
||||
self.thread = threading.Thread(
|
||||
target=self.worker,
|
||||
name=f'Hotkey "{keycode}:{modifiers}"',
|
||||
args=(keycode, modifiers)
|
||||
)
|
||||
self.thread.daemon = True
|
||||
logger.debug('Starting thread worker...')
|
||||
self.thread.start()
|
||||
logger.debug('Done.')
|
||||
|
||||
def unregister(self) -> None:
|
||||
"""Unregister the hotkey handling."""
|
||||
thread = self.thread
|
||||
|
||||
if thread:
|
||||
logger.debug('Thread is/was running')
|
||||
self.thread = None # type: ignore
|
||||
logger.debug('Telling thread WM_QUIT')
|
||||
PostThreadMessage(thread.ident, WM_QUIT, 0, 0)
|
||||
logger.debug('Joining thread')
|
||||
thread.join() # Wait for it to unregister hotkey and quit
|
||||
|
||||
else:
|
||||
logger.debug('No thread')
|
||||
|
||||
logger.debug('Done.')
|
||||
|
||||
def worker(self, keycode, modifiers) -> None: # noqa: CCR001
|
||||
"""Handle hotkeys."""
|
||||
logger.debug('Begin...')
|
||||
# Hotkey must be registered by the thread that handles it
|
||||
if not RegisterHotKey(None, 1, modifiers | MOD_NOREPEAT, keycode):
|
||||
logger.debug("We're not the right thread?")
|
||||
self.thread = None # type: ignore
|
||||
return
|
||||
|
||||
fake = INPUT(INPUT_KEYBOARD, INPUTUNION(ki=KEYBDINPUT(keycode, keycode, 0, 0, None)))
|
||||
|
||||
msg = MSG()
|
||||
logger.debug('Entering GetMessage() loop...')
|
||||
while GetMessage(ctypes.byref(msg), None, 0, 0) != 0:
|
||||
logger.debug('Got message')
|
||||
if msg.message == WM_HOTKEY:
|
||||
logger.debug('WM_HOTKEY')
|
||||
|
||||
if (
|
||||
config.get_int('hotkey_always')
|
||||
or window_title(GetForegroundWindow()).startswith('Elite - Dangerous')
|
||||
):
|
||||
if not config.shutting_down:
|
||||
logger.debug('Sending event <<Invoke>>')
|
||||
self.root.event_generate('<<Invoke>>', when="tail")
|
||||
|
||||
else:
|
||||
logger.debug('Passing key on')
|
||||
UnregisterHotKey(None, 1)
|
||||
SendInput(1, fake, ctypes.sizeof(INPUT))
|
||||
if not RegisterHotKey(None, 1, modifiers | MOD_NOREPEAT, keycode):
|
||||
logger.debug("We aren't registered for this ?")
|
||||
break
|
||||
|
||||
elif msg.message == WM_SND_GOOD:
|
||||
logger.debug('WM_SND_GOOD')
|
||||
winsound.PlaySound(self.snd_good, winsound.SND_MEMORY) # synchronous
|
||||
|
||||
elif msg.message == WM_SND_BAD:
|
||||
logger.debug('WM_SND_BAD')
|
||||
winsound.PlaySound(self.snd_bad, winsound.SND_MEMORY) # synchronous
|
||||
|
||||
else:
|
||||
logger.debug('Something else')
|
||||
TranslateMessage(ctypes.byref(msg))
|
||||
DispatchMessage(ctypes.byref(msg))
|
||||
|
||||
logger.debug('Exited GetMessage() loop.')
|
||||
UnregisterHotKey(None, 1)
|
||||
self.thread = None # type: ignore
|
||||
logger.debug('Done.')
|
||||
|
||||
def acquire_start(self) -> None:
|
||||
"""Start acquiring hotkey state via polling."""
|
||||
pass
|
||||
|
||||
def acquire_stop(self) -> None:
|
||||
"""Stop acquiring hotkey state."""
|
||||
pass
|
||||
|
||||
def fromevent(self, event) -> Optional[Union[bool, Tuple]]: # noqa: CCR001
|
||||
"""
|
||||
Return configuration (keycode, modifiers) or None=clear or False=retain previous.
|
||||
|
||||
event.state is a pain - it shows the state of the modifiers *before* a modifier key was pressed.
|
||||
event.state *does* differentiate between left and right Ctrl and Alt and between Return and Enter
|
||||
by putting KF_EXTENDED in bit 18, but RegisterHotKey doesn't differentiate.
|
||||
|
||||
:param event: tk event ?
|
||||
:return: False to retain previous, None to not use, else (keycode, modifiers)
|
||||
"""
|
||||
modifiers = ((GetKeyState(VK_MENU) & 0x8000) and MOD_ALT) \
|
||||
| ((GetKeyState(VK_CONTROL) & 0x8000) and MOD_CONTROL) \
|
||||
| ((GetKeyState(VK_SHIFT) & 0x8000) and MOD_SHIFT) \
|
||||
| ((GetKeyState(VK_LWIN) & 0x8000) and MOD_WIN) \
|
||||
| ((GetKeyState(VK_RWIN) & 0x8000) and MOD_WIN)
|
||||
keycode = event.keycode
|
||||
|
||||
if keycode in [VK_SHIFT, VK_CONTROL, VK_MENU, VK_LWIN, VK_RWIN]:
|
||||
return (0, modifiers)
|
||||
|
||||
if not modifiers:
|
||||
if keycode == VK_ESCAPE: # Esc = retain previous
|
||||
return False
|
||||
|
||||
elif keycode in [VK_BACK, VK_DELETE, VK_CLEAR, VK_OEM_CLEAR]: # BkSp, Del, Clear = clear hotkey
|
||||
return None
|
||||
|
||||
elif keycode in [VK_RETURN, VK_SPACE, VK_OEM_MINUS] or ord('A') <= keycode <= ord(
|
||||
'Z'): # don't allow keys needed for typing in System Map
|
||||
winsound.MessageBeep()
|
||||
return None
|
||||
|
||||
elif (keycode in [VK_NUMLOCK, VK_SCROLL, VK_PROCESSKEY]
|
||||
or VK_CAPITAL <= keycode <= VK_MODECHANGE): # ignore unmodified mode switch keys
|
||||
return (0, modifiers)
|
||||
|
||||
# See if the keycode is usable and available
|
||||
if RegisterHotKey(None, 2, modifiers | MOD_NOREPEAT, keycode):
|
||||
UnregisterHotKey(None, 2)
|
||||
return (keycode, modifiers)
|
||||
|
||||
else:
|
||||
winsound.MessageBeep()
|
||||
return None
|
||||
|
||||
def display(self, keycode, modifiers) -> str:
|
||||
"""
|
||||
Return displayable form of given hotkey + modifiers.
|
||||
|
||||
:param keycode:
|
||||
:param modifiers:
|
||||
:return: string form
|
||||
"""
|
||||
text = ''
|
||||
if modifiers & MOD_WIN:
|
||||
text += u'❖+'
|
||||
|
||||
if modifiers & MOD_CONTROL:
|
||||
text += u'Ctrl+'
|
||||
|
||||
if modifiers & MOD_ALT:
|
||||
text += u'Alt+'
|
||||
|
||||
if modifiers & MOD_SHIFT:
|
||||
text += u'⇧+'
|
||||
|
||||
if VK_NUMPAD0 <= keycode <= VK_DIVIDE:
|
||||
text += u'№'
|
||||
|
||||
if not keycode:
|
||||
pass
|
||||
|
||||
elif VK_F1 <= keycode <= VK_F24:
|
||||
text += f'F{keycode + 1 - VK_F1}'
|
||||
|
||||
elif keycode in WindowsHotkeyMgr.DISPLAY: # specials
|
||||
text += WindowsHotkeyMgr.DISPLAY[keycode]
|
||||
|
||||
else:
|
||||
c = MapVirtualKey(keycode, 2) # printable ?
|
||||
if not c: # oops not printable
|
||||
text += u'⁈'
|
||||
|
||||
elif c < 0x20: # control keys
|
||||
text += chr(c + 0x40)
|
||||
|
||||
else:
|
||||
text += chr(c).upper()
|
||||
|
||||
return text
|
||||
|
||||
def play_good(self) -> None:
|
||||
"""Play the 'good' sound."""
|
||||
if self.thread:
|
||||
PostThreadMessage(self.thread.ident, WM_SND_GOOD, 0, 0)
|
||||
|
||||
def play_bad(self) -> None:
|
||||
"""Play the 'bad' sound."""
|
||||
if self.thread:
|
||||
PostThreadMessage(self.thread.ident, WM_SND_BAD, 0, 0)
|
||||
|
||||
|
||||
class LinuxHotKeyMgr(AbstractHotkeyMgr):
|
||||
"""
|
||||
Hot key management.
|
||||
|
||||
Not actually implemented on Linux. It's a no-op instead.
|
||||
"""
|
||||
|
||||
def register(self, root, keycode, modifiers) -> None:
|
||||
"""Register the hotkey handler."""
|
||||
pass
|
||||
|
||||
def unregister(self) -> None:
|
||||
"""Unregister the hotkey handling."""
|
||||
pass
|
||||
|
||||
def play_good(self) -> None:
|
||||
"""Play the 'good' sound."""
|
||||
pass
|
||||
|
||||
def play_bad(self) -> None:
|
||||
"""Play the 'bad' sound."""
|
||||
pass
|
||||
|
||||
|
||||
def get_hotkeymgr() -> AbstractHotkeyMgr:
|
||||
"""
|
||||
Determine platform-specific HotkeyMgr.
|
||||
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return: Appropriate class instance.
|
||||
:raises ValueError: If unsupported platform.
|
||||
"""
|
||||
if sys.platform == 'darwin':
|
||||
return MacHotkeyMgr()
|
||||
|
||||
elif sys.platform == 'win32':
|
||||
return WindowsHotkeyMgr()
|
||||
|
||||
elif sys.platform == 'linux':
|
||||
return LinuxHotKeyMgr()
|
||||
|
||||
else:
|
||||
raise ValueError(f'Unknown platform: {sys.platform}')
|
||||
|
||||
|
||||
# singleton
|
||||
hotkeymgr = get_hotkeymgr()
|
||||
@@ -0,0 +1,95 @@
|
||||
"""Handle keyboard input for manual update triggering."""
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import abc
|
||||
import sys
|
||||
from abc import abstractmethod
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
|
||||
class AbstractHotkeyMgr(abc.ABC):
|
||||
"""Abstract root class of all platforms specific HotKeyMgr."""
|
||||
|
||||
@abstractmethod
|
||||
def register(self, root, keycode, modifiers) -> None:
|
||||
"""Register the hotkey handler."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def unregister(self) -> None:
|
||||
"""Unregister the hotkey handling."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def acquire_start(self) -> None:
|
||||
"""Start acquiring hotkey state via polling."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def acquire_stop(self) -> None:
|
||||
"""Stop acquiring hotkey state."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def fromevent(self, event) -> Optional[Union[bool, Tuple]]:
|
||||
"""
|
||||
Return configuration (keycode, modifiers) or None=clear or False=retain previous.
|
||||
|
||||
event.state is a pain - it shows the state of the modifiers *before* a modifier key was pressed.
|
||||
event.state *does* differentiate between left and right Ctrl and Alt and between Return and Enter
|
||||
by putting KF_EXTENDED in bit 18, but RegisterHotKey doesn't differentiate.
|
||||
|
||||
:param event: tk event ?
|
||||
:return: False to retain previous, None to not use, else (keycode, modifiers)
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def display(self, keycode: int, modifiers: int) -> str:
|
||||
"""
|
||||
Return displayable form of given hotkey + modifiers.
|
||||
|
||||
:param keycode:
|
||||
:param modifiers:
|
||||
:return: string form
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def play_good(self) -> None:
|
||||
"""Play the 'good' sound."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def play_bad(self) -> None:
|
||||
"""Play the 'bad' sound."""
|
||||
pass
|
||||
|
||||
|
||||
def get_hotkeymgr() -> AbstractHotkeyMgr:
|
||||
"""
|
||||
Determine platform-specific HotkeyMgr.
|
||||
|
||||
:param args:
|
||||
:param kwargs:
|
||||
:return: Appropriate class instance.
|
||||
:raises ValueError: If unsupported platform.
|
||||
"""
|
||||
if sys.platform == 'darwin':
|
||||
from hotkey.darwin import MacHotkeyMgr
|
||||
return MacHotkeyMgr()
|
||||
|
||||
elif sys.platform == 'win32':
|
||||
from hotkey.windows import WindowsHotkeyMgr
|
||||
return WindowsHotkeyMgr()
|
||||
|
||||
elif sys.platform == 'linux':
|
||||
from hotkey.linux import LinuxHotKeyMgr
|
||||
return LinuxHotKeyMgr()
|
||||
|
||||
else:
|
||||
raise ValueError(f'Unknown platform: {sys.platform}')
|
||||
|
||||
|
||||
# singleton
|
||||
hotkeymgr = get_hotkeymgr()
|
||||
@@ -0,0 +1,274 @@
|
||||
"""darwin/macOS implementation of hotkey.AbstractHotkeyMgr."""
|
||||
import pathlib
|
||||
import sys
|
||||
import tkinter as tk
|
||||
from typing import Callable, Optional, Tuple, Union
|
||||
assert sys.platform == 'darwin'
|
||||
|
||||
import objc
|
||||
from AppKit import (
|
||||
NSAlternateKeyMask, NSApplication, NSBeep, NSClearLineFunctionKey, NSCommandKeyMask, NSControlKeyMask,
|
||||
NSDeleteFunctionKey, NSDeviceIndependentModifierFlagsMask, NSEvent, NSF1FunctionKey, NSF35FunctionKey,
|
||||
NSFlagsChanged, NSKeyDown, NSKeyDownMask, NSKeyUp, NSNumericPadKeyMask, NSShiftKeyMask, NSSound, NSWorkspace
|
||||
)
|
||||
|
||||
from config import config
|
||||
from EDMCLogging import get_main_logger
|
||||
from hotkey import AbstractHotkeyMgr
|
||||
|
||||
logger = get_main_logger()
|
||||
|
||||
|
||||
class MacHotkeyMgr(AbstractHotkeyMgr):
|
||||
"""Hot key management."""
|
||||
|
||||
POLL = 250
|
||||
# https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSEvent_Class/#//apple_ref/doc/constant_group/Function_Key_Unicodes
|
||||
DISPLAY = {
|
||||
0x03: u'⌅', 0x09: u'⇥', 0xd: u'↩', 0x19: u'⇤', 0x1b: u'esc', 0x20: u'⏘', 0x7f: u'⌫',
|
||||
0xf700: u'↑', 0xf701: u'↓', 0xf702: u'←', 0xf703: u'→',
|
||||
0xf727: u'Ins',
|
||||
0xf728: u'⌦', 0xf729: u'↖', 0xf72a: u'Fn', 0xf72b: u'↘',
|
||||
0xf72c: u'⇞', 0xf72d: u'⇟', 0xf72e: u'PrtScr', 0xf72f: u'ScrollLock',
|
||||
0xf730: u'Pause', 0xf731: u'SysReq', 0xf732: u'Break', 0xf733: u'Reset',
|
||||
0xf739: u'⌧',
|
||||
}
|
||||
(ACQUIRE_INACTIVE, ACQUIRE_ACTIVE, ACQUIRE_NEW) = range(3)
|
||||
|
||||
def __init__(self):
|
||||
self.MODIFIERMASK = NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask \
|
||||
| NSNumericPadKeyMask
|
||||
self.root: tk.Tk
|
||||
|
||||
self.keycode = 0
|
||||
self.modifiers = 0
|
||||
self.activated = False
|
||||
self.observer = None
|
||||
|
||||
self.acquire_key = 0
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
|
||||
self.tkProcessKeyEvent_old: Callable
|
||||
|
||||
self.snd_good = NSSound.alloc().initWithContentsOfFile_byReference_(
|
||||
pathlib.Path(config.respath_path) / 'snd_good.wav', False
|
||||
)
|
||||
self.snd_bad = NSSound.alloc().initWithContentsOfFile_byReference_(
|
||||
pathlib.Path(config.respath_path) / 'snd_bad.wav', False
|
||||
)
|
||||
|
||||
def register(self, root: tk.Tk, keycode: int, modifiers: int) -> None:
|
||||
"""
|
||||
Register current hotkey for monitoring.
|
||||
|
||||
:param root: parent window.
|
||||
:param keycode: Key to monitor.
|
||||
:param modifiers: Any modifiers to take into account.
|
||||
"""
|
||||
self.root = root
|
||||
self.keycode = keycode
|
||||
self.modifiers = modifiers
|
||||
self.activated = False
|
||||
|
||||
if keycode:
|
||||
if not self.observer:
|
||||
self.root.after_idle(self._observe)
|
||||
self.root.after(MacHotkeyMgr.POLL, self._poll)
|
||||
|
||||
# Monkey-patch tk (tkMacOSXKeyEvent.c)
|
||||
if not callable(self.tkProcessKeyEvent_old):
|
||||
sel = b'tkProcessKeyEvent:'
|
||||
cls = NSApplication.sharedApplication().class__() # type: ignore
|
||||
self.tkProcessKeyEvent_old = NSApplication.sharedApplication().methodForSelector_(sel) # type: ignore
|
||||
newmethod = objc.selector( # type: ignore
|
||||
self.tkProcessKeyEvent,
|
||||
selector=self.tkProcessKeyEvent_old.selector,
|
||||
signature=self.tkProcessKeyEvent_old.signature
|
||||
)
|
||||
objc.classAddMethod(cls, sel, newmethod) # type: ignore
|
||||
|
||||
def tkProcessKeyEvent(self, cls, the_event): # noqa: N802
|
||||
"""
|
||||
Monkey-patch tk (tkMacOSXKeyEvent.c).
|
||||
|
||||
- workaround crash on OSX 10.9 & 10.10 on seeing a composing character
|
||||
- notice when modifier key state changes
|
||||
- keep a copy of NSEvent.charactersIgnoringModifiers, which is what we need for the hotkey
|
||||
|
||||
(Would like to use a decorator but need to ensure the application is created before this is installed)
|
||||
:param cls: ???
|
||||
:param the_event: tk event
|
||||
:return: ???
|
||||
"""
|
||||
if self.acquire_state:
|
||||
if the_event.type() == NSFlagsChanged:
|
||||
self.acquire_key = the_event.modifierFlags() & NSDeviceIndependentModifierFlagsMask
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_NEW
|
||||
# suppress the event by not chaining the old function
|
||||
return the_event
|
||||
|
||||
elif the_event.type() in (NSKeyDown, NSKeyUp):
|
||||
c = the_event.charactersIgnoringModifiers()
|
||||
self.acquire_key = (c and ord(c[0]) or 0) | \
|
||||
(the_event.modifierFlags() & NSDeviceIndependentModifierFlagsMask)
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_NEW
|
||||
# suppress the event by not chaining the old function
|
||||
return the_event
|
||||
|
||||
# replace empty characters with charactersIgnoringModifiers to avoid crash
|
||||
elif the_event.type() in (NSKeyDown, NSKeyUp) and not the_event.characters():
|
||||
the_event = NSEvent.keyEventWithType_location_modifierFlags_timestamp_windowNumber_context_characters_charactersIgnoringModifiers_isARepeat_keyCode_( # noqa: E501
|
||||
# noqa: E501
|
||||
the_event.type(),
|
||||
the_event.locationInWindow(),
|
||||
the_event.modifierFlags(),
|
||||
the_event.timestamp(),
|
||||
the_event.windowNumber(),
|
||||
the_event.context(),
|
||||
the_event.charactersIgnoringModifiers(),
|
||||
the_event.charactersIgnoringModifiers(),
|
||||
the_event.isARepeat(),
|
||||
the_event.keyCode()
|
||||
)
|
||||
return self.tkProcessKeyEvent_old(cls, the_event)
|
||||
|
||||
def _observe(self):
|
||||
# Must be called after root.mainloop() so that the app's message loop has been created
|
||||
self.observer = NSEvent.addGlobalMonitorForEventsMatchingMask_handler_(NSKeyDownMask, self._handler)
|
||||
|
||||
def _poll(self):
|
||||
if config.shutting_down:
|
||||
return
|
||||
|
||||
# No way of signalling to Tkinter from within the callback handler block that doesn't
|
||||
# cause Python to crash, so poll.
|
||||
if self.activated:
|
||||
self.activated = False
|
||||
self.root.event_generate('<<Invoke>>', when="tail")
|
||||
|
||||
if self.keycode or self.modifiers:
|
||||
self.root.after(MacHotkeyMgr.POLL, self._poll)
|
||||
|
||||
def unregister(self) -> None:
|
||||
"""Remove hotkey registration."""
|
||||
self.keycode = 0
|
||||
self.modifiers = 0
|
||||
|
||||
@objc.callbackFor(NSEvent.addGlobalMonitorForEventsMatchingMask_handler_)
|
||||
def _handler(self, event) -> None:
|
||||
# use event.charactersIgnoringModifiers to handle composing characters like Alt-e
|
||||
if (
|
||||
(event.modifierFlags() & self.MODIFIERMASK) == self.modifiers
|
||||
and ord(event.charactersIgnoringModifiers()[0]) == self.keycode
|
||||
):
|
||||
if config.get_int('hotkey_always'):
|
||||
self.activated = True
|
||||
|
||||
else: # Only trigger if game client is front process
|
||||
front = NSWorkspace.sharedWorkspace().frontmostApplication()
|
||||
if front and front.bundleIdentifier() == 'uk.co.frontier.EliteDangerous':
|
||||
self.activated = True
|
||||
|
||||
def acquire_start(self) -> None:
|
||||
"""Start acquiring hotkey state via polling."""
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_ACTIVE
|
||||
self.root.after_idle(self._acquire_poll)
|
||||
|
||||
def acquire_stop(self) -> None:
|
||||
"""Stop acquiring hotkey state."""
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
|
||||
def _acquire_poll(self) -> None:
|
||||
"""Perform a poll of current hotkey state."""
|
||||
if config.shutting_down:
|
||||
return
|
||||
|
||||
# No way of signalling to Tkinter from within the monkey-patched event handler that doesn't
|
||||
# cause Python to crash, so poll.
|
||||
if self.acquire_state:
|
||||
if self.acquire_state == MacHotkeyMgr.ACQUIRE_NEW:
|
||||
# Abuse tkEvent's keycode field to hold our acquired key & modifier
|
||||
self.root.event_generate('<KeyPress>', keycode=self.acquire_key)
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_ACTIVE
|
||||
self.root.after(50, self._acquire_poll)
|
||||
|
||||
def fromevent(self, event) -> Optional[Union[bool, Tuple]]:
|
||||
"""
|
||||
Return configuration (keycode, modifiers) or None=clear or False=retain previous.
|
||||
|
||||
:param event: tk event ?
|
||||
:return: False to retain previous, None to not use, else (keycode, modifiers)
|
||||
"""
|
||||
(keycode, modifiers) = (event.keycode & 0xffff, event.keycode & 0xffff0000) # Set by _acquire_poll()
|
||||
if (
|
||||
keycode
|
||||
and not (modifiers & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask))
|
||||
):
|
||||
if keycode == 0x1b: # Esc = retain previous
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
return False
|
||||
|
||||
# BkSp, Del, Clear = clear hotkey
|
||||
elif keycode in [0x7f, ord(NSDeleteFunctionKey), ord(NSClearLineFunctionKey)]:
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
return None
|
||||
|
||||
# don't allow keys needed for typing in System Map
|
||||
elif keycode in [0x13, 0x20, 0x2d] or 0x61 <= keycode <= 0x7a:
|
||||
NSBeep()
|
||||
self.acquire_state = MacHotkeyMgr.ACQUIRE_INACTIVE
|
||||
return None
|
||||
|
||||
return (keycode, modifiers)
|
||||
|
||||
def display(self, keycode, modifiers) -> str:
|
||||
"""
|
||||
Return displayable form of given hotkey + modifiers.
|
||||
|
||||
:param keycode:
|
||||
:param modifiers:
|
||||
:return: string form
|
||||
"""
|
||||
text = ''
|
||||
if modifiers & NSControlKeyMask:
|
||||
text += u'⌃'
|
||||
|
||||
if modifiers & NSAlternateKeyMask:
|
||||
text += u'⌥'
|
||||
|
||||
if modifiers & NSShiftKeyMask:
|
||||
text += u'⇧'
|
||||
|
||||
if modifiers & NSCommandKeyMask:
|
||||
text += u'⌘'
|
||||
|
||||
if (modifiers & NSNumericPadKeyMask) and keycode <= 0x7f:
|
||||
text += u'№'
|
||||
|
||||
if not keycode:
|
||||
pass
|
||||
|
||||
elif ord(NSF1FunctionKey) <= keycode <= ord(NSF35FunctionKey):
|
||||
text += f'F{keycode + 1 - ord(NSF1FunctionKey)}'
|
||||
|
||||
elif keycode in MacHotkeyMgr.DISPLAY: # specials
|
||||
text += MacHotkeyMgr.DISPLAY[keycode]
|
||||
|
||||
elif keycode < 0x20: # control keys
|
||||
text += chr(keycode + 0x40)
|
||||
|
||||
elif keycode < 0xf700: # key char
|
||||
text += chr(keycode).upper()
|
||||
|
||||
else:
|
||||
text += u'⁈'
|
||||
|
||||
return text
|
||||
|
||||
def play_good(self):
|
||||
"""Play the 'good' sound."""
|
||||
self.snd_good.play()
|
||||
|
||||
def play_bad(self):
|
||||
"""Play the 'bad' sound."""
|
||||
self.snd_bad.play()
|
||||
@@ -0,0 +1,64 @@
|
||||
"""Linux implementation of hotkey.AbstractHotkeyMgr."""
|
||||
import sys
|
||||
|
||||
from EDMCLogging import get_main_logger
|
||||
from hotkey import AbstractHotkeyMgr
|
||||
|
||||
assert sys.platform == 'linux'
|
||||
|
||||
logger = get_main_logger()
|
||||
|
||||
|
||||
class LinuxHotKeyMgr(AbstractHotkeyMgr):
|
||||
"""
|
||||
Hot key management.
|
||||
|
||||
Not actually implemented on Linux. It's a no-op instead.
|
||||
"""
|
||||
|
||||
def register(self, root, keycode, modifiers) -> None:
|
||||
"""Register the hotkey handler."""
|
||||
pass
|
||||
|
||||
def unregister(self) -> None:
|
||||
"""Unregister the hotkey handling."""
|
||||
pass
|
||||
|
||||
def acquire_start(self) -> None:
|
||||
"""Start acquiring hotkey state via polling."""
|
||||
pass
|
||||
|
||||
def acquire_stop(self) -> None:
|
||||
"""Stop acquiring hotkey state."""
|
||||
pass
|
||||
|
||||
def fromevent(self, event) -> bool | tuple | None:
|
||||
"""
|
||||
Return configuration (keycode, modifiers) or None=clear or False=retain previous.
|
||||
|
||||
event.state is a pain - it shows the state of the modifiers *before* a modifier key was pressed.
|
||||
event.state *does* differentiate between left and right Ctrl and Alt and between Return and Enter
|
||||
by putting KF_EXTENDED in bit 18, but RegisterHotKey doesn't differentiate.
|
||||
|
||||
:param event: tk event ?
|
||||
:return: False to retain previous, None to not use, else (keycode, modifiers)
|
||||
"""
|
||||
pass
|
||||
|
||||
def display(self, keycode: int, modifiers: int) -> str:
|
||||
"""
|
||||
Return displayable form of given hotkey + modifiers.
|
||||
|
||||
:param keycode:
|
||||
:param modifiers:
|
||||
:return: string form
|
||||
"""
|
||||
return "Unsupported on linux"
|
||||
|
||||
def play_good(self) -> None:
|
||||
"""Play the 'good' sound."""
|
||||
pass
|
||||
|
||||
def play_bad(self) -> None:
|
||||
"""Play the 'bad' sound."""
|
||||
pass
|
||||
@@ -0,0 +1,370 @@
|
||||
"""Windows implementation of hotkey.AbstractHotkeyMgr."""
|
||||
import atexit
|
||||
import ctypes
|
||||
import pathlib
|
||||
import sys
|
||||
import threading
|
||||
import tkinter as tk
|
||||
import winsound
|
||||
from ctypes.wintypes import DWORD, HWND, LONG, LPWSTR, MSG, ULONG, WORD
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
from config import config
|
||||
from EDMCLogging import get_main_logger
|
||||
from hotkey import AbstractHotkeyMgr
|
||||
|
||||
assert sys.platform == 'win32'
|
||||
|
||||
logger = get_main_logger()
|
||||
|
||||
RegisterHotKey = ctypes.windll.user32.RegisterHotKey
|
||||
UnregisterHotKey = ctypes.windll.user32.UnregisterHotKey
|
||||
MOD_ALT = 0x0001
|
||||
MOD_CONTROL = 0x0002
|
||||
MOD_SHIFT = 0x0004
|
||||
MOD_WIN = 0x0008
|
||||
MOD_NOREPEAT = 0x4000
|
||||
|
||||
GetMessage = ctypes.windll.user32.GetMessageW
|
||||
TranslateMessage = ctypes.windll.user32.TranslateMessage
|
||||
DispatchMessage = ctypes.windll.user32.DispatchMessageW
|
||||
PostThreadMessage = ctypes.windll.user32.PostThreadMessageW
|
||||
WM_QUIT = 0x0012
|
||||
WM_HOTKEY = 0x0312
|
||||
WM_APP = 0x8000
|
||||
WM_SND_GOOD = WM_APP + 1
|
||||
WM_SND_BAD = WM_APP + 2
|
||||
|
||||
GetKeyState = ctypes.windll.user32.GetKeyState
|
||||
MapVirtualKey = ctypes.windll.user32.MapVirtualKeyW
|
||||
VK_BACK = 0x08
|
||||
VK_CLEAR = 0x0c
|
||||
VK_RETURN = 0x0d
|
||||
VK_SHIFT = 0x10
|
||||
VK_CONTROL = 0x11
|
||||
VK_MENU = 0x12
|
||||
VK_CAPITAL = 0x14
|
||||
VK_MODECHANGE = 0x1f
|
||||
VK_ESCAPE = 0x1b
|
||||
VK_SPACE = 0x20
|
||||
VK_DELETE = 0x2e
|
||||
VK_LWIN = 0x5b
|
||||
VK_RWIN = 0x5c
|
||||
VK_NUMPAD0 = 0x60
|
||||
VK_DIVIDE = 0x6f
|
||||
VK_F1 = 0x70
|
||||
VK_F24 = 0x87
|
||||
VK_OEM_MINUS = 0xbd
|
||||
VK_NUMLOCK = 0x90
|
||||
VK_SCROLL = 0x91
|
||||
VK_PROCESSKEY = 0xe5
|
||||
VK_OEM_CLEAR = 0xfe
|
||||
|
||||
GetForegroundWindow = ctypes.windll.user32.GetForegroundWindow
|
||||
GetWindowText = ctypes.windll.user32.GetWindowTextW
|
||||
GetWindowText.argtypes = [HWND, LPWSTR, ctypes.c_int]
|
||||
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
|
||||
|
||||
|
||||
def window_title(h) -> str:
|
||||
"""
|
||||
Determine the title for a window.
|
||||
|
||||
:param h: Window handle.
|
||||
:return: Window title.
|
||||
"""
|
||||
if h:
|
||||
title_length = GetWindowTextLength(h) + 1
|
||||
buf = ctypes.create_unicode_buffer(title_length)
|
||||
if GetWindowText(h, buf, title_length):
|
||||
return buf.value
|
||||
|
||||
return ''
|
||||
|
||||
|
||||
class MOUSEINPUT(ctypes.Structure):
|
||||
"""Mouse Input structure."""
|
||||
|
||||
_fields_ = [
|
||||
('dx', LONG),
|
||||
('dy', LONG),
|
||||
('mouseData', DWORD),
|
||||
('dwFlags', DWORD),
|
||||
('time', DWORD),
|
||||
('dwExtraInfo', ctypes.POINTER(ULONG))
|
||||
]
|
||||
|
||||
|
||||
class KEYBDINPUT(ctypes.Structure):
|
||||
"""Keyboard Input structure."""
|
||||
|
||||
_fields_ = [
|
||||
('wVk', WORD),
|
||||
('wScan', WORD),
|
||||
('dwFlags', DWORD),
|
||||
('time', DWORD),
|
||||
('dwExtraInfo', ctypes.POINTER(ULONG))
|
||||
]
|
||||
|
||||
|
||||
class HARDWAREINPUT(ctypes.Structure):
|
||||
"""Hardware Input structure."""
|
||||
|
||||
_fields_ = [
|
||||
('uMsg', DWORD),
|
||||
('wParamL', WORD),
|
||||
('wParamH', WORD)
|
||||
]
|
||||
|
||||
|
||||
class INPUTUNION(ctypes.Union):
|
||||
"""Input union."""
|
||||
|
||||
_fields_ = [
|
||||
('mi', MOUSEINPUT),
|
||||
('ki', KEYBDINPUT),
|
||||
('hi', HARDWAREINPUT)
|
||||
]
|
||||
|
||||
|
||||
class INPUT(ctypes.Structure):
|
||||
"""Input structure."""
|
||||
|
||||
_fields_ = [
|
||||
('type', DWORD),
|
||||
('union', INPUTUNION)
|
||||
]
|
||||
|
||||
|
||||
SendInput = ctypes.windll.user32.SendInput
|
||||
SendInput.argtypes = [ctypes.c_uint, ctypes.POINTER(INPUT), ctypes.c_int]
|
||||
|
||||
INPUT_MOUSE = 0
|
||||
INPUT_KEYBOARD = 1
|
||||
INPUT_HARDWARE = 2
|
||||
|
||||
|
||||
class WindowsHotkeyMgr(AbstractHotkeyMgr):
|
||||
"""Hot key management."""
|
||||
|
||||
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
|
||||
# Limit ourselves to symbols in Windows 7 Segoe UI
|
||||
DISPLAY = {
|
||||
0x03: 'Break', 0x08: 'Bksp', 0x09: '↹', 0x0c: 'Clear', 0x0d: '↵', 0x13: 'Pause',
|
||||
0x14: 'Ⓐ', 0x1b: 'Esc',
|
||||
0x20: '⏘', 0x21: 'PgUp', 0x22: 'PgDn', 0x23: 'End', 0x24: 'Home',
|
||||
0x25: '←', 0x26: '↑', 0x27: '→', 0x28: '↓',
|
||||
0x2c: 'PrtScn', 0x2d: 'Ins', 0x2e: 'Del', 0x2f: 'Help',
|
||||
0x5d: '▤', 0x5f: '☾',
|
||||
0x90: '➀', 0x91: 'ScrLk',
|
||||
0xa6: '⇦', 0xa7: '⇨', 0xa9: '⊗', 0xab: '☆', 0xac: '⌂', 0xb4: '✉',
|
||||
}
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.root: tk.Tk = None # type: ignore
|
||||
self.thread: threading.Thread = None # type: ignore
|
||||
with open(pathlib.Path(config.respath) / 'snd_good.wav', 'rb') as sg:
|
||||
self.snd_good = sg.read()
|
||||
with open(pathlib.Path(config.respath) / 'snd_bad.wav', 'rb') as sb:
|
||||
self.snd_bad = sb.read()
|
||||
atexit.register(self.unregister)
|
||||
|
||||
def register(self, root: tk.Tk, keycode, modifiers) -> None:
|
||||
"""Register the hotkey handler."""
|
||||
self.root = root
|
||||
|
||||
if self.thread:
|
||||
logger.debug('Was already registered, unregistering...')
|
||||
self.unregister()
|
||||
|
||||
if keycode or modifiers:
|
||||
logger.debug('Creating thread worker...')
|
||||
self.thread = threading.Thread(
|
||||
target=self.worker,
|
||||
name=f'Hotkey "{keycode}:{modifiers}"',
|
||||
args=(keycode, modifiers)
|
||||
)
|
||||
self.thread.daemon = True
|
||||
logger.debug('Starting thread worker...')
|
||||
self.thread.start()
|
||||
logger.debug('Done.')
|
||||
|
||||
def unregister(self) -> None:
|
||||
"""Unregister the hotkey handling."""
|
||||
thread = self.thread
|
||||
|
||||
if thread:
|
||||
logger.debug('Thread is/was running')
|
||||
self.thread = None # type: ignore
|
||||
logger.debug('Telling thread WM_QUIT')
|
||||
PostThreadMessage(thread.ident, WM_QUIT, 0, 0)
|
||||
logger.debug('Joining thread')
|
||||
thread.join() # Wait for it to unregister hotkey and quit
|
||||
|
||||
else:
|
||||
logger.debug('No thread')
|
||||
|
||||
logger.debug('Done.')
|
||||
|
||||
def worker(self, keycode, modifiers) -> None: # noqa: CCR001
|
||||
"""Handle hotkeys."""
|
||||
logger.debug('Begin...')
|
||||
# Hotkey must be registered by the thread that handles it
|
||||
if not RegisterHotKey(None, 1, modifiers | MOD_NOREPEAT, keycode):
|
||||
logger.debug("We're not the right thread?")
|
||||
self.thread = None # type: ignore
|
||||
return
|
||||
|
||||
fake = INPUT(INPUT_KEYBOARD, INPUTUNION(ki=KEYBDINPUT(keycode, keycode, 0, 0, None)))
|
||||
|
||||
msg = MSG()
|
||||
logger.debug('Entering GetMessage() loop...')
|
||||
while GetMessage(ctypes.byref(msg), None, 0, 0) != 0:
|
||||
logger.debug('Got message')
|
||||
if msg.message == WM_HOTKEY:
|
||||
logger.debug('WM_HOTKEY')
|
||||
|
||||
if (
|
||||
config.get_int('hotkey_always')
|
||||
or window_title(GetForegroundWindow()).startswith('Elite - Dangerous')
|
||||
):
|
||||
if not config.shutting_down:
|
||||
logger.debug('Sending event <<Invoke>>')
|
||||
self.root.event_generate('<<Invoke>>', when="tail")
|
||||
|
||||
else:
|
||||
logger.debug('Passing key on')
|
||||
UnregisterHotKey(None, 1)
|
||||
SendInput(1, fake, ctypes.sizeof(INPUT))
|
||||
if not RegisterHotKey(None, 1, modifiers | MOD_NOREPEAT, keycode):
|
||||
logger.debug("We aren't registered for this ?")
|
||||
break
|
||||
|
||||
elif msg.message == WM_SND_GOOD:
|
||||
logger.debug('WM_SND_GOOD')
|
||||
winsound.PlaySound(self.snd_good, winsound.SND_MEMORY) # synchronous
|
||||
|
||||
elif msg.message == WM_SND_BAD:
|
||||
logger.debug('WM_SND_BAD')
|
||||
winsound.PlaySound(self.snd_bad, winsound.SND_MEMORY) # synchronous
|
||||
|
||||
else:
|
||||
logger.debug('Something else')
|
||||
TranslateMessage(ctypes.byref(msg))
|
||||
DispatchMessage(ctypes.byref(msg))
|
||||
|
||||
logger.debug('Exited GetMessage() loop.')
|
||||
UnregisterHotKey(None, 1)
|
||||
self.thread = None # type: ignore
|
||||
logger.debug('Done.')
|
||||
|
||||
def acquire_start(self) -> None:
|
||||
"""Start acquiring hotkey state via polling."""
|
||||
pass
|
||||
|
||||
def acquire_stop(self) -> None:
|
||||
"""Stop acquiring hotkey state."""
|
||||
pass
|
||||
|
||||
def fromevent(self, event) -> Optional[Union[bool, Tuple]]: # noqa: CCR001
|
||||
"""
|
||||
Return configuration (keycode, modifiers) or None=clear or False=retain previous.
|
||||
|
||||
event.state is a pain - it shows the state of the modifiers *before* a modifier key was pressed.
|
||||
event.state *does* differentiate between left and right Ctrl and Alt and between Return and Enter
|
||||
by putting KF_EXTENDED in bit 18, but RegisterHotKey doesn't differentiate.
|
||||
|
||||
:param event: tk event ?
|
||||
:return: False to retain previous, None to not use, else (keycode, modifiers)
|
||||
"""
|
||||
modifiers = ((GetKeyState(VK_MENU) & 0x8000) and MOD_ALT) \
|
||||
| ((GetKeyState(VK_CONTROL) & 0x8000) and MOD_CONTROL) \
|
||||
| ((GetKeyState(VK_SHIFT) & 0x8000) and MOD_SHIFT) \
|
||||
| ((GetKeyState(VK_LWIN) & 0x8000) and MOD_WIN) \
|
||||
| ((GetKeyState(VK_RWIN) & 0x8000) and MOD_WIN)
|
||||
keycode = event.keycode
|
||||
|
||||
if keycode in [VK_SHIFT, VK_CONTROL, VK_MENU, VK_LWIN, VK_RWIN]:
|
||||
return (0, modifiers)
|
||||
|
||||
if not modifiers:
|
||||
if keycode == VK_ESCAPE: # Esc = retain previous
|
||||
return False
|
||||
|
||||
elif keycode in [VK_BACK, VK_DELETE, VK_CLEAR, VK_OEM_CLEAR]: # BkSp, Del, Clear = clear hotkey
|
||||
return None
|
||||
|
||||
elif (
|
||||
keycode in [VK_RETURN, VK_SPACE, VK_OEM_MINUS] or ord('A') <= keycode <= ord('Z')
|
||||
): # don't allow keys needed for typing in System Map
|
||||
winsound.MessageBeep()
|
||||
return None
|
||||
|
||||
elif (keycode in [VK_NUMLOCK, VK_SCROLL, VK_PROCESSKEY]
|
||||
or VK_CAPITAL <= keycode <= VK_MODECHANGE): # ignore unmodified mode switch keys
|
||||
return (0, modifiers)
|
||||
|
||||
# See if the keycode is usable and available
|
||||
if RegisterHotKey(None, 2, modifiers | MOD_NOREPEAT, keycode):
|
||||
UnregisterHotKey(None, 2)
|
||||
return (keycode, modifiers)
|
||||
|
||||
else:
|
||||
winsound.MessageBeep()
|
||||
return None
|
||||
|
||||
def display(self, keycode, modifiers) -> str:
|
||||
"""
|
||||
Return displayable form of given hotkey + modifiers.
|
||||
|
||||
:param keycode:
|
||||
:param modifiers:
|
||||
:return: string form
|
||||
"""
|
||||
text = ''
|
||||
if modifiers & MOD_WIN:
|
||||
text += '❖+'
|
||||
|
||||
if modifiers & MOD_CONTROL:
|
||||
text += 'Ctrl+'
|
||||
|
||||
if modifiers & MOD_ALT:
|
||||
text += 'Alt+'
|
||||
|
||||
if modifiers & MOD_SHIFT:
|
||||
text += '⇧+'
|
||||
|
||||
if VK_NUMPAD0 <= keycode <= VK_DIVIDE:
|
||||
text += '№'
|
||||
|
||||
if not keycode:
|
||||
pass
|
||||
|
||||
elif VK_F1 <= keycode <= VK_F24:
|
||||
text += f'F{keycode + 1 - VK_F1}'
|
||||
|
||||
elif keycode in WindowsHotkeyMgr.DISPLAY: # specials
|
||||
text += WindowsHotkeyMgr.DISPLAY[keycode]
|
||||
|
||||
else:
|
||||
c = MapVirtualKey(keycode, 2) # printable ?
|
||||
if not c: # oops not printable
|
||||
text += '⁈'
|
||||
|
||||
elif c < 0x20: # control keys
|
||||
text += chr(c + 0x40)
|
||||
|
||||
else:
|
||||
text += chr(c).upper()
|
||||
|
||||
return text
|
||||
|
||||
def play_good(self) -> None:
|
||||
"""Play the 'good' sound."""
|
||||
if self.thread:
|
||||
PostThreadMessage(self.thread.ident, WM_SND_GOOD, 0, 0)
|
||||
|
||||
def play_bad(self) -> None:
|
||||
"""Play the 'bad' sound."""
|
||||
if self.thread:
|
||||
PostThreadMessage(self.thread.ident, WM_SND_BAD, 0, 0)
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
# Ref: <https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.5.html>
|
||||
Version=1.5
|
||||
Name=E:D Market Connector
|
||||
Comment=Utilise Elite Dangerous Journal and CAPI data
|
||||
Icon=io.edcd.EDMarketConnector
|
||||
Categories=Game;
|
||||
Keywords=Elite;Dangerous;EDDN;EDSM;EDDB;Inara;Spansh;
|
||||
Exec=edmarketconnector
|
||||
Terminal=false
|
||||
SingleMainWindow=true
|
||||
File renamed without changes.
+1
-1
@@ -33,7 +33,7 @@ class JournalLock:
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialise where the journal directory and lock file are."""
|
||||
self.journal_dir: str = config.get_str('journaldir') or config.default_journal_dir
|
||||
self.journal_dir: str | None = config.get_str('journaldir') or config.default_journal_dir
|
||||
self.journal_dir_path: Optional[pathlib.Path] = None
|
||||
self.set_path_from_journaldir()
|
||||
self.journal_dir_lockfile_name: Optional[pathlib.Path] = None
|
||||
|
||||
+16
-2
@@ -1,6 +1,7 @@
|
||||
"""Fetch kill switches from EDMC Repo."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import threading
|
||||
from copy import deepcopy
|
||||
from typing import (
|
||||
@@ -339,6 +340,16 @@ def fetch_kill_switches(target=DEFAULT_KILLSWITCH_URL) -> Optional[KillSwitchJSO
|
||||
:return: a list of dicts containing kill switch data, or None
|
||||
"""
|
||||
logger.info("Attempting to fetch kill switches")
|
||||
if target.startswith('file:'):
|
||||
target = target.replace('file:', '')
|
||||
try:
|
||||
with open(target, 'r') as t:
|
||||
return json.load(t)
|
||||
|
||||
except FileNotFoundError:
|
||||
logger.warning(f"No such file '{target}'")
|
||||
return None
|
||||
|
||||
try:
|
||||
data = requests.get(target, timeout=10).json()
|
||||
|
||||
@@ -458,13 +469,16 @@ def get_kill_switches_thread(
|
||||
active: KillSwitchSet = KillSwitchSet([])
|
||||
|
||||
|
||||
def setup_main_list():
|
||||
def setup_main_list(filename: Optional[str]):
|
||||
"""
|
||||
Set up the global set of kill switches for querying.
|
||||
|
||||
Plugins should NOT call this EVER.
|
||||
"""
|
||||
if (data := get_kill_switches(DEFAULT_KILLSWITCH_URL, OLD_KILLSWITCH_URL)) is None:
|
||||
if filename is None:
|
||||
filename = DEFAULT_KILLSWITCH_URL
|
||||
|
||||
if (data := get_kill_switches(filename, OLD_KILLSWITCH_URL)) is None:
|
||||
logger.warning("Unable to fetch kill switches. Setting global set to an empty set")
|
||||
return
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ class _Translations:
|
||||
self.translations = {None: {}}
|
||||
builtins.__dict__['_'] = lambda x: str(x).replace(r'\"', '"').replace('{CR}', '\n')
|
||||
|
||||
def install(self, lang: str = None) -> None: # noqa: CCR001
|
||||
def install(self, lang: str | None = None) -> None: # noqa: CCR001
|
||||
"""
|
||||
Install the translation function to the _ builtin.
|
||||
|
||||
@@ -250,7 +250,7 @@ class _Locale:
|
||||
self.float_formatter.setMinimumFractionDigits_(5)
|
||||
self.float_formatter.setMaximumFractionDigits_(5)
|
||||
|
||||
def stringFromNumber(self, number: Union[float, int], decimals: int = None) -> str: # noqa: N802
|
||||
def stringFromNumber(self, number: Union[float, int], decimals: int | None = None) -> str: # noqa: N802
|
||||
warnings.warn(DeprecationWarning('use _Locale.string_from_number instead.'))
|
||||
return self.string_from_number(number, decimals) # type: ignore
|
||||
|
||||
|
||||
+307
-187
@@ -14,9 +14,7 @@ from collections import OrderedDict, defaultdict
|
||||
from os import SEEK_END, SEEK_SET, listdir
|
||||
from os.path import basename, expanduser, getctime, isdir, join
|
||||
from time import gmtime, localtime, mktime, sleep, strftime, strptime, time
|
||||
from typing import TYPE_CHECKING, Any, BinaryIO, Dict, List, MutableMapping, Optional
|
||||
from typing import OrderedDict as OrderedDictT
|
||||
from typing import Tuple
|
||||
from typing import TYPE_CHECKING, Any, BinaryIO, MutableMapping, Tuple
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import tkinter
|
||||
@@ -91,11 +89,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
# TODO(A_D): A bunch of these should be switched to default values (eg '' for strings) and no longer be Optional
|
||||
FileSystemEventHandler.__init__(self) # futureproofing - not need for current version of watchdog
|
||||
self.root: 'tkinter.Tk' = None # type: ignore # Don't use Optional[] - mypy thinks no methods
|
||||
self.currentdir: Optional[str] = None # The actual logdir that we're monitoring
|
||||
self.logfile: Optional[str] = None
|
||||
self.observer: Optional['Observer'] = None
|
||||
self.currentdir: str | None = None # The actual logdir that we're monitoring
|
||||
self.logfile: str | None = None
|
||||
self.observer: 'Observer' | None = None
|
||||
self.observed = None # a watchdog ObservedWatch, or None if polling
|
||||
self.thread: Optional[threading.Thread] = None
|
||||
self.thread: threading.Thread | None = None
|
||||
# For communicating journal entries back to main thread
|
||||
self.event_queue: queue.Queue = queue.Queue(maxsize=0)
|
||||
|
||||
@@ -112,27 +110,19 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
self.game_was_running = False # For generation of the "ShutDown" event
|
||||
|
||||
# Context for journal handling
|
||||
self.version: Optional[str] = None
|
||||
self.version_semantic: Optional[semantic_version.Version] = None
|
||||
self.version: str | None = None
|
||||
self.version_semantic: semantic_version.Version | None = None
|
||||
self.is_beta = False
|
||||
self.mode: Optional[str] = None
|
||||
self.group: Optional[str] = None
|
||||
self.cmdr: Optional[str] = None
|
||||
self.planet: Optional[str] = None
|
||||
self.system: Optional[str] = None
|
||||
self.station: Optional[str] = None
|
||||
self.station_marketid: Optional[int] = None
|
||||
self.stationtype: Optional[str] = None
|
||||
self.coordinates: Optional[Tuple[float, float, float]] = None
|
||||
self.systemaddress: Optional[int] = None
|
||||
self.systempopulation: Optional[int] = None
|
||||
self.started: Optional[int] = None # Timestamp of the LoadGame event
|
||||
self.mode: str | None = None
|
||||
self.group: str | None = None
|
||||
self.cmdr: str | None = None
|
||||
self.started: int | None = None # Timestamp of the LoadGame event
|
||||
|
||||
self._navroute_retries_remaining = 0
|
||||
self._last_navroute_journal_timestamp: Optional[float] = None
|
||||
self._last_navroute_journal_timestamp: float | None = None
|
||||
|
||||
self._fcmaterials_retries_remaining = 0
|
||||
self._last_fcmaterials_journal_timestamp: Optional[float] = None
|
||||
self._last_fcmaterials_journal_timestamp: float | None = None
|
||||
|
||||
# For determining Live versus Legacy galaxy.
|
||||
# The assumption is gameversion will parse via `coerce()` and always
|
||||
@@ -144,7 +134,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
def __init_state(self) -> None:
|
||||
# Cmdr state shared with EDSM and plugins
|
||||
# If you change anything here update PLUGINS.md documentation!
|
||||
self.state: Dict = {
|
||||
self.state: dict = {
|
||||
'GameLanguage': None, # From `Fileheader
|
||||
'GameVersion': None, # From `Fileheader
|
||||
'GameBuild': None, # From `Fileheader
|
||||
@@ -195,8 +185,13 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
'Taxi': None, # True whenever we are _in_ a taxi. ie, this is reset on Disembark etc.
|
||||
'Dropship': None, # Best effort as to whether or not the above taxi is a dropship.
|
||||
'StarPos': None, # Best effort current system's galaxy position.
|
||||
'SystemAddress': None,
|
||||
'SystemName': None,
|
||||
'SystemPopulation': None,
|
||||
'Body': None,
|
||||
'BodyID': None,
|
||||
'BodyType': None,
|
||||
'StationName': None,
|
||||
|
||||
'NavRoute': None,
|
||||
}
|
||||
@@ -274,7 +269,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
logger.debug('Done.')
|
||||
return True
|
||||
|
||||
def journal_newest_filename(self, journals_dir) -> Optional[str]:
|
||||
def journal_newest_filename(self, journals_dir) -> str | None:
|
||||
"""
|
||||
Determine the newest Journal file name.
|
||||
|
||||
@@ -306,19 +301,20 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
self.mode = None
|
||||
self.group = None
|
||||
self.cmdr = None
|
||||
self.planet = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.station_marketid = None
|
||||
self.stationtype = None
|
||||
self.state['SystemAddress'] = None
|
||||
self.state['SystemName'] = None
|
||||
self.state['SystemPopulation'] = None
|
||||
self.state['StarPos'] = None
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
self.state['BodyType'] = None
|
||||
self.state['StationName'] = None
|
||||
self.state['MarketID'] = None
|
||||
self.state['StationType'] = None
|
||||
self.stationservices = None
|
||||
self.coordinates = None
|
||||
self.systemaddress = None
|
||||
self.is_beta = False
|
||||
self.state['OnFoot'] = False
|
||||
self.state['IsDocked'] = False
|
||||
self.state['Body'] = None
|
||||
self.state['BodyType'] = None
|
||||
|
||||
if self.observed:
|
||||
logger.debug('self.observed: Calling unschedule_all()')
|
||||
@@ -415,25 +411,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
|
||||
if self.live:
|
||||
if self.game_was_running:
|
||||
logger.info("Game is/was running, so synthesizing StartUp event for plugins")
|
||||
# Game is running locally
|
||||
entry: OrderedDictT[str, Any] = OrderedDict([
|
||||
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())),
|
||||
('event', 'StartUp'),
|
||||
('StarSystem', self.system),
|
||||
('StarPos', self.coordinates),
|
||||
('SystemAddress', self.systemaddress),
|
||||
('Population', self.systempopulation),
|
||||
])
|
||||
|
||||
if self.planet:
|
||||
entry['Body'] = self.planet
|
||||
|
||||
entry['Docked'] = bool(self.station)
|
||||
|
||||
if self.station:
|
||||
entry['StationName'] = self.station
|
||||
entry['StationType'] = self.stationtype
|
||||
entry['MarketID'] = self.station_marketid
|
||||
entry = self.synthesize_startup_event()
|
||||
|
||||
self.event_queue.put(json.dumps(entry, separators=(', ', ':')))
|
||||
|
||||
@@ -455,7 +435,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
|
||||
# Check whether new log file started, e.g. client (re)started.
|
||||
if emitter and emitter.is_alive():
|
||||
new_journal_file: Optional[str] = self.logfile # updated by on_created watchdog callback
|
||||
new_journal_file: str | None = self.logfile # updated by on_created watchdog callback
|
||||
|
||||
else:
|
||||
# Poll
|
||||
@@ -534,6 +514,41 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
|
||||
logger.debug('Done.')
|
||||
|
||||
def synthesize_startup_event(self) -> dict[str, Any]:
|
||||
"""
|
||||
Synthesize a 'StartUp' event to notify plugins of initial state.
|
||||
|
||||
May be called, e.g. after 'catch up' loading of current latest
|
||||
journal file on startup, or when a new journal file is detected without
|
||||
the game running locally.
|
||||
|
||||
:return: Synthesized event as a dict
|
||||
"""
|
||||
entry: dict[str, Any] = {
|
||||
'timestamp': strftime('%Y-%m-%dT%H:%M:%SZ', gmtime()),
|
||||
'event': 'StartUp',
|
||||
'StarSystem': self.state['SystemName'],
|
||||
'StarPos': self.state['StarPos'],
|
||||
'SystemAddress': self.state['SystemAddress'],
|
||||
'Population': self.state['SystemPopulation'],
|
||||
}
|
||||
|
||||
if self.state['Body']:
|
||||
entry['Body'] = self.state['Body']
|
||||
entry['BodyID'] = self.state['BodyID']
|
||||
entry['BodyType'] = self.state['BodyType']
|
||||
|
||||
if self.state['StationName']:
|
||||
entry['Docked'] = True
|
||||
entry['MarketID'] = self.state['MarketID']
|
||||
entry['StationName'] = self.state['StationName']
|
||||
entry['StationType'] = self.state['StationType']
|
||||
|
||||
else:
|
||||
entry['Docked'] = False
|
||||
|
||||
return entry
|
||||
|
||||
def parse_entry(self, line: bytes) -> MutableMapping[str, Any]: # noqa: C901, CCR001
|
||||
"""
|
||||
Parse a Journal JSON line.
|
||||
@@ -563,14 +578,16 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
self.cmdr = None
|
||||
self.mode = None
|
||||
self.group = None
|
||||
self.planet = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.station_marketid = None
|
||||
self.stationtype = None
|
||||
self.state['SystemAddress'] = None
|
||||
self.state['SystemName'] = None
|
||||
self.state['SystemPopulation'] = None
|
||||
self.state['StarPos'] = None
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
self.state['StationName'] = None
|
||||
self.state['MarketID'] = None
|
||||
self.state['StationType'] = None
|
||||
self.stationservices = None
|
||||
self.coordinates = None
|
||||
self.systemaddress = None
|
||||
self.started = None
|
||||
self.__init_state()
|
||||
|
||||
@@ -599,34 +616,35 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
self.mode = entry.get('GameMode')
|
||||
|
||||
self.group = entry.get('Group')
|
||||
self.planet = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.station_marketid = None
|
||||
self.stationtype = None
|
||||
self.state['SystemAddress'] = None
|
||||
self.state['SystemName'] = None
|
||||
self.state['SystemPopulation'] = None
|
||||
self.state['StarPos'] = None
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
self.state['BodyType'] = None
|
||||
self.state['StationName'] = None
|
||||
self.state['MarketID'] = None
|
||||
self.state['StationType'] = None
|
||||
self.stationservices = None
|
||||
self.coordinates = None
|
||||
self.systemaddress = None
|
||||
self.started = timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ'))
|
||||
# Don't set Ship, ShipID etc since this will reflect Fighter or SRV if starting in those
|
||||
self.state.update({
|
||||
'Captain': None,
|
||||
'Credits': entry['Credits'],
|
||||
'FID': entry.get('FID'), # From 3.3
|
||||
'Horizons': entry['Horizons'], # From 3.0
|
||||
'Odyssey': entry.get('Odyssey', False), # From 4.0 Odyssey
|
||||
'Loan': entry['Loan'],
|
||||
'Captain': None,
|
||||
'Credits': entry['Credits'],
|
||||
'FID': entry.get('FID'), # From 3.3
|
||||
'Horizons': entry['Horizons'], # From 3.0
|
||||
'Odyssey': entry.get('Odyssey', False), # From 4.0 Odyssey
|
||||
'Loan': entry['Loan'],
|
||||
# For Odyssey, by 4.0.0.100, and at least from Horizons 3.8.0.201 the order of events changed
|
||||
# to LoadGame being after some 'status' events.
|
||||
# 'Engineers': {}, # 'EngineerProgress' event now before 'LoadGame'
|
||||
# 'Rank': {}, # 'Rank'/'Progress' events now before 'LoadGame'
|
||||
# 'Reputation': {}, # 'Reputation' event now before 'LoadGame'
|
||||
'Statistics': {}, # Still after 'LoadGame' in 4.0.0.903
|
||||
'Role': None,
|
||||
'Taxi': None,
|
||||
'Dropship': None,
|
||||
'Body': None,
|
||||
'BodyType': None,
|
||||
# 'Engineers': {}, # 'EngineerProgress' event now before 'LoadGame'
|
||||
# 'Rank': {}, # 'Rank'/'Progress' events now before 'LoadGame'
|
||||
# 'Reputation': {}, # 'Reputation' event now before 'LoadGame'
|
||||
'Statistics': {}, # Still after 'LoadGame' in 4.0.0.903
|
||||
'Role': None,
|
||||
'Taxi': None,
|
||||
'Dropship': None,
|
||||
})
|
||||
if entry.get('Ship') is not None and self._RE_SHIP_ONFOOT.search(entry['Ship']):
|
||||
self.state['OnFoot'] = True
|
||||
@@ -738,9 +756,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
modules.pop(from_slot, None)
|
||||
|
||||
elif event_type == 'undocked':
|
||||
self.station = None
|
||||
self.station_marketid = None
|
||||
self.stationtype = None
|
||||
self.state['StationName'] = None
|
||||
self.state['MarketID'] = None
|
||||
self.state['StationType'] = None
|
||||
self.stationservices = None
|
||||
self.state['IsDocked'] = False
|
||||
|
||||
@@ -760,9 +778,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
# • StationName (if at a station)
|
||||
# • StationType
|
||||
# • MarketID
|
||||
self.station = None
|
||||
self.state['StationName'] = None
|
||||
self.state['MarketID'] = None
|
||||
if entry.get('OnStation'):
|
||||
self.station = entry.get('StationName', '')
|
||||
self.state['StationName'] = entry.get('StationName', '')
|
||||
self.state['MarketID'] = entry.get('MarketID', '')
|
||||
|
||||
self.state['OnFoot'] = False
|
||||
self.state['Taxi'] = entry['Taxi']
|
||||
@@ -790,10 +810,10 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
# • MarketID
|
||||
|
||||
if entry.get('OnStation', False):
|
||||
self.station = entry.get('StationName', '')
|
||||
self.state['StationName'] = entry.get('StationName', '')
|
||||
|
||||
else:
|
||||
self.station = None
|
||||
self.state['StationName'] = None
|
||||
|
||||
self.state['OnFoot'] = True
|
||||
if self.state['Taxi'] is not None and self.state['Taxi'] != entry.get('Taxi', False):
|
||||
@@ -808,77 +828,204 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
self.state['Taxi'] = False
|
||||
self.state['Dropship'] = False
|
||||
|
||||
elif event_type == 'supercruiseexit':
|
||||
# For any orbital station we have no way of determining the body
|
||||
# it orbits:
|
||||
#
|
||||
# In-ship Status.json doesn't specify this.
|
||||
# On-foot Status.json lists the station itself as Body.
|
||||
# Location for stations (on-foot or in-ship) has station as Body.
|
||||
# SupercruiseExit (own ship or taxi) lists the station as the Body.
|
||||
if entry['BodyType'] == 'Station':
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
|
||||
elif event_type == 'docked':
|
||||
###############################################################
|
||||
# Track: Station
|
||||
###############################################################
|
||||
self.state['IsDocked'] = True
|
||||
self.station = entry.get('StationName') # May be None
|
||||
self.station_marketid = entry.get('MarketID') # May be None
|
||||
self.stationtype = entry.get('StationType') # May be None
|
||||
self.state['StationName'] = entry.get('StationName') # It may be None
|
||||
self.state['MarketID'] = entry.get('MarketID') # It may be None
|
||||
self.state['StationType'] = entry.get('StationType') # It may be None
|
||||
self.stationservices = entry.get('StationServices') # None under E:D < 2.4
|
||||
|
||||
# No need to set self.state['Taxi'] or Dropship here, if its those, the next event is a Disembark anyway
|
||||
# No need to set self.state['Taxi'] or Dropship here, if it's
|
||||
# those, the next event is a Disembark anyway
|
||||
###############################################################
|
||||
|
||||
elif event_type in ('location', 'fsdjump', 'carrierjump'):
|
||||
# alpha4 - any changes ?
|
||||
# Location:
|
||||
# New in Odyssey:
|
||||
# • Taxi: bool
|
||||
# • Multicrew: bool
|
||||
# • InSRV: bool
|
||||
# • OnFoot: bool
|
||||
"""
|
||||
Notes on tracking of a player's location.
|
||||
|
||||
Body
|
||||
---
|
||||
There are some caveats about tracking Body name, ID and type,
|
||||
mostly due to close-orbiting binary planets/moons.
|
||||
|
||||
Presence on or near a Body is indicated in several scenarios:
|
||||
|
||||
1. When the player logs in.
|
||||
2. When the player's location changes due to being docked
|
||||
on a Fleet Carrier when it jumps.
|
||||
3. When the player flies within Orbital Cruise range of a
|
||||
Body.
|
||||
|
||||
For the first case this will always be a 'Location' event.
|
||||
If landed on a Body, or docked at a surface port then this
|
||||
will be indicated. However, if docked at an orbital station
|
||||
the 'Body' is the name of that station, with 'BodyType' having
|
||||
'Station' as its value.
|
||||
|
||||
In the second case although it *should* be a 'CarrierJump'
|
||||
event, for a while now it's actually been a 'Location' event.
|
||||
This should follow the same rules as being docked at an
|
||||
orbital station.
|
||||
|
||||
For the last case there are some caveats to do with close
|
||||
orbiting binary bodies:
|
||||
|
||||
1. 'ApproachBody' indicates presence near the Body in question.
|
||||
2. 'LeaveBody' indicates the player is no longer considered
|
||||
to be near the Body. This is specifically when no longer
|
||||
in Orbital Cruise around the Body such that the HUD for that
|
||||
has been switched out for the normal SuperCruise one.
|
||||
3. 'SupercruiseExit' does not indicate any change of presence
|
||||
near a Body.
|
||||
4. 'SupercruiseEntry' *also* **DOES NOT** indicate that the
|
||||
player is no longer near the Body. They can easily utilise
|
||||
Orbital Cruise to rapidly travel around the Body and then
|
||||
land on it again **without a fresh 'ApproachBody'** event.
|
||||
|
||||
The only way to check for this is to utilise the Body (name)
|
||||
present in `Status.json` data, as this *will* correctly
|
||||
reflect the second Body.
|
||||
"""
|
||||
###############################################################
|
||||
# Track: Body
|
||||
###############################################################
|
||||
if event_type in ('location', 'carrierjump'):
|
||||
self.planet = entry.get('Body') if entry.get('BodyType') == 'Planet' else None
|
||||
# We're not guaranteeing this is a planet, rather than a
|
||||
# station.
|
||||
self.state['Body'] = entry.get('Body')
|
||||
self.state['BodyID'] = entry.get('BodyID')
|
||||
self.state['BodyType'] = entry.get('BodyType')
|
||||
|
||||
if event_type == 'location':
|
||||
logger.trace_if('journal.locations', '"Location" event')
|
||||
if entry.get('Docked'):
|
||||
self.state['IsDocked'] = True
|
||||
|
||||
elif event_type == 'fsdjump':
|
||||
self.planet = None
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
self.state['BodyType'] = None
|
||||
###############################################################
|
||||
|
||||
###############################################################
|
||||
# Track: IsDocked
|
||||
###############################################################
|
||||
if event_type == 'location':
|
||||
logger.trace_if('journal.locations', '"Location" event')
|
||||
self.state['IsDocked'] = entry.get('Docked', False)
|
||||
###############################################################
|
||||
|
||||
###############################################################
|
||||
# Track: Current System
|
||||
###############################################################
|
||||
if 'StarPos' in entry:
|
||||
# Plugins need this as well, so copy in state
|
||||
self.state['StarPos'] = self.coordinates = tuple(entry['StarPos']) # type: ignore
|
||||
|
||||
self.systemaddress = entry.get('SystemAddress')
|
||||
|
||||
self.systempopulation = entry.get('Population')
|
||||
|
||||
if entry['StarSystem'] == 'ProvingGround':
|
||||
self.system = 'CQC'
|
||||
self.state['StarPos'] = tuple(entry['StarPos']) # type: ignore
|
||||
|
||||
else:
|
||||
self.system = entry['StarSystem']
|
||||
logger.warning(f"'{event_type}' event without 'StarPos' !!!:\n{entry}\n")
|
||||
|
||||
self.station = entry.get('StationName') # May be None
|
||||
# If on foot in-station 'Docked' is false, but we have a
|
||||
# 'BodyType' of 'Station', and the 'Body' is the station name
|
||||
# NB: No MarketID
|
||||
if entry.get('BodyType') and entry['BodyType'] == 'Station':
|
||||
self.station = entry.get('Body')
|
||||
if 'SystemAddress' not in entry:
|
||||
logger.warning(f"{event_type} event without SystemAddress !!!:\n{entry}\n")
|
||||
|
||||
self.station_marketid = entry.get('MarketID') # May be None
|
||||
self.stationtype = entry.get('StationType') # May be None
|
||||
self.stationservices = entry.get('StationServices') # None in Odyssey for on-foot 'Location'
|
||||
# But we'll still *use* the value, because if a 'location' event doesn't
|
||||
# have this we've still moved and now don't know where and MUST NOT
|
||||
# continue to use any old value.
|
||||
# Yes, explicitly state `None` here, so it's crystal clear.
|
||||
self.state['SystemAddress'] = entry.get('SystemAddress', None)
|
||||
|
||||
self.state['SystemPopulation'] = entry.get('Population')
|
||||
|
||||
if entry['StarSystem'] == 'ProvingGround':
|
||||
self.state['SystemName'] = 'CQC'
|
||||
|
||||
else:
|
||||
self.state['SystemName'] = entry['StarSystem']
|
||||
###############################################################
|
||||
|
||||
###############################################################
|
||||
# Track: Current station, if applicable
|
||||
###############################################################
|
||||
if event_type == 'fsdjump':
|
||||
self.state['StationName'] = None
|
||||
self.state['MarketID'] = None
|
||||
self.state['StationType'] = None
|
||||
self.stationservices = None
|
||||
|
||||
else:
|
||||
self.state['StationName'] = entry.get('StationName') # It may be None
|
||||
# If on foot in-station 'Docked' is false, but we have a
|
||||
# 'BodyType' of 'Station', and the 'Body' is the station name
|
||||
# NB: No MarketID
|
||||
if entry.get('BodyType') and entry['BodyType'] == 'Station':
|
||||
self.state['StationName'] = entry.get('Body')
|
||||
|
||||
self.state['MarketID'] = entry.get('MarketID') # May be None
|
||||
self.state['StationType'] = entry.get('StationType') # May be None
|
||||
self.stationservices = entry.get('StationServices') # None in Odyssey for on-foot 'Location'
|
||||
###############################################################
|
||||
|
||||
###############################################################
|
||||
# Track: Whether in a Taxi/Dropship
|
||||
###############################################################
|
||||
self.state['Taxi'] = entry.get('Taxi', None)
|
||||
if not self.state['Taxi']:
|
||||
self.state['Dropship'] = None
|
||||
###############################################################
|
||||
|
||||
elif event_type == 'approachbody':
|
||||
self.planet = entry['Body']
|
||||
self.state['Body'] = entry['Body']
|
||||
self.state['BodyType'] = 'Planet' # Best guess. Journal says always planet.
|
||||
self.state['BodyID'] = entry.get('BodyID')
|
||||
# This isn't in the event, but Journal doc for ApproachBody says:
|
||||
# when in Supercruise, and distance from planet drops to within the 'Orbital Cruise' zone
|
||||
# Used in plugins/eddn.py for setting entry Body/BodyType
|
||||
# on 'docked' events when Planetary.
|
||||
self.state['BodyType'] = 'Planet'
|
||||
|
||||
elif event_type in ('leavebody', 'supercruiseentry'):
|
||||
self.planet = None
|
||||
elif event_type == 'leavebody':
|
||||
# Triggered when ship goes above Orbital Cruise altitude, such
|
||||
# that a new 'ApproachBody' would get triggered if the ship
|
||||
# went back down.
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
self.state['BodyType'] = None
|
||||
|
||||
elif event_type == 'supercruiseentry':
|
||||
# We only clear Body state if the Type is Station. This is
|
||||
# because we won't get a fresh ApproachBody if we don't leave
|
||||
# Orbital Cruise but land again.
|
||||
if self.state['BodyType'] == 'Station':
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
self.state['BodyType'] = None
|
||||
|
||||
###############################################################
|
||||
# Track: Current station, if applicable
|
||||
###############################################################
|
||||
self.state['StationName'] = None
|
||||
self.state['MarketID'] = None
|
||||
self.state['StationType'] = None
|
||||
self.stationservices = None
|
||||
###############################################################
|
||||
|
||||
elif event_type == 'music':
|
||||
if entry['MusicTrack'] == 'MainMenu':
|
||||
# We'll get new Body state when the player logs back into
|
||||
# the game.
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
self.state['BodyType'] = None
|
||||
|
||||
elif event_type in ('rank', 'promotion'):
|
||||
payload = dict(entry)
|
||||
payload.pop('event')
|
||||
@@ -1562,18 +1709,19 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
elif event_type == 'joinacrew':
|
||||
self.state['Captain'] = entry['Captain']
|
||||
self.state['Role'] = 'Idle'
|
||||
self.planet = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.station_marketid = None
|
||||
self.stationtype = None
|
||||
self.stationservices = None
|
||||
self.coordinates = None
|
||||
self.systemaddress = None
|
||||
self.state['OnFoot'] = False
|
||||
|
||||
self.state['StarPos'] = None
|
||||
self.state['SystemName'] = None
|
||||
self.state['SystemAddress'] = None
|
||||
self.state['SystemPopulation'] = None
|
||||
self.state['StarPos'] = None
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
self.state['BodyType'] = None
|
||||
self.state['StationName'] = None
|
||||
self.state['MarketID'] = None
|
||||
self.state['StationType'] = None
|
||||
self.stationservices = None
|
||||
self.state['OnFoot'] = False
|
||||
|
||||
elif event_type == 'changecrewrole':
|
||||
self.state['Role'] = entry['Role']
|
||||
@@ -1581,17 +1729,18 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
elif event_type == 'quitacrew':
|
||||
self.state['Captain'] = None
|
||||
self.state['Role'] = None
|
||||
self.planet = None
|
||||
self.system = None
|
||||
self.station = None
|
||||
self.station_marketid = None
|
||||
self.stationtype = None
|
||||
self.stationservices = None
|
||||
self.coordinates = None
|
||||
self.systemaddress = None
|
||||
|
||||
self.state['SystemName'] = None
|
||||
self.state['SystemAddress'] = None
|
||||
self.state['SystemPopulation'] = None
|
||||
self.state['StarPos'] = None
|
||||
self.state['Body'] = None
|
||||
self.state['BodyID'] = None
|
||||
self.state['BodyType'] = None
|
||||
self.state['StationName'] = None
|
||||
self.state['MarketID'] = None
|
||||
self.state['StationType'] = None
|
||||
self.stationservices = None
|
||||
|
||||
# TODO: on_foot: Will we get an event after this to know ?
|
||||
|
||||
elif event_type == 'friends':
|
||||
@@ -1676,11 +1825,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
# There should be a `Backpack` event as you 'come to' in the
|
||||
# new location, so no need to zero out BackPack here.
|
||||
|
||||
# HACK (not game related / 2021-06-2): self.planet is moved into a more general self.state['Body'].
|
||||
# This exists to help plugins doing what they SHOULDN'T BE cope. It will be removed at some point.
|
||||
if self.state['Body'] is None or self.state['BodyType'] == 'Planet':
|
||||
self.planet = self.state['Body']
|
||||
|
||||
return entry
|
||||
|
||||
except Exception as ex:
|
||||
@@ -1918,7 +2062,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
slotid = journal_loadoutid - 4293000000
|
||||
return slotid
|
||||
|
||||
def canonicalise(self, item: Optional[str]) -> str:
|
||||
def canonicalise(self, item: str | None) -> str:
|
||||
"""
|
||||
Produce canonical name for a ship module.
|
||||
|
||||
@@ -1955,7 +2099,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
|
||||
return item.capitalize()
|
||||
|
||||
def get_entry(self) -> Optional[MutableMapping[str, Any]]:
|
||||
def get_entry(self) -> MutableMapping[str, Any] | None:
|
||||
"""
|
||||
Pull the next Journal event from the event_queue.
|
||||
|
||||
@@ -1976,34 +2120,10 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
if entry['event'] == 'Location':
|
||||
logger.trace_if('journal.locations', '"Location" event')
|
||||
|
||||
if not self.live and entry['event'] not in (None, 'Fileheader'):
|
||||
if not self.live and entry['event'] not in (None, 'Fileheader', 'ShutDown'):
|
||||
# Game not running locally, but Journal has been updated
|
||||
self.live = True
|
||||
if self.station:
|
||||
entry = OrderedDict([
|
||||
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())),
|
||||
('event', 'StartUp'),
|
||||
('Docked', True),
|
||||
('MarketID', self.station_marketid),
|
||||
('StationName', self.station),
|
||||
('StationType', self.stationtype),
|
||||
('StarSystem', self.system),
|
||||
('StarPos', self.coordinates),
|
||||
('SystemAddress', self.systemaddress),
|
||||
])
|
||||
|
||||
else:
|
||||
entry = OrderedDict([
|
||||
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())),
|
||||
('event', 'StartUp'),
|
||||
('Docked', False),
|
||||
('StarSystem', self.system),
|
||||
('StarPos', self.coordinates),
|
||||
('SystemAddress', self.systemaddress),
|
||||
])
|
||||
|
||||
if entry['event'] == 'Location':
|
||||
logger.trace_if('journal.locations', 'Appending "Location" event to event_queue')
|
||||
entry = self.synthesize_startup_event()
|
||||
|
||||
self.event_queue.put(json.dumps(entry, separators=(', ', ':')))
|
||||
|
||||
@@ -2051,7 +2171,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
|
||||
return False
|
||||
|
||||
def ship(self, timestamped=True) -> Optional[MutableMapping[str, Any]]:
|
||||
def ship(self, timestamped=True) -> MutableMapping[str, Any] | None:
|
||||
"""
|
||||
Produce a subset of data for the current ship.
|
||||
|
||||
@@ -2188,7 +2308,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
except OSError:
|
||||
logger.exception("OSError writing ship loadout to new filename with utf-8 encoding, aborting.")
|
||||
|
||||
def coalesce_cargo(self, raw_cargo: List[MutableMapping[str, Any]]) -> List[MutableMapping[str, Any]]:
|
||||
def coalesce_cargo(self, raw_cargo: list[MutableMapping[str, Any]]) -> list[MutableMapping[str, Any]]:
|
||||
"""
|
||||
Coalesce multiple entries of the same cargo into one.
|
||||
|
||||
@@ -2209,7 +2329,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
:return: Coalesced data
|
||||
"""
|
||||
# self.state['Cargo'].update({self.canonicalise(x['Name']): x['Count'] for x in entry['Inventory']})
|
||||
out: List[MutableMapping[str, Any]] = []
|
||||
out: list[MutableMapping[str, Any]] = []
|
||||
for inventory_item in raw_cargo:
|
||||
if not any(self.canonicalise(x['Name']) == self.canonicalise(inventory_item['Name']) for x in out):
|
||||
out.append(dict(inventory_item))
|
||||
@@ -2250,7 +2370,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
|
||||
return slots
|
||||
|
||||
def _parse_navroute_file(self) -> Optional[dict[str, Any]]:
|
||||
def _parse_navroute_file(self) -> dict[str, Any] | None:
|
||||
"""Read and parse NavRoute.json."""
|
||||
if self.currentdir is None:
|
||||
raise ValueError('currentdir unset')
|
||||
@@ -2276,7 +2396,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
|
||||
return data
|
||||
|
||||
def _parse_fcmaterials_file(self) -> Optional[dict[str, Any]]:
|
||||
def _parse_fcmaterials_file(self) -> dict[str, Any] | None:
|
||||
"""Read and parse FCMaterials.json."""
|
||||
if self.currentdir is None:
|
||||
raise ValueError('currentdir unset')
|
||||
@@ -2348,7 +2468,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
|
||||
self._last_navroute_journal_timestamp = None
|
||||
return True
|
||||
|
||||
def __fcmaterials_retry(self) -> Optional[Dict[str, Any]]:
|
||||
def __fcmaterials_retry(self) -> dict[str, Any] | None:
|
||||
"""Retry reading FCMaterials files."""
|
||||
if self._fcmaterials_retries_remaining == 0:
|
||||
return None
|
||||
|
||||
+3
-2
@@ -58,7 +58,7 @@ class Notebook(ttk.Notebook):
|
||||
class Frame(sys.platform == 'darwin' and tk.Frame or ttk.Frame): # type: ignore
|
||||
"""Custom t(t)k.Frame class to fix some display issues."""
|
||||
|
||||
def __init__(self, master: Optional[ttk.Frame] = None, **kw):
|
||||
def __init__(self, master: ttk.Notebook | None = None, **kw):
|
||||
if sys.platform == 'darwin':
|
||||
kw['background'] = kw.pop('background', PAGEBG)
|
||||
tk.Frame.__init__(self, master, **kw)
|
||||
@@ -76,7 +76,8 @@ class Label(tk.Label):
|
||||
"""Custom tk.Label class to fix some display issues."""
|
||||
|
||||
def __init__(self, master: Optional[ttk.Frame] = None, **kw):
|
||||
if sys.platform in ['darwin', 'win32']:
|
||||
# This format chosen over `sys.platform in (...)` as mypy and friends dont understand that
|
||||
if sys.platform == 'darwin' or sys.platform == 'win32':
|
||||
kw['foreground'] = kw.pop('foreground', PAGEFG)
|
||||
kw['background'] = kw.pop('background', PAGEBG)
|
||||
else:
|
||||
|
||||
+2
-2
@@ -93,13 +93,13 @@ def lookup(module, ship_map, entitled=False) -> Optional[dict]: # noqa: C901, C
|
||||
# Countermeasures - e.g. Hpt_PlasmaPointDefence_Turret_Tiny
|
||||
elif name[0] == 'hpt' and name[1] in countermeasure_map:
|
||||
new['category'] = 'utility'
|
||||
new['name'], new['rating'] = countermeasure_map[len(name) > 4 and (name[1], name[4]) or name[1]]
|
||||
new['name'], new['rating'] = countermeasure_map[name[1]]
|
||||
new['class'] = weaponclass_map[name[-1]]
|
||||
|
||||
# Utility - e.g. Hpt_CargoScanner_Size0_Class1
|
||||
elif name[0] == 'hpt' and name[1] in utility_map:
|
||||
new['category'] = 'utility'
|
||||
new['name'] = utility_map[len(name) > 4 and (name[1], name[4]) or name[1]]
|
||||
new['name'] = utility_map[name[1]]
|
||||
if not name[2].startswith('size') or not name[3].startswith('class'):
|
||||
raise AssertionError(f'{module["id"]}: Unknown class/rating "{name[2]}/{name[3]}"')
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ import os
|
||||
import sys
|
||||
import tkinter as tk
|
||||
from builtins import object, str
|
||||
from typing import Any, Callable, List, Mapping, MutableMapping, Optional, Tuple
|
||||
from tkinter import ttk
|
||||
from typing import Any, Callable, List, Mapping, MutableMapping, Optional
|
||||
|
||||
import companion
|
||||
import myNotebook as nb # noqa: N813
|
||||
@@ -26,7 +27,7 @@ class LastError:
|
||||
"""Holds the last plugin error."""
|
||||
|
||||
msg: Optional[str]
|
||||
root: tk.Frame
|
||||
root: tk.Tk
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.msg = None
|
||||
@@ -118,7 +119,7 @@ class Plugin(object):
|
||||
|
||||
return None
|
||||
|
||||
def get_prefs(self, parent: tk.Frame, cmdr: str, is_beta: bool) -> Optional[tk.Frame]:
|
||||
def get_prefs(self, parent: ttk.Notebook, cmdr: str | None, is_beta: bool) -> Optional[tk.Frame]:
|
||||
"""
|
||||
If the plugin provides a prefs frame, create and return it.
|
||||
|
||||
@@ -140,7 +141,7 @@ class Plugin(object):
|
||||
return None
|
||||
|
||||
|
||||
def load_plugins(master: tk.Frame) -> None: # noqa: CCR001
|
||||
def load_plugins(master: tk.Tk) -> None: # noqa: CCR001
|
||||
"""Find and load all plugins."""
|
||||
last_error.root = master
|
||||
|
||||
@@ -159,7 +160,10 @@ def load_plugins(master: tk.Frame) -> None: # noqa: CCR001
|
||||
sys.path.append(config.plugin_dir)
|
||||
|
||||
found = []
|
||||
# Load any plugins that are also packages first
|
||||
# Load any plugins that are also packages first, but note it's *still*
|
||||
# 100% relying on there being a `load.py`, as only that will be loaded.
|
||||
# The intent here is to e.g. have EDMC-Overlay load before any plugins
|
||||
# that depend on it.
|
||||
for name in sorted(
|
||||
os.listdir(config.plugin_dir_path),
|
||||
key=lambda n: (not os.path.isfile(os.path.join(config.plugin_dir_path, n, '__init__.py')), n.lower())
|
||||
@@ -198,7 +202,7 @@ def provides(fn_name: str) -> List[str]:
|
||||
|
||||
|
||||
def invoke(
|
||||
plugin_name: str, fallback: str, fn_name: str, *args: Tuple
|
||||
plugin_name: str, fallback: str | None, fn_name: str, *args: Any
|
||||
) -> Optional[str]:
|
||||
"""
|
||||
Invoke a function on a named plugin.
|
||||
@@ -248,7 +252,7 @@ def notify_stop() -> Optional[str]:
|
||||
return error
|
||||
|
||||
|
||||
def notify_prefs_cmdr_changed(cmdr: str, is_beta: bool) -> None:
|
||||
def notify_prefs_cmdr_changed(cmdr: str | None, is_beta: bool) -> None:
|
||||
"""
|
||||
Notify plugins that the Cmdr was changed while the settings dialog is open.
|
||||
|
||||
@@ -265,7 +269,7 @@ def notify_prefs_cmdr_changed(cmdr: str, is_beta: bool) -> None:
|
||||
logger.exception(f'Plugin "{plugin.name}" failed')
|
||||
|
||||
|
||||
def notify_prefs_changed(cmdr: str, is_beta: bool) -> None:
|
||||
def notify_prefs_changed(cmdr: str | None, is_beta: bool) -> None:
|
||||
"""
|
||||
Notify plugins that the settings dialog has been closed.
|
||||
|
||||
@@ -285,7 +289,7 @@ def notify_prefs_changed(cmdr: str, is_beta: bool) -> None:
|
||||
|
||||
|
||||
def notify_journal_entry(
|
||||
cmdr: str, is_beta: bool, system: str, station: str,
|
||||
cmdr: str, is_beta: bool, system: str | None, station: str | None,
|
||||
entry: MutableMapping[str, Any],
|
||||
state: Mapping[str, Any]
|
||||
) -> Optional[str]:
|
||||
@@ -401,6 +405,30 @@ def notify_capidata(
|
||||
return error
|
||||
|
||||
|
||||
def notify_capi_fleetcarrierdata(
|
||||
data: companion.CAPIData
|
||||
) -> str | None:
|
||||
"""
|
||||
Send the latest CAPI Fleetcarrier data from the FD servers to each plugin.
|
||||
|
||||
:param data: The CAPIData returned in the CAPI response
|
||||
:returns: Error message from the first plugin that returns one (if any)
|
||||
"""
|
||||
error = None
|
||||
for plugin in PLUGINS:
|
||||
fc_callback = plugin._get_func('capi_fleetcarrier')
|
||||
if fc_callback is not None and callable(fc_callback):
|
||||
try:
|
||||
# Pass a copy of the CAPIData in case the callee modifies it
|
||||
newerror = fc_callback(copy.deepcopy(data))
|
||||
error = error if error else newerror
|
||||
|
||||
except Exception:
|
||||
logger.exception(f'Plugin "{plugin.name}" failed on receiving Fleetcarrier data')
|
||||
|
||||
return error
|
||||
|
||||
|
||||
def show_error(err: str) -> None:
|
||||
"""
|
||||
Display an error message in the status line of the main window.
|
||||
|
||||
+6
-6
@@ -15,10 +15,9 @@
|
||||
# Thus you **MUST** check if any imports you add in this file are only
|
||||
# referenced in this file (or only in any other core plugin), and if so...
|
||||
#
|
||||
# YOU MUST ENSURE THAT PERTINENT ADJUSTMENTS ARE MADE IN `setup.py`
|
||||
# SO AS TO ENSURE THE FILES ARE ACTUALLY PRESENT IN AN END-USER
|
||||
# INSTALLATION ON WINDOWS.
|
||||
#
|
||||
# YOU MUST ENSURE THAT PERTINENT ADJUSTMENTS ARE MADE IN
|
||||
# `Build-exe-and-msi.py` SO AS TO ENSURE THE FILES ARE ACTUALLY PRESENT
|
||||
# IN AN END-USER INSTALLATION ON WINDOWS.
|
||||
#
|
||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||
@@ -27,6 +26,7 @@ import gzip
|
||||
import io
|
||||
import json
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
import myNotebook as nb # noqa: N813 # its not my fault.
|
||||
@@ -80,7 +80,7 @@ def plugin_start3(path: str) -> str:
|
||||
return 'Coriolis'
|
||||
|
||||
|
||||
def plugin_prefs(parent: tk.Widget, cmdr: str, is_beta: bool) -> tk.Frame:
|
||||
def plugin_prefs(parent: ttk.Notebook, cmdr: str | None, is_beta: bool) -> tk.Frame:
|
||||
"""Set up plugin preferences."""
|
||||
PADX = 10 # noqa: N806
|
||||
|
||||
@@ -127,7 +127,7 @@ def plugin_prefs(parent: tk.Widget, cmdr: str, is_beta: bool) -> tk.Frame:
|
||||
return conf_frame
|
||||
|
||||
|
||||
def prefs_changed(cmdr: str, is_beta: bool) -> None:
|
||||
def prefs_changed(cmdr: str | None, is_beta: bool) -> None:
|
||||
"""Update URLs."""
|
||||
global normal_url, beta_url, override_mode
|
||||
normal_url = normal_textvar.get()
|
||||
|
||||
+40
-59
@@ -42,7 +42,7 @@
|
||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||
import tkinter
|
||||
from typing import TYPE_CHECKING, Any, Mapping, MutableMapping, Optional
|
||||
from typing import TYPE_CHECKING, Any, Mapping
|
||||
|
||||
import requests
|
||||
|
||||
@@ -50,7 +50,7 @@ import EDMCLogging
|
||||
import killswitch
|
||||
import plug
|
||||
from companion import CAPIData
|
||||
from config import config
|
||||
from config import appname, config
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from tkinter import Tk
|
||||
@@ -69,12 +69,12 @@ class This:
|
||||
def __init__(self) -> None:
|
||||
# Main window clicks
|
||||
self.system_link: tkinter.Widget
|
||||
self.system: Optional[str] = None
|
||||
self.system_address: Optional[str] = None
|
||||
self.system_population: Optional[int] = None
|
||||
self.system_name: str | None = None
|
||||
self.system_address: str | None = None
|
||||
self.system_population: int | None = None
|
||||
self.station_link: tkinter.Widget
|
||||
self.station: Optional[str] = None
|
||||
self.station_marketid: Optional[int] = None
|
||||
self.station_name: str | None = None
|
||||
self.station_marketid: int | None = None
|
||||
self.on_foot = False
|
||||
|
||||
|
||||
@@ -131,12 +131,14 @@ def plugin_app(parent: 'Tk'):
|
||||
:param parent: The tk parent to place our widgets into.
|
||||
:return: See PLUGINS.md#display
|
||||
"""
|
||||
this.system_link = parent.children['system'] # system label in main window
|
||||
this.system = None
|
||||
# system label in main window
|
||||
this.system_link = parent.nametowidget(f".{appname.lower()}.system")
|
||||
this.system_name = None
|
||||
this.system_address = None
|
||||
this.station = None
|
||||
this.station_name = None
|
||||
this.station_marketid = None # Frontier MarketID
|
||||
this.station_link = parent.children['station'] # station label in main window
|
||||
# station label in main window
|
||||
this.station_link = parent.nametowidget(f".{appname.lower()}.station")
|
||||
this.station_link['popup_copy'] = lambda x: x != this.STATION_UNDOCKED
|
||||
|
||||
|
||||
@@ -152,9 +154,9 @@ def prefs_changed(cmdr: str, is_beta: bool) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def journal_entry( # noqa: CCR001
|
||||
def journal_entry(
|
||||
cmdr: str, is_beta: bool, system: str, station: str,
|
||||
entry: MutableMapping[str, Any],
|
||||
entry: dict[str, Any],
|
||||
state: Mapping[str, Any]
|
||||
):
|
||||
"""
|
||||
@@ -168,6 +170,9 @@ def journal_entry( # noqa: CCR001
|
||||
:param state: `monitor.state`
|
||||
:return: None if no error, else an error string.
|
||||
"""
|
||||
should_return: bool
|
||||
new_entry: dict[str, Any] = {}
|
||||
|
||||
should_return, new_entry = killswitch.check_killswitch('plugins.eddb.journal', entry)
|
||||
if should_return:
|
||||
# LANG: Journal Processing disabled due to an active killswitch
|
||||
@@ -179,59 +184,35 @@ def journal_entry( # noqa: CCR001
|
||||
return
|
||||
|
||||
this.on_foot = state['OnFoot']
|
||||
# Always update our system address even if we're not currently the provider for system or station, but dont update
|
||||
# on events that contain "future" data, such as FSDTarget
|
||||
if entry['event'] in ('Location', 'Docked', 'CarrierJump', 'FSDJump'):
|
||||
this.system_address = entry.get('SystemAddress') or this.system_address
|
||||
this.system = entry.get('StarSystem') or this.system
|
||||
this.system_address = state['SystemAddress']
|
||||
this.system_name = state['SystemName']
|
||||
this.system_population = state['SystemPopulation']
|
||||
this.station_name = state['StationName']
|
||||
this.station_marketid = state['MarketID']
|
||||
|
||||
# We need pop == 0 to set the value so as to clear 'x' in systems with
|
||||
# no stations.
|
||||
pop = entry.get('Population')
|
||||
if pop is not None:
|
||||
this.system_population = pop
|
||||
|
||||
this.station = entry.get('StationName') or this.station
|
||||
# on_foot station detection
|
||||
if entry['event'] == 'Location' and entry['BodyType'] == 'Station':
|
||||
this.station = entry['Body']
|
||||
|
||||
this.station_marketid = entry.get('MarketID') or this.station_marketid
|
||||
# We might pick up StationName in DockingRequested, make sure we clear it if leaving
|
||||
if entry['event'] in ('Undocked', 'FSDJump', 'SupercruiseEntry'):
|
||||
this.station = None
|
||||
this.station_marketid = None
|
||||
|
||||
if entry['event'] == 'Embark' and not entry.get('OnStation'):
|
||||
# If we're embarking OnStation to a Taxi/Dropship we'll also get an
|
||||
# Undocked event.
|
||||
this.station = None
|
||||
this.station_marketid = None
|
||||
|
||||
# Only actually change URLs if we are current provider.
|
||||
if config.get_str('system_provider') == 'eddb':
|
||||
this.system_link['text'] = this.system
|
||||
# Only change URL text if we are current provider.
|
||||
if config.get_str('station_provider') == 'eddb':
|
||||
this.system_link['text'] = this.system_name
|
||||
# Do *NOT* set 'url' here, as it's set to a function that will call
|
||||
# through correctly. We don't want a static string.
|
||||
this.system_link.update_idletasks()
|
||||
|
||||
# But only actually change the URL if we are current station provider.
|
||||
if config.get_str('station_provider') == 'eddb':
|
||||
text = this.station
|
||||
if not text:
|
||||
if this.station_name:
|
||||
this.station_link['text'] = this.station_name
|
||||
|
||||
else:
|
||||
if this.system_population is not None and this.system_population > 0:
|
||||
text = this.STATION_UNDOCKED
|
||||
this.station_link['text'] = this.STATION_UNDOCKED
|
||||
|
||||
else:
|
||||
text = ''
|
||||
this.station_link['text'] = ''
|
||||
|
||||
this.station_link['text'] = text
|
||||
# Do *NOT* set 'url' here, as it's set to a function that will call
|
||||
# through correctly. We don't want a static string.
|
||||
this.station_link.update_idletasks()
|
||||
|
||||
|
||||
def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]:
|
||||
def cmdr_data(data: CAPIData, is_beta: bool) -> str | None:
|
||||
"""
|
||||
Process new CAPI data.
|
||||
|
||||
@@ -244,22 +225,22 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]:
|
||||
this.station_marketid = data['lastStarport']['id']
|
||||
|
||||
# Only trust CAPI if these aren't yet set
|
||||
if not this.system:
|
||||
this.system = data['lastSystem']['name']
|
||||
if not this.system_name:
|
||||
this.system_name = data['lastSystem']['name']
|
||||
|
||||
if not this.station and data['commander']['docked']:
|
||||
this.station = data['lastStarport']['name']
|
||||
if not this.station_name and data['commander']['docked']:
|
||||
this.station_name = data['lastStarport']['name']
|
||||
|
||||
# Override standard URL functions
|
||||
if config.get_str('system_provider') == 'eddb':
|
||||
this.system_link['text'] = this.system
|
||||
this.system_link['text'] = this.system_name
|
||||
# Do *NOT* set 'url' here, as it's set to a function that will call
|
||||
# through correctly. We don't want a static string.
|
||||
this.system_link.update_idletasks()
|
||||
|
||||
if config.get_str('station_provider') == 'eddb':
|
||||
if data['commander']['docked'] or this.on_foot and this.station:
|
||||
this.station_link['text'] = this.station
|
||||
if data['commander']['docked'] or this.on_foot and this.station_name:
|
||||
this.station_link['text'] = this.station_name
|
||||
|
||||
elif data['lastStarport']['name'] and data['lastStarport']['name'] != "":
|
||||
this.station_link['text'] = this.STATION_UNDOCKED
|
||||
|
||||
+195
-110
@@ -15,10 +15,9 @@
|
||||
# Thus you **MUST** check if any imports you add in this file are only
|
||||
# referenced in this file (or only in any other core plugin), and if so...
|
||||
#
|
||||
# YOU MUST ENSURE THAT PERTINENT ADJUSTMENTS ARE MADE IN `setup.py`
|
||||
# SO AS TO ENSURE THE FILES ARE ACTUALLY PRESENT IN AN END-USER
|
||||
# INSTALLATION ON WINDOWS.
|
||||
#
|
||||
# YOU MUST ENSURE THAT PERTINENT ADJUSTMENTS ARE MADE IN
|
||||
# `Build-exe-and-msi.py` SO AS TO ENSURE THE FILES ARE ACTUALLY PRESENT
|
||||
# IN AN END-USER INSTALLATION ON WINDOWS.
|
||||
#
|
||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||
@@ -35,7 +34,7 @@ from collections import OrderedDict
|
||||
from platform import system
|
||||
from textwrap import dedent
|
||||
from threading import Lock
|
||||
from typing import TYPE_CHECKING, Any, Dict, Iterator, List, Mapping, MutableMapping, Optional
|
||||
from typing import TYPE_CHECKING, Any, Iterator, Mapping, MutableMapping, Optional
|
||||
from typing import OrderedDict as OrderedDictT
|
||||
from typing import Tuple, Union
|
||||
|
||||
@@ -47,7 +46,7 @@ import killswitch
|
||||
import myNotebook as nb # noqa: N813
|
||||
import plug
|
||||
from companion import CAPIData, category_map
|
||||
from config import applongname, appversion_nobuild, config, debug_senders, user_agent
|
||||
from config import applongname, appname, appversion_nobuild, config, debug_senders, user_agent
|
||||
from EDMCLogging import get_main_logger
|
||||
from monitor import monitor
|
||||
from myNotebook import Frame
|
||||
@@ -83,22 +82,27 @@ class This:
|
||||
self.odyssey = False
|
||||
|
||||
# Track location to add to Journal events
|
||||
self.systemaddress: Optional[str] = None
|
||||
self.system_address: Optional[str] = None
|
||||
self.system_name: Optional[str] = None
|
||||
self.coordinates: Optional[Tuple] = None
|
||||
self.body_name: Optional[str] = None
|
||||
self.body_id: Optional[int] = None
|
||||
self.body_type: Optional[int] = None
|
||||
self.station_name: str | None = None
|
||||
self.station_type: str | None = None
|
||||
self.station_marketid: str | None = None
|
||||
# Track Status.json data
|
||||
self.status_body_name: Optional[str] = None
|
||||
|
||||
# Avoid duplicates
|
||||
self.marketId: Optional[str] = None
|
||||
self.commodities: Optional[List[OrderedDictT[str, Any]]] = None
|
||||
self.outfitting: Optional[Tuple[bool, List[str]]] = None
|
||||
self.shipyard: Optional[Tuple[bool, List[Mapping[str, Any]]]] = None
|
||||
self.commodities: Optional[list[OrderedDictT[str, Any]]] = None
|
||||
self.outfitting: Optional[Tuple[bool, list[str]]] = None
|
||||
self.shipyard: Optional[Tuple[bool, list[Mapping[str, Any]]]] = None
|
||||
self.fcmaterials_marketid: int = 0
|
||||
self.fcmaterials: Optional[List[OrderedDictT[str, Any]]] = None
|
||||
self.fcmaterials: Optional[list[OrderedDictT[str, Any]]] = None
|
||||
self.fcmaterials_capi_marketid: int = 0
|
||||
self.fcmaterials_capi: Optional[List[OrderedDictT[str, Any]]] = None
|
||||
self.fcmaterials_capi: Optional[list[OrderedDictT[str, Any]]] = None
|
||||
|
||||
# For the tkinter parent window, so we can call update_idletasks()
|
||||
self.parent: tk.Tk
|
||||
@@ -118,9 +122,15 @@ class This:
|
||||
|
||||
# Tracking UI
|
||||
self.ui: tk.Frame
|
||||
self.ui_system_name: tk.Label
|
||||
self.ui_system_address: tk.Label
|
||||
self.ui_j_body_name: tk.Label
|
||||
self.ui_j_body_id: tk.Label
|
||||
self.ui_j_body_type: tk.Label
|
||||
self.ui_s_body_name: tk.Label
|
||||
self.ui_station_name: tk.Label
|
||||
self.ui_station_type: tk.Label
|
||||
self.ui_station_marketid: tk.Label
|
||||
|
||||
|
||||
this = This()
|
||||
@@ -380,10 +390,10 @@ class EDDNSender:
|
||||
:param text: The status text to be set/logged.
|
||||
"""
|
||||
if os.getenv('EDMC_NO_UI'):
|
||||
logger.INFO(text)
|
||||
logger.info(text)
|
||||
return
|
||||
|
||||
self.eddn.parent.children['status']['text'] = text
|
||||
self.eddn.parent.nametowidget(f".{appname.lower()}.status")['text'] = text
|
||||
|
||||
def send_message(self, msg: str) -> bool:
|
||||
"""
|
||||
@@ -403,6 +413,9 @@ class EDDNSender:
|
||||
:return: `True` for "now remove this message from the queue"
|
||||
"""
|
||||
logger.trace_if("plugin.eddn.send", "Sending message")
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('plugins.eddn.send', json.loads(msg))
|
||||
if should_return:
|
||||
logger.warning('eddn.send has been disabled via killswitch. Returning.')
|
||||
@@ -613,7 +626,7 @@ class EDDN:
|
||||
|
||||
self.sender = EDDNSender(self, self.eddn_url)
|
||||
|
||||
self.fss_signals: List[Mapping[str, Any]] = []
|
||||
self.fss_signals: list[Mapping[str, Any]] = []
|
||||
|
||||
def close(self):
|
||||
"""Close down the EDDN class instance."""
|
||||
@@ -636,13 +649,25 @@ class EDDN:
|
||||
:param data: a dict containing the starport data
|
||||
:param is_beta: whether or not we're currently in beta mode
|
||||
"""
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
should_return, new_data = killswitch.check_killswitch('capi.request./market', {})
|
||||
if should_return:
|
||||
logger.warning("capi.request./market has been disabled by killswitch. Returning.")
|
||||
return
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('eddn.capi_export.commodities', {})
|
||||
if should_return:
|
||||
logger.warning("eddn.capi_export.commodities has been disabled by killswitch. Returning.")
|
||||
return
|
||||
|
||||
modules, ships = self.safe_modules_and_ships(data)
|
||||
horizons: bool = capi_is_horizons(
|
||||
data['lastStarport'].get('economies', {}),
|
||||
modules,
|
||||
ships
|
||||
)
|
||||
commodities: List[OrderedDictT[str, Any]] = []
|
||||
commodities: list[OrderedDictT[str, Any]] = []
|
||||
for commodity in data['lastStarport'].get('commodities') or []:
|
||||
# Check 'marketable' and 'not prohibited'
|
||||
if (category_map.get(commodity['categoryname'], True)
|
||||
@@ -704,7 +729,7 @@ class EDDN:
|
||||
# Send any FCMaterials.json-equivalent 'orders' as well
|
||||
self.export_capi_fcmaterials(data, is_beta, horizons)
|
||||
|
||||
def safe_modules_and_ships(self, data: Mapping[str, Any]) -> Tuple[Dict, Dict]:
|
||||
def safe_modules_and_ships(self, data: Mapping[str, Any]) -> Tuple[dict, dict]:
|
||||
"""
|
||||
Produce a sanity-checked version of ships and modules from CAPI data.
|
||||
|
||||
@@ -715,7 +740,7 @@ class EDDN:
|
||||
:param data: The raw CAPI data.
|
||||
:return: Sanity-checked data.
|
||||
"""
|
||||
modules: Dict[str, Any] = data['lastStarport'].get('modules')
|
||||
modules: dict[str, Any] = data['lastStarport'].get('modules')
|
||||
if modules is None or not isinstance(modules, dict):
|
||||
if modules is None:
|
||||
logger.debug('modules was None. FC or Damaged Station?')
|
||||
@@ -732,7 +757,7 @@ class EDDN:
|
||||
# Set a safe value
|
||||
modules = {}
|
||||
|
||||
ships: Dict[str, Any] = data['lastStarport'].get('ships')
|
||||
ships: dict[str, Any] = data['lastStarport'].get('ships')
|
||||
if ships is None or not isinstance(ships, dict):
|
||||
if ships is None:
|
||||
logger.debug('ships was None')
|
||||
@@ -757,6 +782,18 @@ class EDDN:
|
||||
:param data: dict containing the outfitting data
|
||||
:param is_beta: whether or not we're currently in beta mode
|
||||
"""
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
should_return, new_data = killswitch.check_killswitch('capi.request./shipyard', {})
|
||||
if should_return:
|
||||
logger.warning("capi.request./shipyard has been disabled by killswitch. Returning.")
|
||||
return
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('eddn.capi_export.outfitting', {})
|
||||
if should_return:
|
||||
logger.warning("eddn.capi_export.outfitting has been disabled by killswitch. Returning.")
|
||||
return
|
||||
|
||||
modules, ships = self.safe_modules_and_ships(data)
|
||||
|
||||
# Horizons flag - will hit at least Int_PlanetApproachSuite other than at engineer bases ("Colony"),
|
||||
@@ -773,7 +810,7 @@ class EDDN:
|
||||
modules.values()
|
||||
)
|
||||
|
||||
outfitting: List[str] = sorted(
|
||||
outfitting: list[str] = sorted(
|
||||
self.MODULE_RE.sub(lambda match: match.group(0).capitalize(), mod['name'].lower()) for mod in to_search
|
||||
)
|
||||
|
||||
@@ -813,6 +850,18 @@ class EDDN:
|
||||
:param data: dict containing the shipyard data
|
||||
:param is_beta: whether or not we are in beta mode
|
||||
"""
|
||||
should_return: bool
|
||||
new_data: dict[str, Any]
|
||||
should_return, new_data = killswitch.check_killswitch('capi.request./shipyard', {})
|
||||
if should_return:
|
||||
logger.warning("capi.request./shipyard has been disabled by killswitch. Returning.")
|
||||
return
|
||||
|
||||
should_return, new_data = killswitch.check_killswitch('eddn.capi_export.shipyard', {})
|
||||
if should_return:
|
||||
logger.warning("eddn.capi_export.shipyard has been disabled by killswitch. Returning.")
|
||||
return
|
||||
|
||||
modules, ships = self.safe_modules_and_ships(data)
|
||||
|
||||
horizons: bool = capi_is_horizons(
|
||||
@@ -821,7 +870,7 @@ class EDDN:
|
||||
ships
|
||||
)
|
||||
|
||||
shipyard: List[Mapping[str, Any]] = sorted(
|
||||
shipyard: list[Mapping[str, Any]] = sorted(
|
||||
itertools.chain(
|
||||
(ship['name'].lower() for ship in (ships['shipyard_list'] or {}).values()),
|
||||
(ship['name'].lower() for ship in ships['unavailable_list'] or {}),
|
||||
@@ -864,8 +913,8 @@ class EDDN:
|
||||
:param is_beta: whether or not we're in beta mode
|
||||
:param entry: the journal entry containing the commodities data
|
||||
"""
|
||||
items: List[Mapping[str, Any]] = entry.get('Items') or []
|
||||
commodities: List[OrderedDictT[str, Any]] = sorted((OrderedDict([
|
||||
items: list[Mapping[str, Any]] = entry.get('Items') or []
|
||||
commodities: list[OrderedDictT[str, Any]] = sorted((OrderedDict([
|
||||
('name', self.canonicalise(commodity['Name'])),
|
||||
('meanPrice', commodity['MeanPrice']),
|
||||
('buyPrice', commodity['BuyPrice']),
|
||||
@@ -912,11 +961,11 @@ class EDDN:
|
||||
:param is_beta: Whether or not we're in beta mode
|
||||
:param entry: The relevant journal entry
|
||||
"""
|
||||
modules: List[Mapping[str, Any]] = entry.get('Items', [])
|
||||
modules: list[Mapping[str, Any]] = entry.get('Items', [])
|
||||
horizons: bool = entry.get('Horizons', False)
|
||||
# outfitting = sorted([self.MODULE_RE.sub(lambda m: m.group(0).capitalize(), module['Name'])
|
||||
# for module in modules if module['Name'] != 'int_planetapproachsuite'])
|
||||
outfitting: List[str] = sorted(
|
||||
outfitting: list[str] = sorted(
|
||||
self.MODULE_RE.sub(lambda m: m.group(0).capitalize(), mod['Name']) for mod in
|
||||
filter(lambda m: m['Name'] != 'int_planetapproachsuite', modules)
|
||||
)
|
||||
@@ -951,7 +1000,7 @@ class EDDN:
|
||||
:param is_beta: Whether or not we're in beta mode
|
||||
:param entry: the relevant journal entry
|
||||
"""
|
||||
ships: List[Mapping[str, Any]] = entry.get('PriceList') or []
|
||||
ships: list[Mapping[str, Any]] = entry.get('PriceList') or []
|
||||
horizons: bool = entry.get('Horizons', False)
|
||||
shipyard = sorted(ship['ShipType'] for ship in ships)
|
||||
# Don't send empty ships list - shipyard data is only guaranteed present if user has visited the shipyard.
|
||||
@@ -1078,18 +1127,17 @@ class EDDN:
|
||||
entry['StarSystem'] = system_name
|
||||
|
||||
if 'SystemAddress' not in entry:
|
||||
if this.systemaddress is None:
|
||||
if this.system_address is None:
|
||||
logger.warning("this.systemaddress is None, can't add SystemAddress")
|
||||
return "this.systemaddress is None, can't add SystemAddress"
|
||||
|
||||
entry['SystemAddress'] = this.systemaddress
|
||||
entry['SystemAddress'] = this.system_address
|
||||
|
||||
if 'StarPos' not in entry:
|
||||
# Prefer the passed-in, probably monitor.state version
|
||||
# Prefer the passed-in version
|
||||
if system_coordinates is not None:
|
||||
entry['StarPos'] = system_coordinates
|
||||
|
||||
# TODO: Deprecate in-plugin tracking
|
||||
elif this.coordinates is not None:
|
||||
entry['StarPos'] = list(this.coordinates)
|
||||
|
||||
@@ -1122,7 +1170,7 @@ class EDDN:
|
||||
#######################################################################
|
||||
# In this case should add StarPos, but only if the
|
||||
# SystemAddress of where we think we are matches.
|
||||
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
|
||||
if this.system_address is None or this.system_address != entry['SystemAddress']:
|
||||
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
|
||||
return 'Wrong System! Missed jump ?'
|
||||
|
||||
@@ -1164,7 +1212,7 @@ class EDDN:
|
||||
#######################################################################
|
||||
# In this case should add StarSystem and StarPos, but only if the
|
||||
# SystemAddress of where we think we are matches.
|
||||
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
|
||||
if this.system_address is None or this.system_address != entry['SystemAddress']:
|
||||
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
|
||||
return 'Wrong System! Missed jump ?'
|
||||
|
||||
@@ -1226,7 +1274,7 @@ class EDDN:
|
||||
#######################################################################
|
||||
# In this case should add StarPos, but only if the
|
||||
# SystemAddress of where we think we are matches.
|
||||
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
|
||||
if this.system_address is None or this.system_address != entry['SystemAddress']:
|
||||
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
|
||||
return 'Wrong System! Missed jump ?'
|
||||
|
||||
@@ -1241,6 +1289,8 @@ class EDDN:
|
||||
logger.warning(f'this.status_body_name was not set properly:'
|
||||
f' "{this.status_body_name}" ({type(this.status_body_name)})')
|
||||
|
||||
# this.status_body_name is available for cross-checks, so try to set
|
||||
# BodyName and ID.
|
||||
else:
|
||||
# In case Frontier add it in
|
||||
if 'BodyName' not in entry:
|
||||
@@ -1318,7 +1368,7 @@ class EDDN:
|
||||
#######################################################################
|
||||
# In this case should add StarPos, but only if the
|
||||
# SystemAddress of where we think we are matches.
|
||||
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
|
||||
if this.system_address is None or this.system_address != entry['SystemAddress']:
|
||||
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
|
||||
return 'Wrong System! Missed jump ?'
|
||||
|
||||
@@ -1613,7 +1663,7 @@ class EDDN:
|
||||
#######################################################################
|
||||
# In this case should add SystemName and StarPos, but only if the
|
||||
# SystemAddress of where we think we are matches.
|
||||
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
|
||||
if this.system_address is None or this.system_address != entry['SystemAddress']:
|
||||
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
|
||||
return 'Wrong System! Missed jump ?'
|
||||
|
||||
@@ -1663,7 +1713,7 @@ class EDDN:
|
||||
#######################################################################
|
||||
# In this case should add StarPos, but only if the
|
||||
# SystemAddress of where we think we are matches.
|
||||
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
|
||||
if this.system_address is None or this.system_address != entry['SystemAddress']:
|
||||
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
|
||||
return 'Wrong System! Missed jump ?'
|
||||
|
||||
@@ -1719,7 +1769,7 @@ class EDDN:
|
||||
#######################################################################
|
||||
# In this case should add SystemName and StarPos, but only if the
|
||||
# SystemAddress of where we think we are matches.
|
||||
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
|
||||
if this.system_address is None or this.system_address != entry['SystemAddress']:
|
||||
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
|
||||
return 'Wrong System! Missed jump ?'
|
||||
|
||||
@@ -1777,11 +1827,11 @@ class EDDN:
|
||||
|
||||
else:
|
||||
# Horizons order, so use tracked data for cross-check
|
||||
if this.systemaddress is None or system_name is None or system_starpos is None:
|
||||
logger.error(f'Location tracking failure: {this.systemaddress=}, {system_name=}, {system_starpos=}')
|
||||
if this.system_address is None or system_name is None or system_starpos is None:
|
||||
logger.error(f'Location tracking failure: {this.system_address=}, {system_name=}, {system_starpos=}')
|
||||
return 'Current location not tracked properly, started after game?'
|
||||
|
||||
aug_systemaddress = this.systemaddress
|
||||
aug_systemaddress = this.system_address
|
||||
aug_starsystem = system_name
|
||||
aug_starpos = system_starpos
|
||||
|
||||
@@ -1793,7 +1843,7 @@ class EDDN:
|
||||
#######################################################################
|
||||
|
||||
# Build basis of message
|
||||
msg: Dict = {
|
||||
msg: dict = {
|
||||
'$schemaRef': f'https://eddn.edcd.io/schemas/fsssignaldiscovered/1{"/test" if is_beta else ""}',
|
||||
'message': {
|
||||
"event": "FSSSignalDiscovered",
|
||||
@@ -1857,7 +1907,7 @@ class EDDN:
|
||||
match = self.CANONICALISE_RE.match(item)
|
||||
return match and match.group(1) or item
|
||||
|
||||
def capi_gameversion_from_host_endpoint(self, capi_host: str, capi_endpoint: str) -> str:
|
||||
def capi_gameversion_from_host_endpoint(self, capi_host: Optional[str], capi_endpoint: str) -> str:
|
||||
"""
|
||||
Return the correct CAPI gameversion string for the given host/endpoint.
|
||||
|
||||
@@ -1925,23 +1975,75 @@ def plugin_app(parent: tk.Tk) -> Optional[tk.Frame]:
|
||||
this.ui = tk.Frame(parent)
|
||||
|
||||
row = this.ui.grid_size()[1]
|
||||
|
||||
#######################################################################
|
||||
# System
|
||||
#######################################################################
|
||||
# SystemName
|
||||
system_name_label = tk.Label(this.ui, text="J:SystemName:")
|
||||
system_name_label.grid(row=row, column=0, sticky=tk.W)
|
||||
this.ui_system_name = tk.Label(this.ui, name='eddn_track_system_name', anchor=tk.W)
|
||||
this.ui_system_name.grid(row=row, column=1, sticky=tk.E)
|
||||
row += 1
|
||||
# SystemAddress
|
||||
system_address_label = tk.Label(this.ui, text="J:SystemAddress:")
|
||||
system_address_label.grid(row=row, column=0, sticky=tk.W)
|
||||
this.ui_system_address = tk.Label(this.ui, name='eddn_track_system_address', anchor=tk.W)
|
||||
this.ui_system_address.grid(row=row, column=1, sticky=tk.E)
|
||||
row += 1
|
||||
#######################################################################
|
||||
|
||||
#######################################################################
|
||||
# Body
|
||||
#######################################################################
|
||||
# Body Name from Journal
|
||||
journal_body_name_label = tk.Label(this.ui, text="J:BodyName:")
|
||||
journal_body_name_label.grid(row=row, column=0, sticky=tk.W)
|
||||
this.ui_j_body_name = tk.Label(this.ui, name='eddn_track_j_body_name', anchor=tk.W)
|
||||
this.ui_j_body_name.grid(row=row, column=1, sticky=tk.E)
|
||||
row += 1
|
||||
|
||||
# Body ID from Journal
|
||||
journal_body_id_label = tk.Label(this.ui, text="J:BodyID:")
|
||||
journal_body_id_label.grid(row=row, column=0, sticky=tk.W)
|
||||
this.ui_j_body_id = tk.Label(this.ui, name='eddn_track_j_body_id', anchor=tk.W)
|
||||
this.ui_j_body_id.grid(row=row, column=1, sticky=tk.E)
|
||||
row += 1
|
||||
|
||||
# Body Type from Journal
|
||||
journal_body_type_label = tk.Label(this.ui, text="J:BodyType:")
|
||||
journal_body_type_label.grid(row=row, column=0, sticky=tk.W)
|
||||
this.ui_j_body_type = tk.Label(this.ui, name='eddn_track_j_body_type', anchor=tk.W)
|
||||
this.ui_j_body_type.grid(row=row, column=1, sticky=tk.E)
|
||||
row += 1
|
||||
# Body Name from Status.json
|
||||
status_body_name_label = tk.Label(this.ui, text="S:BodyName:")
|
||||
status_body_name_label.grid(row=row, column=0, sticky=tk.W)
|
||||
this.ui_s_body_name = tk.Label(this.ui, name='eddn_track_s_body_name', anchor=tk.W)
|
||||
this.ui_s_body_name.grid(row=row, column=1, sticky=tk.E)
|
||||
row += 1
|
||||
#######################################################################
|
||||
|
||||
#######################################################################
|
||||
# Station
|
||||
#######################################################################
|
||||
# Name
|
||||
status_station_name_label = tk.Label(this.ui, text="J:StationName:")
|
||||
status_station_name_label.grid(row=row, column=0, sticky=tk.W)
|
||||
this.ui_station_name = tk.Label(this.ui, name='eddn_track_station_name', anchor=tk.W)
|
||||
this.ui_station_name.grid(row=row, column=1, sticky=tk.E)
|
||||
row += 1
|
||||
# Type
|
||||
status_station_type_label = tk.Label(this.ui, text="J:StationType:")
|
||||
status_station_type_label.grid(row=row, column=0, sticky=tk.W)
|
||||
this.ui_station_type = tk.Label(this.ui, name='eddn_track_station_type', anchor=tk.W)
|
||||
this.ui_station_type.grid(row=row, column=1, sticky=tk.E)
|
||||
row += 1
|
||||
# MarketID
|
||||
status_station_marketid_label = tk.Label(this.ui, text="J:StationID:")
|
||||
status_station_marketid_label.grid(row=row, column=0, sticky=tk.W)
|
||||
this.ui_station_marketid = tk.Label(this.ui, name='eddn_track_station_id', anchor=tk.W)
|
||||
this.ui_station_marketid.grid(row=row, column=1, sticky=tk.E)
|
||||
row += 1
|
||||
#######################################################################
|
||||
|
||||
return this.ui
|
||||
|
||||
@@ -1953,6 +2055,14 @@ def tracking_ui_update() -> None:
|
||||
if not config.eddn_tracking_ui:
|
||||
return
|
||||
|
||||
this.ui_system_name['text'] = '≪None≫'
|
||||
if this.ui_system_name is not None:
|
||||
this.ui_system_name['text'] = this.system_name
|
||||
|
||||
this.ui_system_address['text'] = '≪None≫'
|
||||
if this.ui_system_address is not None:
|
||||
this.ui_system_address['text'] = this.system_address
|
||||
|
||||
this.ui_j_body_name['text'] = '≪None≫'
|
||||
if this.body_name is not None:
|
||||
this.ui_j_body_name['text'] = this.body_name
|
||||
@@ -1961,10 +2071,26 @@ def tracking_ui_update() -> None:
|
||||
if this.body_id is not None:
|
||||
this.ui_j_body_id['text'] = str(this.body_id)
|
||||
|
||||
this.ui_j_body_type['text'] = '≪None≫'
|
||||
if this.body_type is not None:
|
||||
this.ui_j_body_type['text'] = str(this.body_type)
|
||||
|
||||
this.ui_s_body_name['text'] = '≪None≫'
|
||||
if this.status_body_name is not None:
|
||||
this.ui_s_body_name['text'] = this.status_body_name
|
||||
|
||||
this.ui_station_name['text'] = '≪None≫'
|
||||
if this.station_name is not None:
|
||||
this.ui_station_name['text'] = this.station_name
|
||||
|
||||
this.ui_station_type['text'] = '≪None≫'
|
||||
if this.station_type is not None:
|
||||
this.ui_station_type['text'] = this.station_type
|
||||
|
||||
this.ui_station_marketid['text'] = '≪None≫'
|
||||
if this.station_marketid is not None:
|
||||
this.ui_station_marketid['text'] = this.station_marketid
|
||||
|
||||
this.ui.update_idletasks()
|
||||
|
||||
|
||||
@@ -2170,68 +2296,28 @@ def journal_entry( # noqa: C901, CCR001
|
||||
entry
|
||||
)
|
||||
|
||||
# Track location
|
||||
if event_name == 'supercruiseexit':
|
||||
# For any orbital station we have no way of determining the body
|
||||
# it orbits:
|
||||
#
|
||||
# In-ship Status.json doesn't specify this.
|
||||
# On-foot Status.json lists the station itself as Body.
|
||||
# Location for stations (on-foot or in-ship) has station as Body.
|
||||
# SupercruiseExit (own ship or taxi) lists the station as the Body.
|
||||
if entry['BodyType'] == 'Station':
|
||||
this.body_name = None
|
||||
this.body_id = None
|
||||
# Copy some state into module-held variables because we might need it
|
||||
# outside of this function.
|
||||
this.body_name = state['Body']
|
||||
this.body_id = state['BodyID']
|
||||
this.body_type = state['BodyType']
|
||||
this.coordinates = state['StarPos']
|
||||
this.system_address = state['SystemAddress']
|
||||
this.system_name = state['SystemName']
|
||||
this.station_name = state['StationName']
|
||||
this.station_type = state['StationType']
|
||||
this.station_marketid = state['MarketID']
|
||||
|
||||
elif event_name in ('location', 'fsdjump', 'docked', 'carrierjump'):
|
||||
if event_name in ('location', 'carrierjump'):
|
||||
if entry.get('BodyType') == 'Planet':
|
||||
this.body_name = entry.get('Body')
|
||||
this.body_id = entry.get('BodyID')
|
||||
|
||||
else:
|
||||
this.body_name = None
|
||||
|
||||
elif event_name == 'fsdjump':
|
||||
this.body_name = None
|
||||
this.body_id = None
|
||||
|
||||
if 'StarPos' in entry:
|
||||
this.coordinates = tuple(entry['StarPos'])
|
||||
|
||||
elif this.systemaddress != entry.get('SystemAddress'):
|
||||
this.coordinates = None # Docked event doesn't include coordinates
|
||||
|
||||
if 'SystemAddress' not in entry:
|
||||
logger.warning(f'"location" event without SystemAddress !!!:\n{entry}\n')
|
||||
|
||||
# But we'll still *use* the value, because if a 'location' event doesn't
|
||||
# have this we've still moved and now don't know where and MUST NOT
|
||||
# continue to use any old value.
|
||||
# Yes, explicitly state `None` here, so it's crystal clear.
|
||||
this.systemaddress = entry.get('SystemAddress', None) # type: ignore
|
||||
|
||||
if event_name == 'docked':
|
||||
this.eddn.parent.after(this.eddn.REPLAY_DELAY, this.eddn.sender.queue_check_and_send, False)
|
||||
|
||||
elif event_name == 'approachbody':
|
||||
this.body_name = entry['Body']
|
||||
this.body_id = entry.get('BodyID')
|
||||
|
||||
elif event_name == 'leavebody':
|
||||
# NB: **NOT** SupercruiseEntry, because we won't get a fresh
|
||||
# ApproachBody if we don't leave Orbital Cruise and land again.
|
||||
# *This* is triggered when you go above Orbital Cruise altitude.
|
||||
# Status.json BodyName clears when the OC/Glide HUD is deactivated.
|
||||
this.body_name = None
|
||||
this.body_id = None
|
||||
if event_name == 'docked':
|
||||
# Trigger a send/retry of pending EDDN messages
|
||||
this.eddn.parent.after(this.eddn.REPLAY_DELAY, this.eddn.sender.queue_check_and_send, False)
|
||||
|
||||
elif event_name == 'music':
|
||||
if entry['MusicTrack'] == 'MainMenu':
|
||||
this.body_name = None
|
||||
this.body_id = None
|
||||
this.status_body_name = None
|
||||
|
||||
tracking_ui_update()
|
||||
|
||||
# Events with their own EDDN schema
|
||||
if config.get_int('output') & config.OUT_EDDN_SEND_NON_STATION and not state['Captain']:
|
||||
|
||||
@@ -2321,9 +2407,10 @@ def journal_entry( # noqa: C901, CCR001
|
||||
]
|
||||
|
||||
# add planet to Docked event for planetary stations if known
|
||||
if event_name == 'docked' and this.body_name:
|
||||
entry['Body'] = this.body_name
|
||||
entry['BodyType'] = 'Planet'
|
||||
if event_name == 'docked' and state['Body'] is not None:
|
||||
if state['BodyType'] == 'Planet':
|
||||
entry['Body'] = state['Body']
|
||||
entry['BodyType'] = state['BodyType']
|
||||
|
||||
# The generic journal schema is for events:
|
||||
# Docked, FSDJump, Scan, Location, SAASignalsFound, CarrierJump
|
||||
@@ -2344,7 +2431,7 @@ def journal_entry( # noqa: C901, CCR001
|
||||
|
||||
# add mandatory StarSystem and StarPos properties to events
|
||||
if 'StarSystem' not in entry:
|
||||
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
|
||||
if this.system_address is None or this.system_address != entry['SystemAddress']:
|
||||
logger.warning(f"event({entry['event']}) has no StarSystem, but SystemAddress isn't current location")
|
||||
return "Wrong System! Delayed Scan event?"
|
||||
|
||||
@@ -2361,7 +2448,7 @@ def journal_entry( # noqa: C901, CCR001
|
||||
|
||||
# Gazelle[TD] reported seeing a lagged Scan event with incorrect
|
||||
# augmented StarPos: <https://github.com/EDCD/EDMarketConnector/issues/961>
|
||||
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
|
||||
if this.system_address is None or this.system_address != entry['SystemAddress']:
|
||||
logger.warning(f"event({entry['event']}) has no StarPos, but SystemAddress isn't current location")
|
||||
return "Wrong System! Delayed Scan event?"
|
||||
|
||||
@@ -2416,8 +2503,6 @@ def journal_entry( # noqa: C901, CCR001
|
||||
logger.debug(f'Failed exporting {entry["event"]}', exc_info=e)
|
||||
return str(e)
|
||||
|
||||
tracking_ui_update()
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@@ -2456,14 +2541,14 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]: # noqa: CCR001
|
||||
):
|
||||
this.cmdr_name = cmdr_name
|
||||
|
||||
if (data['commander'].get('docked') or (this.on_foot and monitor.station)
|
||||
if (data['commander'].get('docked') or (this.on_foot and monitor.state['StationName'])
|
||||
and config.get_int('output') & config.OUT_EDDN_SEND_STATION_DATA):
|
||||
try:
|
||||
if this.marketId != data['lastStarport']['id']:
|
||||
this.commodities = this.outfitting = this.shipyard = None
|
||||
this.marketId = data['lastStarport']['id']
|
||||
|
||||
status = this.parent.children['status']
|
||||
status = this.parent.nametowidget(f".{appname.lower()}.status")
|
||||
old_status = status['text']
|
||||
if not old_status:
|
||||
status['text'] = _('Sending data to EDDN...') # LANG: Status text shown while attempting to send data
|
||||
@@ -2541,7 +2626,7 @@ def capi_is_horizons(economies: MAP_STR_ANY, modules: MAP_STR_ANY, ships: MAP_ST
|
||||
return economies_colony or modules_horizons or ship_horizons
|
||||
|
||||
|
||||
def dashboard_entry(cmdr: str, is_beta: bool, entry: Dict[str, Any]) -> None:
|
||||
def dashboard_entry(cmdr: str, is_beta: bool, entry: dict[str, Any]) -> None:
|
||||
"""
|
||||
Process Status.json data to track things like current Body.
|
||||
|
||||
|
||||
+166
-148
@@ -38,16 +38,18 @@ from datetime import datetime, timedelta, timezone
|
||||
from queue import Queue
|
||||
from threading import Thread
|
||||
from time import sleep
|
||||
from typing import TYPE_CHECKING, Any, List, Literal, Mapping, MutableMapping, Optional, Set, Tuple, Union, cast
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Mapping, MutableMapping, Optional, Set, Tuple, Union, cast
|
||||
|
||||
import requests
|
||||
|
||||
import killswitch
|
||||
import monitor
|
||||
import myNotebook
|
||||
import myNotebook as nb # noqa: N813
|
||||
import plug
|
||||
from companion import CAPIData
|
||||
from config import applongname, appversion, config, debug_senders, user_agent
|
||||
from config import applongname, appname, appversion, config, debug_senders, user_agent
|
||||
from edmc_data import DEBUG_WEBSERVER_HOST, DEBUG_WEBSERVER_PORT
|
||||
from EDMCLogging import get_main_logger
|
||||
from ttkHyperlinkLabel import HyperlinkLabel
|
||||
@@ -82,8 +84,8 @@ class This:
|
||||
self.session: requests.Session = requests.Session()
|
||||
self.session.headers['User-Agent'] = user_agent
|
||||
self.queue: Queue = Queue() # Items to be sent to EDSM by worker thread
|
||||
self.discarded_events: Set[str] = [] # List discarded events from EDSM
|
||||
self.lastlookup: requests.Response # Result of last system lookup
|
||||
self.discarded_events: Set[str] = set() # List discarded events from EDSM
|
||||
self.lastlookup: Dict[str, Any] # Result of last system lookup
|
||||
|
||||
# Game state
|
||||
self.multicrew: bool = False # don't send captain's ship info to EDSM while on a crew
|
||||
@@ -91,13 +93,13 @@ class This:
|
||||
self.newgame: bool = False # starting up - batch initial burst of events
|
||||
self.newgame_docked: bool = False # starting up while docked
|
||||
self.navbeaconscan: int = 0 # batch up burst of Scan events after NavBeaconScan
|
||||
self.system_link: tk.Widget = None
|
||||
self.system: tk.Tk = None
|
||||
self.system_address: Optional[int] = None # Frontier SystemAddress
|
||||
self.system_population: Optional[int] = None
|
||||
self.station_link: tk.Widget = None
|
||||
self.station: Optional[str] = None
|
||||
self.station_marketid: Optional[int] = None # Frontier MarketID
|
||||
self.system_link: tk.Widget | None = None
|
||||
self.system_name: tk.Tk | None = None
|
||||
self.system_address: int | None = None # Frontier SystemAddress
|
||||
self.system_population: int | None = None
|
||||
self.station_link: tk.Widget | None = None
|
||||
self.station_name: str | None = None
|
||||
self.station_marketid: int | None = None # Frontier MarketID
|
||||
self.on_foot = False
|
||||
|
||||
self._IMG_KNOWN = None
|
||||
@@ -107,19 +109,19 @@ class This:
|
||||
|
||||
self.thread: Optional[threading.Thread] = None
|
||||
|
||||
self.log = None
|
||||
self.log_button = None
|
||||
self.log: tk.IntVar | None = None
|
||||
self.log_button: ttk.Checkbutton | None = None
|
||||
|
||||
self.label = None
|
||||
self.label: tk.Widget | None = None
|
||||
|
||||
self.cmdr_label = None
|
||||
self.cmdr_text = None
|
||||
self.cmdr_label: myNotebook.Label | None = None
|
||||
self.cmdr_text: myNotebook.Label | None = None
|
||||
|
||||
self.user_label = None
|
||||
self.user = None
|
||||
self.user_label: myNotebook.Label | None = None
|
||||
self.user: myNotebook.Entry | None = None
|
||||
|
||||
self.apikey_label = None
|
||||
self.apikey = None
|
||||
self.apikey_label: myNotebook.Label | None = None
|
||||
self.apikey: myNotebook.Entry | None = None
|
||||
|
||||
|
||||
this = This()
|
||||
@@ -184,9 +186,9 @@ def station_url(system_name: str, station_name: str) -> str:
|
||||
)
|
||||
|
||||
# monitor state might think these are gone, but we don't yet
|
||||
if this.system and this.station:
|
||||
if this.system_name and this.station_name:
|
||||
return requests.utils.requote_uri(
|
||||
f'https://www.edsm.net/en/system?systemName={this.system}&stationName={this.station}'
|
||||
f'https://www.edsm.net/en/system?systemName={this.system_name}&stationName={this.station_name}'
|
||||
)
|
||||
|
||||
if system_name:
|
||||
@@ -248,9 +250,15 @@ def plugin_app(parent: tk.Tk) -> None:
|
||||
:param parent: The tk parent to place our widgets into.
|
||||
:return: See PLUGINS.md#display
|
||||
"""
|
||||
this.system_link = parent.children['system'] # system label in main window
|
||||
# system label in main window
|
||||
this.system_link = parent.nametowidget(f".{appname.lower()}.system")
|
||||
if this.system_link is None:
|
||||
logger.error("Couldn't look up system widget!!!")
|
||||
return
|
||||
|
||||
this.system_link.bind_all('<<EDSMStatus>>', update_status)
|
||||
this.station_link = parent.children['station'] # station label in main window
|
||||
# station label in main window
|
||||
this.station_link = parent.nametowidget(f".{appname.lower()}.station")
|
||||
|
||||
|
||||
def plugin_stop() -> None:
|
||||
@@ -267,7 +275,7 @@ def plugin_stop() -> None:
|
||||
logger.debug('Done.')
|
||||
|
||||
|
||||
def plugin_prefs(parent: tk.Tk, cmdr: str, is_beta: bool) -> tk.Frame:
|
||||
def plugin_prefs(parent: ttk.Notebook, cmdr: str | None, is_beta: bool) -> tk.Frame:
|
||||
"""
|
||||
Plugin preferences setup hook.
|
||||
|
||||
@@ -300,7 +308,8 @@ def plugin_prefs(parent: tk.Tk, cmdr: str, is_beta: bool) -> tk.Frame:
|
||||
frame, text=_('Send flight log and Cmdr status to EDSM'), variable=this.log, command=prefsvarchanged
|
||||
)
|
||||
|
||||
this.log_button.grid(columnspan=2, padx=BUTTONX, pady=(5, 0), sticky=tk.W)
|
||||
if this.log_button:
|
||||
this.log_button.grid(columnspan=2, padx=BUTTONX, pady=(5, 0), sticky=tk.W)
|
||||
|
||||
nb.Label(frame).grid(sticky=tk.W) # big spacer
|
||||
# Section heading in settings
|
||||
@@ -315,61 +324,77 @@ def plugin_prefs(parent: tk.Tk, cmdr: str, is_beta: bool) -> tk.Frame:
|
||||
|
||||
cur_row = 10
|
||||
|
||||
this.label.grid(columnspan=2, padx=PADX, sticky=tk.W)
|
||||
if this.label:
|
||||
this.label.grid(columnspan=2, padx=PADX, sticky=tk.W)
|
||||
|
||||
# LANG: Game Commander name label in EDSM settings
|
||||
this.cmdr_label = nb.Label(frame, text=_('Cmdr')) # Main window
|
||||
this.cmdr_label.grid(row=cur_row, padx=PADX, sticky=tk.W)
|
||||
this.cmdr_text = nb.Label(frame)
|
||||
this.cmdr_text.grid(row=cur_row, column=1, padx=PADX, pady=PADY, sticky=tk.W)
|
||||
if this.cmdr_label and this.cmdr_text:
|
||||
# LANG: Game Commander name label in EDSM settings
|
||||
this.cmdr_label = nb.Label(frame, text=_('Cmdr')) # Main window
|
||||
this.cmdr_label.grid(row=cur_row, padx=PADX, sticky=tk.W)
|
||||
this.cmdr_text = nb.Label(frame)
|
||||
this.cmdr_text.grid(row=cur_row, column=1, padx=PADX, pady=PADY, sticky=tk.W)
|
||||
|
||||
cur_row += 1
|
||||
|
||||
# LANG: EDSM Commander name label in EDSM settings
|
||||
this.user_label = nb.Label(frame, text=_('Commander Name')) # EDSM setting
|
||||
this.user_label.grid(row=cur_row, padx=PADX, sticky=tk.W)
|
||||
this.user = nb.Entry(frame)
|
||||
this.user.grid(row=cur_row, column=1, padx=PADX, pady=PADY, sticky=tk.EW)
|
||||
if this.user_label and this.label:
|
||||
# LANG: EDSM Commander name label in EDSM settings
|
||||
this.user_label = nb.Label(frame, text=_('Commander Name')) # EDSM setting
|
||||
this.user_label.grid(row=cur_row, padx=PADX, sticky=tk.W)
|
||||
this.user = nb.Entry(frame)
|
||||
this.user.grid(row=cur_row, column=1, padx=PADX, pady=PADY, sticky=tk.EW)
|
||||
|
||||
cur_row += 1
|
||||
|
||||
# LANG: EDSM API key label
|
||||
this.apikey_label = nb.Label(frame, text=_('API Key')) # EDSM setting
|
||||
this.apikey_label.grid(row=cur_row, padx=PADX, sticky=tk.W)
|
||||
this.apikey = nb.Entry(frame)
|
||||
this.apikey.grid(row=cur_row, column=1, padx=PADX, pady=PADY, sticky=tk.EW)
|
||||
if this.apikey_label and this.apikey:
|
||||
# LANG: EDSM API key label
|
||||
this.apikey_label = nb.Label(frame, text=_('API Key')) # EDSM setting
|
||||
this.apikey_label.grid(row=cur_row, padx=PADX, sticky=tk.W)
|
||||
this.apikey = nb.Entry(frame)
|
||||
this.apikey.grid(row=cur_row, column=1, padx=PADX, pady=PADY, sticky=tk.EW)
|
||||
|
||||
prefs_cmdr_changed(cmdr, is_beta)
|
||||
|
||||
return frame
|
||||
|
||||
|
||||
def prefs_cmdr_changed(cmdr: str, is_beta: bool) -> None:
|
||||
def prefs_cmdr_changed(cmdr: str | None, is_beta: bool) -> None: # noqa: CCR001
|
||||
"""
|
||||
Handle the Commander name changing whilst Settings was open.
|
||||
|
||||
:param cmdr: The new current Commander name.
|
||||
:param is_beta: Whether game beta was detected.
|
||||
"""
|
||||
this.log_button['state'] = tk.NORMAL if cmdr and not is_beta else tk.DISABLED
|
||||
this.user['state'] = tk.NORMAL
|
||||
this.user.delete(0, tk.END)
|
||||
this.apikey['state'] = tk.NORMAL
|
||||
this.apikey.delete(0, tk.END)
|
||||
if this.log_button:
|
||||
this.log_button['state'] = tk.NORMAL if cmdr and not is_beta else tk.DISABLED
|
||||
|
||||
if this.user:
|
||||
this.user['state'] = tk.NORMAL
|
||||
this.user.delete(0, tk.END)
|
||||
|
||||
if this.apikey:
|
||||
this.apikey['state'] = tk.NORMAL
|
||||
this.apikey.delete(0, tk.END)
|
||||
|
||||
if cmdr:
|
||||
this.cmdr_text['text'] = f'{cmdr}{" [Beta]" if is_beta else ""}'
|
||||
if this.cmdr_text:
|
||||
this.cmdr_text['text'] = f'{cmdr}{" [Beta]" if is_beta else ""}'
|
||||
|
||||
cred = credentials(cmdr)
|
||||
|
||||
if cred:
|
||||
this.user.insert(0, cred[0])
|
||||
this.apikey.insert(0, cred[1])
|
||||
if this.user:
|
||||
this.user.insert(0, cred[0])
|
||||
|
||||
if this.apikey:
|
||||
this.apikey.insert(0, cred[1])
|
||||
|
||||
else:
|
||||
# LANG: We have no data on the current commander
|
||||
this.cmdr_text['text'] = _('None')
|
||||
if this.cmdr_text:
|
||||
# LANG: We have no data on the current commander
|
||||
this.cmdr_text['text'] = _('None')
|
||||
|
||||
to_set: Union[Literal['normal'], Literal['disabled']] = tk.DISABLED
|
||||
if cmdr and not is_beta and this.log.get():
|
||||
if cmdr and not is_beta and this.log and this.log.get():
|
||||
to_set = tk.NORMAL
|
||||
|
||||
set_prefs_ui_states(to_set)
|
||||
@@ -378,7 +403,7 @@ def prefs_cmdr_changed(cmdr: str, is_beta: bool) -> None:
|
||||
def prefsvarchanged() -> None:
|
||||
"""Handle the 'Send data to EDSM' tickbox changing state."""
|
||||
to_set = tk.DISABLED
|
||||
if this.log.get():
|
||||
if this.log and this.log.get() and this.log_button:
|
||||
to_set = this.log_button['state']
|
||||
|
||||
set_prefs_ui_states(to_set)
|
||||
@@ -390,13 +415,17 @@ def set_prefs_ui_states(state: str) -> None:
|
||||
|
||||
:param state: the state to set each entry to
|
||||
"""
|
||||
this.label['state'] = state
|
||||
this.cmdr_label['state'] = state
|
||||
this.cmdr_text['state'] = state
|
||||
this.user_label['state'] = state
|
||||
this.user['state'] = state
|
||||
this.apikey_label['state'] = state
|
||||
this.apikey['state'] = state
|
||||
if (
|
||||
this.label and this.cmdr_label and this.cmdr_text and this.user_label and this.user
|
||||
and this.apikey_label and this.apikey
|
||||
):
|
||||
this.label['state'] = state
|
||||
this.cmdr_label['state'] = state
|
||||
this.cmdr_text['state'] = state
|
||||
this.user_label['state'] = state
|
||||
this.user['state'] = state
|
||||
this.apikey_label['state'] = state
|
||||
this.apikey['state'] = state
|
||||
|
||||
|
||||
def prefs_changed(cmdr: str, is_beta: bool) -> None:
|
||||
@@ -406,7 +435,8 @@ def prefs_changed(cmdr: str, is_beta: bool) -> None:
|
||||
:param cmdr: Name of Commander.
|
||||
:param is_beta: Whether game beta was detected.
|
||||
"""
|
||||
config.set('edsm_out', this.log.get())
|
||||
if this.log:
|
||||
config.set('edsm_out', this.log.get())
|
||||
|
||||
if cmdr and not is_beta:
|
||||
# TODO: remove this when config is rewritten.
|
||||
@@ -414,17 +444,18 @@ def prefs_changed(cmdr: str, is_beta: bool) -> None:
|
||||
usernames: List[str] = config.get_list('edsm_usernames', default=[])
|
||||
apikeys: List[str] = config.get_list('edsm_apikeys', default=[])
|
||||
|
||||
if cmdr in cmdrs:
|
||||
idx = cmdrs.index(cmdr)
|
||||
usernames.extend([''] * (1 + idx - len(usernames)))
|
||||
usernames[idx] = this.user.get().strip()
|
||||
apikeys.extend([''] * (1 + idx - len(apikeys)))
|
||||
apikeys[idx] = this.apikey.get().strip()
|
||||
if this.user and this.apikey:
|
||||
if cmdr in cmdrs:
|
||||
idx = cmdrs.index(cmdr)
|
||||
usernames.extend([''] * (1 + idx - len(usernames)))
|
||||
usernames[idx] = this.user.get().strip()
|
||||
apikeys.extend([''] * (1 + idx - len(apikeys)))
|
||||
apikeys[idx] = this.apikey.get().strip()
|
||||
|
||||
else:
|
||||
config.set('edsm_cmdrs', cmdrs + [cmdr])
|
||||
usernames.append(this.user.get().strip())
|
||||
apikeys.append(this.apikey.get().strip())
|
||||
else:
|
||||
config.set('edsm_cmdrs', cmdrs + [cmdr])
|
||||
usernames.append(this.user.get().strip())
|
||||
apikeys.append(this.apikey.get().strip())
|
||||
|
||||
config.set('edsm_usernames', usernames)
|
||||
config.set('edsm_apikeys', apikeys)
|
||||
@@ -494,6 +525,11 @@ def journal_entry( # noqa: C901, CCR001
|
||||
|
||||
this.game_version = state['GameVersion']
|
||||
this.game_build = state['GameBuild']
|
||||
this.system_address = state['SystemAddress']
|
||||
this.system_name = state['SystemName']
|
||||
this.system_population = state['SystemPopulation']
|
||||
this.station_name = state['StationName']
|
||||
this.station_marketid = state['MarketID']
|
||||
|
||||
entry = new_entry
|
||||
|
||||
@@ -507,50 +543,23 @@ Station: {station}
|
||||
state: {state!r}
|
||||
entry: {entry!r}'''
|
||||
)
|
||||
# Always update our system address even if we're not currently the provider for system or station, but dont update
|
||||
# on events that contain "future" data, such as FSDTarget
|
||||
if entry['event'] in ('Location', 'Docked', 'CarrierJump', 'FSDJump'):
|
||||
this.system_address = entry.get('SystemAddress', this.system_address)
|
||||
this.system = entry.get('StarSystem', this.system)
|
||||
|
||||
# We need pop == 0 to set the value so as to clear 'x' in systems with
|
||||
# no stations.
|
||||
pop = entry.get('Population')
|
||||
if pop is not None:
|
||||
this.system_population = pop
|
||||
|
||||
this.station = entry.get('StationName', this.station)
|
||||
# on_foot station detection
|
||||
if entry['event'] == 'Location' and entry['BodyType'] == 'Station':
|
||||
this.station = entry['Body']
|
||||
|
||||
this.station_marketid = entry.get('MarketID', this.station_marketid)
|
||||
# We might pick up StationName in DockingRequested, make sure we clear it if leaving
|
||||
if entry['event'] in ('Undocked', 'FSDJump', 'SupercruiseEntry'):
|
||||
this.station = None
|
||||
this.station_marketid = None
|
||||
|
||||
if entry['event'] == 'Embark' and not entry.get('OnStation'):
|
||||
# If we're embarking OnStation to a Taxi/Dropship we'll also get an
|
||||
# Undocked event.
|
||||
this.station = None
|
||||
this.station_marketid = None
|
||||
|
||||
if config.get_str('station_provider') == 'EDSM':
|
||||
to_set = this.station
|
||||
if not this.station:
|
||||
to_set = this.station_name
|
||||
if not this.station_name:
|
||||
if this.system_population and this.system_population > 0:
|
||||
to_set = STATION_UNDOCKED
|
||||
|
||||
else:
|
||||
to_set = ''
|
||||
|
||||
this.station_link['text'] = to_set
|
||||
this.station_link['url'] = station_url(str(this.system), str(this.station))
|
||||
this.station_link.update_idletasks()
|
||||
if this.station_link:
|
||||
this.station_link['text'] = to_set
|
||||
this.station_link['url'] = station_url(str(this.system_name), str(this.station_name))
|
||||
this.station_link.update_idletasks()
|
||||
|
||||
# Update display of 'EDSM Status' image
|
||||
if this.system_link['text'] != system:
|
||||
if this.system_link and this.system_link['text'] != system:
|
||||
this.system_link['text'] = system if system else ''
|
||||
this.system_link['image'] = ''
|
||||
this.system_link.update_idletasks()
|
||||
@@ -596,9 +605,8 @@ entry: {entry!r}'''
|
||||
):
|
||||
# LANG: The Inara API only accepts Live galaxy data, not Legacy galaxy data
|
||||
logger.info("EDSM only accepts Live galaxy data")
|
||||
# this.parent.children['status']['text'] =
|
||||
this.legacy_galaxy_last_notified = datetime.now(timezone.utc)
|
||||
return _("EDSM only accepts Live galaxy data")
|
||||
return _("EDSM only accepts Live galaxy data") # LANG: EDSM - Only Live data
|
||||
|
||||
return ''
|
||||
|
||||
@@ -639,7 +647,7 @@ Queueing: {entry!r}'''
|
||||
|
||||
|
||||
# Update system data
|
||||
def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]:
|
||||
def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]: # noqa: CCR001
|
||||
"""
|
||||
Process new CAPI data.
|
||||
|
||||
@@ -654,36 +662,38 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]:
|
||||
this.station_marketid = data['lastStarport']['id']
|
||||
|
||||
# Only trust CAPI if these aren't yet set
|
||||
if not this.system:
|
||||
this.system = data['lastSystem']['name']
|
||||
if not this.system_name:
|
||||
this.system_name = data['lastSystem']['name']
|
||||
|
||||
if not this.station and data['commander']['docked']:
|
||||
this.station = data['lastStarport']['name']
|
||||
if not this.station_name and data['commander']['docked']:
|
||||
this.station_name = data['lastStarport']['name']
|
||||
|
||||
# TODO: Fire off the EDSM API call to trigger the callback for the icons
|
||||
|
||||
if config.get_str('system_provider') == 'EDSM':
|
||||
this.system_link['text'] = this.system
|
||||
# Do *NOT* set 'url' here, as it's set to a function that will call
|
||||
# through correctly. We don't want a static string.
|
||||
this.system_link.update_idletasks()
|
||||
if this.system_link:
|
||||
this.system_link['text'] = this.system_name
|
||||
# Do *NOT* set 'url' here, as it's set to a function that will call
|
||||
# through correctly. We don't want a static string.
|
||||
this.system_link.update_idletasks()
|
||||
|
||||
if config.get_str('station_provider') == 'EDSM':
|
||||
if data['commander']['docked'] or this.on_foot and this.station:
|
||||
this.station_link['text'] = this.station
|
||||
if this.station_link:
|
||||
if data['commander']['docked'] or this.on_foot and this.station_name:
|
||||
this.station_link['text'] = this.station_name
|
||||
|
||||
elif data['lastStarport']['name'] and data['lastStarport']['name'] != "":
|
||||
this.station_link['text'] = STATION_UNDOCKED
|
||||
elif data['lastStarport']['name'] and data['lastStarport']['name'] != "":
|
||||
this.station_link['text'] = STATION_UNDOCKED
|
||||
|
||||
else:
|
||||
this.station_link['text'] = ''
|
||||
else:
|
||||
this.station_link['text'] = ''
|
||||
|
||||
# Do *NOT* set 'url' here, as it's set to a function that will call
|
||||
# through correctly. We don't want a static string.
|
||||
# Do *NOT* set 'url' here, as it's set to a function that will call
|
||||
# through correctly. We don't want a static string.
|
||||
|
||||
this.station_link.update_idletasks()
|
||||
this.station_link.update_idletasks()
|
||||
|
||||
if not this.system_link['text']:
|
||||
if this.system_link and not this.system_link['text']:
|
||||
this.system_link['text'] = system
|
||||
this.system_link['image'] = ''
|
||||
this.system_link.update_idletasks()
|
||||
@@ -759,9 +769,12 @@ def worker() -> None: # noqa: CCR001 C901 # Cant be broken up currently
|
||||
|
||||
retrying = 0
|
||||
while retrying < 3:
|
||||
if item is None:
|
||||
item = cast(Tuple[str, str, str, Mapping[str, Any]], ("", {}))
|
||||
|
||||
should_skip, new_item = killswitch.check_killswitch(
|
||||
'plugins.edsm.worker',
|
||||
item if item is not None else cast(Tuple[str, Mapping[str, Any]], ("", {})),
|
||||
item,
|
||||
logger
|
||||
)
|
||||
|
||||
@@ -838,8 +851,12 @@ def worker() -> None: # noqa: CCR001 C901 # Cant be broken up currently
|
||||
if any(p for p in pending if p['event'] in ('CarrierJump', 'FSDJump', 'Location', 'Docked')):
|
||||
data_elided = data.copy()
|
||||
data_elided['apiKey'] = '<elided>'
|
||||
data_elided['message'] = data_elided['message'].decode('utf-8')
|
||||
data_elided['commanderName'] = data_elided['commanderName'].decode('utf-8')
|
||||
if isinstance(data_elided['message'], bytes):
|
||||
data_elided['message'] = data_elided['message'].decode('utf-8')
|
||||
|
||||
if isinstance(data_elided['commanderName'], bytes):
|
||||
data_elided['commanderName'] = data_elided['commanderName'].decode('utf-8')
|
||||
|
||||
logger.trace_if(
|
||||
'journal.locations',
|
||||
"pending has at least one of ('CarrierJump', 'FSDJump', 'Location', 'Docked')"
|
||||
@@ -858,11 +875,11 @@ def worker() -> None: # noqa: CCR001 C901 # Cant be broken up currently
|
||||
'journal.locations', f'Overall POST data (elided) is:\n{json.dumps(data_elided, indent=2)}'
|
||||
)
|
||||
|
||||
r = this.session.post(TARGET_URL, data=data, timeout=_TIMEOUT)
|
||||
logger.trace_if('plugin.edsm.api', f'API response content: {r.content!r}')
|
||||
r.raise_for_status()
|
||||
response = this.session.post(TARGET_URL, data=data, timeout=_TIMEOUT)
|
||||
logger.trace_if('plugin.edsm.api', f'API response content: {response.content!r}')
|
||||
response.raise_for_status()
|
||||
|
||||
reply = r.json()
|
||||
reply = response.json()
|
||||
msg_num = reply['msgnum']
|
||||
msg = reply['msg']
|
||||
# 1xx = OK
|
||||
@@ -893,7 +910,7 @@ def worker() -> None: # noqa: CCR001 C901 # Cant be broken up currently
|
||||
# Update main window's system status
|
||||
this.lastlookup = r
|
||||
# calls update_status in main thread
|
||||
if not config.shutting_down:
|
||||
if not config.shutting_down and this.system_link is not None:
|
||||
this.system_link.event_generate('<<EDSMStatus>>', when="tail")
|
||||
|
||||
if r['msgnum'] // 100 != 1: # type: ignore
|
||||
@@ -996,18 +1013,19 @@ def update_status(event=None) -> None:
|
||||
# msgnum: 1xx = OK, 2xx = fatal error, 3xx = error, 4xx = ignorable errors.
|
||||
def edsm_notify_system(reply: Mapping[str, Any]) -> None:
|
||||
"""Update the image next to the system link."""
|
||||
if not reply:
|
||||
this.system_link['image'] = this._IMG_ERROR
|
||||
# LANG: EDSM Plugin - Error connecting to EDSM API
|
||||
plug.show_error(_("Error: Can't connect to EDSM"))
|
||||
if this.system_link is not None:
|
||||
if not reply:
|
||||
this.system_link['image'] = this._IMG_ERROR
|
||||
# LANG: EDSM Plugin - Error connecting to EDSM API
|
||||
plug.show_error(_("Error: Can't connect to EDSM"))
|
||||
|
||||
elif reply['msgnum'] // 100 not in (1, 4):
|
||||
this.system_link['image'] = this._IMG_ERROR
|
||||
# LANG: EDSM Plugin - Error message from EDSM API
|
||||
plug.show_error(_('Error: EDSM {MSG}').format(MSG=reply['msg']))
|
||||
elif reply['msgnum'] // 100 not in (1, 4):
|
||||
this.system_link['image'] = this._IMG_ERROR
|
||||
# LANG: EDSM Plugin - Error message from EDSM API
|
||||
plug.show_error(_('Error: EDSM {MSG}').format(MSG=reply['msg']))
|
||||
|
||||
elif reply.get('systemCreated'):
|
||||
this.system_link['image'] = this._IMG_NEW
|
||||
elif reply.get('systemCreated'):
|
||||
this.system_link['image'] = this._IMG_NEW
|
||||
|
||||
else:
|
||||
this.system_link['image'] = this._IMG_KNOWN
|
||||
else:
|
||||
this.system_link['image'] = this._IMG_KNOWN
|
||||
+51
-67
@@ -15,10 +15,9 @@
|
||||
# Thus you **MUST** check if any imports you add in this file are only
|
||||
# referenced in this file (or only in any other core plugin), and if so...
|
||||
#
|
||||
# YOU MUST ENSURE THAT PERTINENT ADJUSTMENTS ARE MADE IN `setup.py`
|
||||
# SO AS TO ENSURE THE FILES ARE ACTUALLY PRESENT IN AN END-USER
|
||||
# INSTALLATION ON WINDOWS.
|
||||
#
|
||||
# YOU MUST ENSURE THAT PERTINENT ADJUSTMENTS ARE MADE IN
|
||||
# `Build-exe-and-msi.py` SO AS TO ENSURE THE FILES ARE ACTUALLY PRESENT
|
||||
# IN AN END-USER INSTALLATION ON WINDOWS.
|
||||
#
|
||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
|
||||
@@ -31,6 +30,7 @@ from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from operator import itemgetter
|
||||
from threading import Lock, Thread
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, Any, Callable, Deque, Dict, List, Mapping, NamedTuple, Optional
|
||||
from typing import OrderedDict as OrderedDictT
|
||||
from typing import Sequence, Union, cast
|
||||
@@ -43,7 +43,7 @@ import myNotebook as nb # noqa: N813
|
||||
import plug
|
||||
import timeout_session
|
||||
from companion import CAPIData
|
||||
from config import applongname, appversion, config, debug_senders
|
||||
from config import applongname, appname, appversion, config, debug_senders
|
||||
from EDMCLogging import get_main_logger
|
||||
from monitor import monitor
|
||||
from ttkHyperlinkLabel import HyperlinkLabel
|
||||
@@ -119,7 +119,7 @@ class This:
|
||||
|
||||
# Main window clicks
|
||||
self.system_link: tk.Widget = None # type: ignore
|
||||
self.system: Optional[str] = None # type: ignore
|
||||
self.system_name: Optional[str] = None # type: ignore
|
||||
self.system_address: Optional[str] = None # type: ignore
|
||||
self.system_population: Optional[int] = None
|
||||
self.station_link: tk.Widget = None # type: ignore
|
||||
@@ -131,7 +131,7 @@ class This:
|
||||
self.log_button: nb.Checkbutton
|
||||
self.label: HyperlinkLabel
|
||||
self.apikey: nb.Entry
|
||||
self.apikey_label: HyperlinkLabel
|
||||
self.apikey_label: tk.Label
|
||||
|
||||
self.events: Dict[Credentials, Deque[Event]] = defaultdict(deque)
|
||||
self.event_lock: Lock = threading.Lock() # protects events, for use when rewriting events
|
||||
@@ -169,10 +169,12 @@ if DEBUG:
|
||||
def system_url(system_name: str) -> str:
|
||||
"""Get a URL for the current system."""
|
||||
if this.system_address:
|
||||
return requests.utils.requote_uri(f'https://inara.cz/galaxy-starsystem/?search={this.system_address}')
|
||||
return requests.utils.requote_uri(f'https://inara.cz/galaxy-starsystem/'
|
||||
f'?search={this.system_address}')
|
||||
|
||||
elif system_name:
|
||||
return requests.utils.requote_uri(f'https://inara.cz/galaxy-starsystem/?search={system_name}')
|
||||
return requests.utils.requote_uri(f'https://inara.cz/galaxy-starsystem/'
|
||||
f'?search={system_name}')
|
||||
|
||||
return ''
|
||||
|
||||
@@ -188,11 +190,13 @@ def station_url(system_name: str, station_name: str) -> str:
|
||||
:return: A URL to inara for the given system and station
|
||||
"""
|
||||
if system_name and station_name:
|
||||
return requests.utils.requote_uri(f'https://inara.cz/galaxy-station/?search={system_name}%20[{station_name}]')
|
||||
return requests.utils.requote_uri(f'https://inara.cz/galaxy-station/'
|
||||
f'?search={system_name}%20[{station_name}]')
|
||||
|
||||
# monitor state might think these are gone, but we don't yet
|
||||
if this.system and this.station:
|
||||
return requests.utils.requote_uri(f'https://inara.cz/galaxy-station/?search={this.system}%20[{this.station}]')
|
||||
if this.system_name and this.station:
|
||||
return requests.utils.requote_uri(f'https://inara.cz/galaxy-station/'
|
||||
f'?search={this.system_name}%20[{this.station}]')
|
||||
|
||||
if system_name:
|
||||
return system_url(system_name)
|
||||
@@ -218,8 +222,10 @@ def plugin_start3(plugin_dir: str) -> str:
|
||||
def plugin_app(parent: tk.Tk) -> None:
|
||||
"""Plugin UI setup Hook."""
|
||||
this.parent = parent
|
||||
this.system_link = parent.children['system'] # system label in main window
|
||||
this.station_link = parent.children['station'] # station label in main window
|
||||
# system label in main window
|
||||
this.system_link = parent.nametowidget(f".{appname.lower()}.system")
|
||||
# station label in main window
|
||||
this.station_link = parent.nametowidget(f".{appname.lower()}.station")
|
||||
this.system_link.bind_all('<<InaraLocation>>', update_location)
|
||||
this.system_link.bind_all('<<InaraShip>>', update_ship)
|
||||
|
||||
@@ -236,7 +242,7 @@ def plugin_stop() -> None:
|
||||
logger.debug('Done.')
|
||||
|
||||
|
||||
def plugin_prefs(parent: tk.Tk, cmdr: str, is_beta: bool) -> tk.Frame:
|
||||
def plugin_prefs(parent: ttk.Notebook, cmdr: str, is_beta: bool) -> tk.Frame:
|
||||
"""Plugin Preferences UI hook."""
|
||||
x_padding = 10
|
||||
x_button_padding = 12 # indent Checkbuttons and Radiobuttons
|
||||
@@ -369,6 +375,31 @@ def journal_entry( # noqa: C901, CCR001
|
||||
|
||||
:return: str - empty if no error, else error string.
|
||||
"""
|
||||
# This overall killswitch check is first in case, e.g. an EDMC bug is
|
||||
# causing users to spam Inara with 'URL provider' queries, and we want to
|
||||
# stop that.
|
||||
should_return: bool
|
||||
new_entry: Dict[str, Any] = {}
|
||||
|
||||
should_return, new_entry = killswitch.check_killswitch('plugins.inara.journal', entry, logger)
|
||||
if should_return:
|
||||
plug.show_error(_('Inara disabled. See Log.')) # LANG: INARA support disabled via killswitch
|
||||
logger.trace('returning due to killswitch match')
|
||||
return ''
|
||||
|
||||
# But then we update all the tracking copies before any other checks,
|
||||
# because they're relevant for URL providing even if *sending* isn't
|
||||
# appropriate.
|
||||
this.on_foot = state['OnFoot']
|
||||
event_name: str = entry['event']
|
||||
this.cmdr = cmdr
|
||||
this.FID = state['FID']
|
||||
this.multicrew = bool(state['Role'])
|
||||
this.system_name = state['SystemName']
|
||||
this.system_address = state['SystemAddress']
|
||||
this.station = state['StationName']
|
||||
this.station_marketid = state['MarketID']
|
||||
|
||||
if not monitor.is_live_galaxy():
|
||||
# Since Update 14 on 2022-11-29 Inara only accepts Live data.
|
||||
if (
|
||||
@@ -380,18 +411,11 @@ def journal_entry( # noqa: C901, CCR001
|
||||
):
|
||||
# LANG: The Inara API only accepts Live galaxy data, not Legacy galaxy data
|
||||
logger.info(_("Inara only accepts Live galaxy data"))
|
||||
# this.parent.children['status']['text'] =
|
||||
this.legacy_galaxy_last_notified = datetime.now(timezone.utc)
|
||||
return _("Inara only accepts Live galaxy data")
|
||||
return _("Inara only accepts Live galaxy data") # LANG: Inara - Only Live data
|
||||
|
||||
return ''
|
||||
|
||||
should_return, new_entry = killswitch.check_killswitch('plugins.inara.journal', entry, logger)
|
||||
if should_return:
|
||||
plug.show_error(_('Inara disabled. See Log.')) # LANG: INARA support disabled via killswitch
|
||||
logger.trace('returning due to killswitch match')
|
||||
return ''
|
||||
|
||||
should_return, new_entry = killswitch.check_killswitch(
|
||||
f'plugins.inara.journal.event.{entry["event"]}', new_entry, logger
|
||||
)
|
||||
@@ -401,12 +425,6 @@ def journal_entry( # noqa: C901, CCR001
|
||||
return ''
|
||||
|
||||
entry = new_entry
|
||||
this.on_foot = state['OnFoot']
|
||||
event_name: str = entry['event']
|
||||
this.cmdr = cmdr
|
||||
this.FID = state['FID']
|
||||
this.multicrew = bool(state['Role'])
|
||||
|
||||
if event_name == 'LoadGame' or this.newuser:
|
||||
# clear cached state
|
||||
if event_name == 'LoadGame':
|
||||
@@ -427,10 +445,6 @@ def journal_entry( # noqa: C901, CCR001
|
||||
this.loadout = None
|
||||
this.fleet = None
|
||||
this.shipswap = False
|
||||
this.system = None
|
||||
this.system_address = None
|
||||
this.station = None
|
||||
this.station_marketid = None
|
||||
|
||||
elif event_name in ('Resurrect', 'ShipyardBuy', 'ShipyardSell', 'SellShipOnRebuy'):
|
||||
# Events that mean a significant change in credits, so we should send credits after next "Update"
|
||||
@@ -439,35 +453,6 @@ def journal_entry( # noqa: C901, CCR001
|
||||
elif event_name in ('ShipyardNew', 'ShipyardSwap') or (event_name == 'Location' and entry['Docked']):
|
||||
this.suppress_docked = True
|
||||
|
||||
# Always update our system address even if we're not currently the provider for system or station, but dont update
|
||||
# on events that contain "future" data, such as FSDTarget
|
||||
if entry['event'] in ('Location', 'Docked', 'CarrierJump', 'FSDJump'):
|
||||
this.system_address = entry.get('SystemAddress') or this.system_address
|
||||
this.system = entry.get('StarSystem') or this.system
|
||||
|
||||
# We need pop == 0 to set the value so as to clear 'x' in systems with
|
||||
# no stations.
|
||||
pop: Optional[int] = entry.get('Population')
|
||||
if pop is not None:
|
||||
this.system_population = pop
|
||||
|
||||
this.station = entry.get('StationName', this.station)
|
||||
# on_foot station detection
|
||||
if entry['event'] == 'Location' and entry['BodyType'] == 'Station':
|
||||
this.station = entry['Body']
|
||||
|
||||
this.station_marketid = entry.get('MarketID', this.station_marketid) or this.station_marketid
|
||||
# We might pick up StationName in DockingRequested, make sure we clear it if leaving
|
||||
if event_name in ('Undocked', 'FSDJump', 'SupercruiseEntry'):
|
||||
this.station = None
|
||||
this.station_marketid = None
|
||||
|
||||
if entry['event'] == 'Embark' and not entry.get('OnStation'):
|
||||
# If we're embarking OnStation to a Taxi/Dropship we'll also get an
|
||||
# Undocked event.
|
||||
this.station = None
|
||||
this.station_marketid = None
|
||||
|
||||
if config.get_int('inara_out') and not is_beta and not this.multicrew and credentials(cmdr):
|
||||
current_credentials = Credentials(this.cmdr, this.FID, str(credentials(this.cmdr)))
|
||||
try:
|
||||
@@ -1154,7 +1139,7 @@ def journal_entry( # noqa: C901, CCR001
|
||||
|
||||
to_send_data: Optional[Dict[str, Any]] = {} # This is a glorified sentinel until lower down.
|
||||
# On Horizons, neither of these exist on TouchDown
|
||||
star_system_name = entry.get('StarSystem', this.system)
|
||||
star_system_name = entry.get('StarSystem', this.system_name)
|
||||
body_name = entry.get('Body', state['Body'] if state['BodyType'] == 'Planet' else None)
|
||||
|
||||
if star_system_name is None:
|
||||
@@ -1373,7 +1358,7 @@ def journal_entry( # noqa: C901, CCR001
|
||||
|
||||
# Only actually change URLs if we are current provider.
|
||||
if config.get_str('system_provider') == 'Inara':
|
||||
this.system_link['text'] = this.system
|
||||
this.system_link['text'] = this.system_name
|
||||
# Do *NOT* set 'url' here, as it's set to a function that will call
|
||||
# through correctly. We don't want a static string.
|
||||
this.system_link.update_idletasks()
|
||||
@@ -1403,14 +1388,14 @@ def cmdr_data(data: CAPIData, is_beta): # noqa: CCR001
|
||||
this.station_marketid = data['commander']['docked'] and data['lastStarport']['id']
|
||||
|
||||
# Only trust CAPI if these aren't yet set
|
||||
this.system = this.system if this.system else data['lastSystem']['name']
|
||||
this.system_name = this.system_name if this.system_name else data['lastSystem']['name']
|
||||
|
||||
if not this.station and data['commander']['docked']:
|
||||
this.station = data['lastStarport']['name']
|
||||
|
||||
# Override standard URL functions
|
||||
if config.get_str('system_provider') == 'Inara':
|
||||
this.system_link['text'] = this.system
|
||||
this.system_link['text'] = this.system_name
|
||||
# Do *NOT* set 'url' here, as it's set to a function that will call
|
||||
# through correctly. We don't want a static string.
|
||||
this.system_link.update_idletasks()
|
||||
@@ -1537,7 +1522,6 @@ def new_add_event(
|
||||
def clean_event_list(event_list: List[Event]) -> List[Event]:
|
||||
"""Check for killswitched events and remove or modify them as requested."""
|
||||
out = []
|
||||
|
||||
for e in event_list:
|
||||
bad, new_event = killswitch.check_killswitch(f'plugins.inara.worker.{e.name}', e.data, logger)
|
||||
if bad:
|
||||
|
||||
@@ -19,7 +19,6 @@ from EDMCLogging import edmclogger, get_main_logger
|
||||
from hotkey import hotkeymgr
|
||||
from l10n import Translations
|
||||
from monitor import monitor
|
||||
from myNotebook import Notebook
|
||||
from theme import theme
|
||||
from ttkHyperlinkLabel import HyperlinkLabel
|
||||
|
||||
@@ -182,7 +181,7 @@ if sys.platform == 'darwin':
|
||||
elif sys.platform == 'win32':
|
||||
import ctypes
|
||||
import winreg
|
||||
from ctypes.wintypes import HINSTANCE, HWND, LPARAM, LPCWSTR, LPVOID, LPWSTR, MAX_PATH, POINT, RECT, SIZE, UINT
|
||||
from ctypes.wintypes import HINSTANCE, HWND, LPCWSTR, LPWSTR, MAX_PATH, POINT, RECT, SIZE, UINT
|
||||
is_wine = False
|
||||
try:
|
||||
WINE_REGISTRY_KEY = r'HKEY_LOCAL_MACHINE\Software\Wine'
|
||||
@@ -190,22 +189,9 @@ elif sys.platform == 'win32':
|
||||
winreg.OpenKey(reg, WINE_REGISTRY_KEY)
|
||||
is_wine = True
|
||||
|
||||
except OSError:
|
||||
except OSError: # Assumed to be 'path not found', i.e. not-wine
|
||||
pass
|
||||
|
||||
# https://msdn.microsoft.com/en-us/library/windows/desktop/bb762115
|
||||
BIF_RETURNONLYFSDIRS = 0x00000001
|
||||
BIF_USENEWUI = 0x00000050
|
||||
BFFM_INITIALIZED = 1
|
||||
BFFM_SETSELECTION = 0x00000467
|
||||
BrowseCallbackProc = ctypes.WINFUNCTYPE(ctypes.c_int, HWND, ctypes.c_uint, LPARAM, LPARAM)
|
||||
|
||||
class BROWSEINFO(ctypes.Structure):
|
||||
"""Windows file browser fields."""
|
||||
|
||||
_fields_ = [("hwndOwner", HWND), ("pidlRoot", LPVOID), ("pszDisplayName", LPWSTR), ("lpszTitle", LPCWSTR),
|
||||
("ulFlags", UINT), ("lpfn", BrowseCallbackProc), ("lParam", LPCWSTR), ("iImage", ctypes.c_int)]
|
||||
|
||||
CalculatePopupWindowPosition = None
|
||||
if not is_wine:
|
||||
try:
|
||||
@@ -279,7 +265,7 @@ class PreferencesDialog(tk.Toplevel):
|
||||
frame = ttk.Frame(self)
|
||||
frame.grid(sticky=tk.NSEW)
|
||||
|
||||
notebook = nb.Notebook(frame)
|
||||
notebook: ttk.Notebook = nb.Notebook(frame)
|
||||
notebook.bind('<<NotebookTabChanged>>', self.tabchanged) # Recompute on tab change
|
||||
|
||||
self.PADX = 10
|
||||
@@ -333,7 +319,7 @@ class PreferencesDialog(tk.Toplevel):
|
||||
):
|
||||
self.geometry(f"+{position.left}+{position.top}")
|
||||
|
||||
def __setup_output_tab(self, root_notebook: nb.Notebook) -> None:
|
||||
def __setup_output_tab(self, root_notebook: ttk.Notebook) -> None:
|
||||
output_frame = nb.Frame(root_notebook)
|
||||
output_frame.columnconfigure(0, weight=1)
|
||||
|
||||
@@ -418,13 +404,13 @@ class PreferencesDialog(tk.Toplevel):
|
||||
# LANG: Label for 'Output' Settings/Preferences tab
|
||||
root_notebook.add(output_frame, text=_('Output')) # Tab heading in settings
|
||||
|
||||
def __setup_plugin_tabs(self, notebook: Notebook) -> None:
|
||||
def __setup_plugin_tabs(self, notebook: ttk.Notebook) -> None:
|
||||
for plugin in plug.PLUGINS:
|
||||
plugin_frame = plugin.get_prefs(notebook, monitor.cmdr, monitor.is_beta)
|
||||
if plugin_frame:
|
||||
notebook.add(plugin_frame, text=plugin.name)
|
||||
|
||||
def __setup_config_tab(self, notebook: Notebook) -> None: # noqa: CCR001
|
||||
def __setup_config_tab(self, notebook: ttk.Notebook) -> None: # noqa: CCR001
|
||||
config_frame = nb.Frame(notebook)
|
||||
config_frame.columnconfigure(1, weight=1)
|
||||
row = AutoInc(start=1)
|
||||
@@ -471,6 +457,25 @@ class PreferencesDialog(tk.Toplevel):
|
||||
state=tk.NORMAL if config.get_str('journaldir') else tk.DISABLED
|
||||
).grid(column=2, pady=self.PADY, sticky=tk.EW, row=row.get())
|
||||
|
||||
# CAPI settings
|
||||
self.capi_fleetcarrier = tk.BooleanVar(value=config.get_bool('capi_fleetcarrier'))
|
||||
|
||||
ttk.Separator(config_frame, orient=tk.HORIZONTAL).grid(
|
||||
columnspan=4, padx=self.PADX, pady=self.PADY*4, sticky=tk.EW, row=row.get()
|
||||
)
|
||||
|
||||
nb.Label(
|
||||
config_frame,
|
||||
text=_('CAPI Settings') # LANG: Settings > Configuration - Label for CAPI section
|
||||
).grid(padx=self.PADX, sticky=tk.W, row=row.get())
|
||||
|
||||
nb.Checkbutton(
|
||||
config_frame,
|
||||
# LANG: Configuration - Enable or disable the Fleet Carrier CAPI calls
|
||||
text=_('Enable Fleetcarrier CAPI Queries'),
|
||||
variable=self.capi_fleetcarrier
|
||||
).grid(columnspan=4, padx=self.PADX, pady=(5, 0), sticky=tk.W, row=row.get())
|
||||
|
||||
if sys.platform in ('darwin', 'win32'):
|
||||
ttk.Separator(config_frame, orient=tk.HORIZONTAL).grid(
|
||||
columnspan=4, padx=self.PADX, pady=self.PADY*4, sticky=tk.EW, row=row.get()
|
||||
@@ -675,7 +680,7 @@ class PreferencesDialog(tk.Toplevel):
|
||||
# LANG: Label for 'Configuration' tab in Settings
|
||||
notebook.add(config_frame, text=_('Configuration'))
|
||||
|
||||
def __setup_privacy_tab(self, notebook: Notebook) -> None:
|
||||
def __setup_privacy_tab(self, notebook: ttk.Notebook) -> None:
|
||||
frame = nb.Frame(notebook)
|
||||
self.hide_multicrew_captain = tk.BooleanVar(value=config.get_bool('hide_multicrew_captain', default=False))
|
||||
self.hide_private_group = tk.BooleanVar(value=config.get_bool('hide_private_group', default=False))
|
||||
@@ -697,7 +702,7 @@ class PreferencesDialog(tk.Toplevel):
|
||||
|
||||
notebook.add(frame, text=_('Privacy')) # LANG: Preferences privacy tab title
|
||||
|
||||
def __setup_appearance_tab(self, notebook: Notebook) -> None:
|
||||
def __setup_appearance_tab(self, notebook: ttk.Notebook) -> None:
|
||||
self.languages = Translations.available_names()
|
||||
# Appearance theme and language setting
|
||||
# LANG: The system default language choice in Settings > Appearance
|
||||
@@ -887,7 +892,7 @@ class PreferencesDialog(tk.Toplevel):
|
||||
# LANG: Label for Settings > Appearance tab
|
||||
notebook.add(appearance_frame, text=_('Appearance')) # Tab heading in settings
|
||||
|
||||
def __setup_plugin_tab(self, notebook: Notebook) -> None: # noqa: CCR001
|
||||
def __setup_plugin_tab(self, notebook: ttk.Notebook) -> None: # noqa: CCR001
|
||||
# Plugin settings and info
|
||||
plugins_frame = nb.Frame(notebook)
|
||||
plugins_frame.columnconfigure(0, weight=1)
|
||||
@@ -1026,42 +1031,13 @@ class PreferencesDialog(tk.Toplevel):
|
||||
:param title: Title of the window
|
||||
:param pathvar: the path to start the dialog on
|
||||
"""
|
||||
import locale
|
||||
|
||||
# If encoding isn't UTF-8 we can't use the tkinter dialog
|
||||
current_locale = locale.getlocale(locale.LC_CTYPE)
|
||||
directory = None
|
||||
if sys.platform == 'win32' and current_locale[1] not in ('utf8', 'UTF8', 'utf-8', 'UTF-8'):
|
||||
def browsecallback(hwnd, uMsg, lParam, lpData): # noqa: N803 # Windows API convention
|
||||
# set initial folder
|
||||
if uMsg == BFFM_INITIALIZED and lpData:
|
||||
ctypes.windll.user32.SendMessageW(hwnd, BFFM_SETSELECTION, 1, lpData)
|
||||
return 0
|
||||
|
||||
browseInfo = BROWSEINFO() # noqa: N806 # Windows convention
|
||||
browseInfo.lpszTitle = title
|
||||
browseInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI
|
||||
browseInfo.lpfn = BrowseCallbackProc(browsecallback)
|
||||
browseInfo.lParam = pathvar.get().startswith('~') and join(config.home_path,
|
||||
pathvar.get()[2:]) or pathvar.get()
|
||||
ctypes.windll.ole32.CoInitialize(None)
|
||||
pidl = ctypes.windll.shell32.SHBrowseForFolderW(ctypes.byref(browseInfo))
|
||||
if pidl:
|
||||
path = ctypes.create_unicode_buffer(MAX_PATH)
|
||||
ctypes.windll.shell32.SHGetPathFromIDListW(pidl, path)
|
||||
ctypes.windll.ole32.CoTaskMemFree(pidl)
|
||||
directory = path.value
|
||||
else:
|
||||
directory = None
|
||||
|
||||
else:
|
||||
import tkinter.filedialog
|
||||
directory = tkinter.filedialog.askdirectory(
|
||||
parent=self,
|
||||
initialdir=expanduser(pathvar.get()),
|
||||
title=title,
|
||||
mustexist=tk.TRUE
|
||||
)
|
||||
import tkinter.filedialog
|
||||
directory = tkinter.filedialog.askdirectory(
|
||||
parent=self,
|
||||
initialdir=expanduser(pathvar.get()),
|
||||
title=title,
|
||||
mustexist=tk.TRUE
|
||||
)
|
||||
|
||||
if directory:
|
||||
pathvar.set(directory)
|
||||
@@ -1188,8 +1164,8 @@ class PreferencesDialog(tk.Toplevel):
|
||||
:return: "break" as a literal, to halt processing
|
||||
"""
|
||||
good = hotkeymgr.fromevent(event)
|
||||
if good:
|
||||
(hotkey_code, hotkey_mods) = good
|
||||
if good and isinstance(good, tuple):
|
||||
hotkey_code, hotkey_mods = good
|
||||
event.widget.delete(0, tk.END)
|
||||
event.widget.insert(0, hotkeymgr.display(hotkey_code, hotkey_mods))
|
||||
if hotkey_code:
|
||||
@@ -1245,6 +1221,8 @@ class PreferencesDialog(tk.Toplevel):
|
||||
else:
|
||||
config.set('journaldir', logdir)
|
||||
|
||||
config.set('capi_fleetcarrier', self.capi_fleetcarrier.get())
|
||||
|
||||
if sys.platform in ('darwin', 'win32'):
|
||||
config.set('hotkey_code', self.hotkey_code)
|
||||
config.set('hotkey_mods', self.hotkey_mods)
|
||||
|
||||
+36
-7
@@ -106,12 +106,12 @@ if sys.platform == 'darwin' and getattr(sys, 'frozen', False): # noqa: C901 # i
|
||||
|
||||
def handleEvent_withReplyEvent_(self, event, replyEvent) -> None: # noqa: N802 N803 # Required to override
|
||||
"""Actual event handling from NSAppleEventManager."""
|
||||
protocolhandler.lasturl = urllib.parse.unquote( # noqa: F821: type: ignore # Its going to be a DPH in
|
||||
protocolhandler.lasturl = urllib.parse.unquote( # noqa: F821: type: ignore # It's going to be a DPH in
|
||||
# this code
|
||||
event.paramDescriptorForKeyword_(keyDirectObject).stringValue()
|
||||
).strip()
|
||||
|
||||
protocolhandler.master.after(DarwinProtocolHandler.POLL, protocolhandler.poll) # noqa: F821: type: ignore
|
||||
protocolhandler.master.after(DarwinProtocolHandler.POLL, protocolhandler.poll) # noqa: F821 # type: ignore
|
||||
|
||||
|
||||
elif (config.auth_force_edmc_protocol
|
||||
@@ -121,12 +121,16 @@ elif (config.auth_force_edmc_protocol
|
||||
and not is_wine
|
||||
and not config.auth_force_localserver
|
||||
)):
|
||||
# This could be false if you use auth_force_edmc_protocol, but then you get to keep the pieces
|
||||
assert sys.platform == 'win32'
|
||||
# spell-checker: words HBRUSH HICON WPARAM wstring WNDCLASS HMENU HGLOBAL
|
||||
from ctypes import windll # type: ignore
|
||||
from ctypes import POINTER, WINFUNCTYPE, Structure, byref, c_long, c_void_p, create_unicode_buffer, wstring_at
|
||||
from ctypes import ( # type: ignore
|
||||
POINTER, WINFUNCTYPE, Structure, byref, c_long, c_void_p, create_unicode_buffer, wstring_at
|
||||
)
|
||||
from ctypes.wintypes import (
|
||||
ATOM, BOOL, DWORD, HBRUSH, HGLOBAL, HICON, HINSTANCE, HMENU, HWND, INT, LPARAM, LPCWSTR, LPVOID, LPWSTR, MSG,
|
||||
UINT, WPARAM
|
||||
ATOM, BOOL, DWORD, HBRUSH, HGLOBAL, HICON, HINSTANCE, HMENU, HWND, INT, LPARAM, LPCWSTR, LPMSG, LPVOID, LPWSTR,
|
||||
MSG, UINT, WPARAM
|
||||
)
|
||||
|
||||
class WNDCLASS(Structure):
|
||||
@@ -157,11 +161,25 @@ elif (config.auth_force_edmc_protocol
|
||||
CreateWindowExW.restype = HWND
|
||||
RegisterClassW = windll.user32.RegisterClassW
|
||||
RegisterClassW.argtypes = [POINTER(WNDCLASS)]
|
||||
DefWindowProcW = windll.user32.DefWindowProcW
|
||||
# DefWindowProcW
|
||||
# Ref: <https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowprocw>
|
||||
# LRESULT DefWindowProcW([in] HWND hWnd,[in] UINT Msg,[in] WPARAM wParam,[in] LPARAM lParam);
|
||||
# As per example at <https://docs.python.org/3/library/ctypes.html#ctypes.WINFUNCTYPE>
|
||||
|
||||
prototype = WINFUNCTYPE(c_long, HWND, UINT, WPARAM, LPARAM)
|
||||
paramflags = (1, "hWnd"), (1, "Msg"), (1, "wParam"), (1, "lParam")
|
||||
DefWindowProcW = prototype(("DefWindowProcW", windll.user32), paramflags)
|
||||
|
||||
GetParent = windll.user32.GetParent
|
||||
SetForegroundWindow = windll.user32.SetForegroundWindow
|
||||
|
||||
GetMessageW = windll.user32.GetMessageW
|
||||
# <https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessagew>
|
||||
# NB: Despite 'BOOL' return type, it *can* be >0, 0 or -1, so is actually
|
||||
# c_long
|
||||
prototype = WINFUNCTYPE(c_long, LPMSG, HWND, UINT, UINT)
|
||||
paramflags = (1, "lpMsg"), (1, "hWnd"), (1, "wMsgFilterMin"), (1, "wMsgFilterMax")
|
||||
GetMessageW = prototype(("GetMessageW", windll.user32), paramflags)
|
||||
|
||||
TranslateMessage = windll.user32.TranslateMessage
|
||||
DispatchMessageW = windll.user32.DispatchMessageW
|
||||
PostThreadMessageW = windll.user32.PostThreadMessageW
|
||||
@@ -303,6 +321,17 @@ elif (config.auth_force_edmc_protocol
|
||||
|
||||
msg = MSG()
|
||||
# Calls GetMessageW: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessagew
|
||||
# Something is off with the return from this, meaning you'll see:
|
||||
# Exception ignored on converting result of ctypes callback function: <function WndProc
|
||||
# at 0x000001F5B8738FE0>
|
||||
# Traceback (most recent call last):
|
||||
# File "C:\Users\Athan\Documents\Devel\EDMarketConnector\protocol.py", line 323, in worker
|
||||
# while int(GetMessageW(byref(msg), None, 0, 0)) != 0:
|
||||
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
# TypeError: 'c_long' object cannot be interpreted as an integer
|
||||
#
|
||||
# But it does actually work. Either getting a non-0 value and
|
||||
# entering the loop, or getting 0 and exiting it.
|
||||
while GetMessageW(byref(msg), None, 0, 0) != 0:
|
||||
logger.trace_if('frontier-auth.windows', f'DDE message of type: {msg.message}')
|
||||
if msg.message == WM_DDE_EXECUTE:
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ addopts = "--cov . --cov plugins --cov-report=term-missing --no-cov-on-fail"
|
||||
# --cov-fail-under 80"
|
||||
|
||||
[tool.coverage.run]
|
||||
omit = [ "tests/*", "venv/*", "dist.win32/*" ]
|
||||
omit = [ "tests/*", "venv/*", ".venv/*", "dist.win32/*" ]
|
||||
plugins = [ "coverage_conditional_plugin" ]
|
||||
|
||||
[tool.coverage.coverage_conditional_plugin.rules]
|
||||
|
||||
+13
-9
@@ -5,7 +5,7 @@ wheel
|
||||
# We can't rely on just picking this up from either the base (not venv),
|
||||
# or venv-init-time version. Specify here so that dependabot will prod us
|
||||
# about new versions.
|
||||
setuptools==65.6.3
|
||||
setuptools==66.0.0
|
||||
|
||||
# Static analysis tools
|
||||
flake8==6.0.0
|
||||
@@ -13,20 +13,24 @@ flake8-annotations-coverage==0.0.6
|
||||
flake8-cognitive-complexity==0.1.0
|
||||
flake8-comprehensions==3.10.1
|
||||
flake8-docstrings==1.6.0
|
||||
isort==5.11.1
|
||||
flake8-isort==5.0.3
|
||||
isort==5.11.4
|
||||
flake8-isort==6.0.0
|
||||
flake8-json==21.7.0
|
||||
flake8-noqa==1.3.0
|
||||
flake8-polyfill==1.0.2
|
||||
flake8-use-fstring==1.4
|
||||
|
||||
mypy==0.991
|
||||
pep8-naming==0.13.2
|
||||
pep8-naming==0.13.3
|
||||
safety==2.3.5
|
||||
types-requests==2.28.11.5
|
||||
types-requests==2.28.11.7
|
||||
types-pkg-resources==0.1.3
|
||||
|
||||
# Code formatting tools
|
||||
autopep8==2.0.0
|
||||
autopep8==2.0.1
|
||||
|
||||
# Git pre-commit checking
|
||||
pre-commit==2.21.0
|
||||
|
||||
# HTML changelogs
|
||||
grip==4.6.1
|
||||
@@ -40,10 +44,10 @@ lxml==4.9.2
|
||||
py2exe==0.13.0.0; sys_platform == 'win32'
|
||||
|
||||
# Testing
|
||||
pytest==7.2.0
|
||||
pytest==7.2.1
|
||||
pytest-cov==4.0.0 # Pytest code coverage support
|
||||
coverage[toml]==6.5.0 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs
|
||||
coverage-conditional-plugin==0.7.0
|
||||
coverage[toml]==7.0.5 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs
|
||||
coverage-conditional-plugin==0.8.0
|
||||
# For manipulating folder permissions and the like.
|
||||
pywin32==305; sys_platform == 'win32'
|
||||
|
||||
|
||||
+5
-2
@@ -1,6 +1,9 @@
|
||||
certifi==2022.12.7
|
||||
requests==2.28.1
|
||||
watchdog==2.2.0
|
||||
requests==2.28.2
|
||||
# requests depends on this now ?
|
||||
charset-normalizer==2.1.1
|
||||
|
||||
watchdog==2.2.1
|
||||
# Commented out because this doesn't package well with py2exe
|
||||
infi.systray==0.1.12; sys_platform == 'win32'
|
||||
# argh==0.26.2 watchdog dep
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# NB: EDMC_PATH is replaced with the correct value by the
|
||||
# scripts/linux-setup.sh script. So, no, there's no missing '$' here.
|
||||
cd EDMC_PATH
|
||||
python3 EDMarketConnector.py
|
||||
@@ -139,7 +139,7 @@ def scan_file(path: pathlib.Path) -> list[ast.Call]:
|
||||
return out
|
||||
|
||||
|
||||
def scan_directory(path: pathlib.Path, skip: list[pathlib.Path] = None) -> dict[pathlib.Path, list[ast.Call]]:
|
||||
def scan_directory(path: pathlib.Path, skip: list[pathlib.Path] | None = None) -> dict[pathlib.Path, list[ast.Call]]:
|
||||
"""
|
||||
Scan a directory for expected callsites.
|
||||
|
||||
@@ -293,7 +293,7 @@ def generate_lang_template(data: dict[pathlib.Path, list[ast.Call]]) -> str:
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--directory', help='Directory to search from', default='.')
|
||||
parser.add_argument('--ignore', action='append', help='directories to ignore', default=['venv', '.git'])
|
||||
parser.add_argument('--ignore', action='append', help='directories to ignore', default=['venv', '.venv', '.git'])
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument('--json', action='store_true', help='JSON output')
|
||||
group.add_argument('--lang', help='en.template "strings" output to specified file, "-" for stdout')
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Set up necessary support files to make running EDMarketConnect streamlined
|
||||
# on Linux.
|
||||
#
|
||||
|
||||
###########################################################################
|
||||
# Shell script launcher
|
||||
#
|
||||
# This needs to be in an appropriate component of $PATH so that the
|
||||
# reference in the .desktop file will work.
|
||||
###########################################################################
|
||||
#######################################################
|
||||
# Determine where edmarketconnector.sh needs to go
|
||||
#######################################################
|
||||
# Really we need this to be "${HOME}/bin", so check that is in $PATH
|
||||
if [[ ":$PATH:" != *":$HOME/bin:"* ]];
|
||||
then
|
||||
echo "You need to have '${HOME}/bin' in your PATH"
|
||||
echo "Please fix this (might require relogging) and try again"
|
||||
exit 1
|
||||
fi
|
||||
EDMC_BIN_PATH="${HOME}/bin"
|
||||
if [ ! -d "${EDMC_BIN_PATH}" ];
|
||||
then
|
||||
echo "'${EDMC_BIN_PATH}' must exist and be a directory!"
|
||||
exit 2
|
||||
fi
|
||||
#######################################################
|
||||
|
||||
#######################################################
|
||||
# Determine where the source is located
|
||||
#######################################################
|
||||
# We know where this script is situated within an unzip/git clone of
|
||||
# the source code, so set EDMC_PATH based on that.
|
||||
# This is in `scripts/` of the source, so one directory up
|
||||
EDMC_PATH="$(dirname $0)/.."
|
||||
# And we need the *full* absolute path
|
||||
EDMC_PATH="$(realpath ${EDMC_PATH})"
|
||||
echo "EDMC_PATH = ${EDMC_PATH}"
|
||||
#######################################################
|
||||
|
||||
|
||||
#######################################################
|
||||
# Copy an edited version of edmarketconnector.sh into place
|
||||
#######################################################
|
||||
echo "Copying launcher shell script into place..."
|
||||
sed -e "s#EDMC_PATH#${EDMC_PATH}#g;" \
|
||||
< "${EDMC_PATH}/scripts/edmarketconnector.sh" \
|
||||
> "${EDMC_BIN_PATH}/edmarketconnector"
|
||||
#######################################################
|
||||
###########################################################################
|
||||
|
||||
###########################################################################
|
||||
# Desktop file
|
||||
#
|
||||
# This needs to be in a path where any XDG-compliant environment will be
|
||||
# able to find it.
|
||||
###########################################################################
|
||||
echo "Copying .desktop file into place ..."
|
||||
install -d -m700 "${HOME}/.local/share/applications"
|
||||
install -t "${HOME}/.local/share/applications" "${EDMC_PATH}/io.edcd.EDMarketConnector.desktop"
|
||||
###########################################################################
|
||||
|
||||
###########################################################################
|
||||
# Icon file
|
||||
#
|
||||
# This needs to be in a path where any XDG-compliant environment will be
|
||||
# able to find it.
|
||||
###########################################################################
|
||||
echo "Copying icon file into place..."
|
||||
install -d -m700 "${HOME}/.local/share/icons/hicolor/512x512/apps"
|
||||
install -t "${HOME}/.local/share/icons/hicolor/512x512/apps" "${EDMC_PATH}/io.edcd.EDMarketConnector.png"
|
||||
###########################################################################
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Run mypy checks against all the relevant files
|
||||
|
||||
# We assume that all `.py` files in git should be checked, and *only* those.
|
||||
mypy $@ $(git ls-tree --full-tree -r --name-only HEAD | grep -E '\.py$')
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
"""Find the reverse dependencies of a package according to pip."""
|
||||
import sys
|
||||
|
||||
import pkg_resources
|
||||
|
||||
|
||||
def find_reverse_deps(package_name: str):
|
||||
"""
|
||||
Find the packages that depend on the named one.
|
||||
|
||||
:param package_name: Target package.
|
||||
:return: List of packages that depend on this one.
|
||||
"""
|
||||
return [
|
||||
pkg.project_name for pkg in pkg_resources.WorkingSet()
|
||||
if package_name in {req.project_name for req in pkg.requires()}
|
||||
]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(find_reverse_deps(sys.argv[1]))
|
||||
@@ -5,7 +5,7 @@ import sys
|
||||
import tkinter
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, Any, AnyStr, Callable, Dict, List, NamedTuple, Optional, Sequence, cast
|
||||
from typing import TYPE_CHECKING, Any, AnyStr, Callable, NamedTuple, Sequence, cast
|
||||
|
||||
import companion
|
||||
import EDMCLogging
|
||||
@@ -45,7 +45,7 @@ RANK_LINES_END = 9
|
||||
POWERPLAY_LINES_START = 9
|
||||
|
||||
|
||||
def status(data: Dict[str, Any]) -> List[List[str]]:
|
||||
def status(data: dict[str, Any]) -> list[list[str]]:
|
||||
"""
|
||||
Get the current status of the cmdr referred to by data.
|
||||
|
||||
@@ -211,7 +211,7 @@ def status(data: Dict[str, Any]) -> List[List[str]]:
|
||||
return res
|
||||
|
||||
|
||||
def export_status(data: Dict[str, Any], filename: AnyStr) -> None:
|
||||
def export_status(data: dict[str, Any], filename: AnyStr) -> None:
|
||||
"""
|
||||
Export status data to a CSV file.
|
||||
|
||||
@@ -236,21 +236,21 @@ class ShipRet(NamedTuple):
|
||||
value: str
|
||||
|
||||
|
||||
def ships(companion_data: Dict[str, Any]) -> List[ShipRet]:
|
||||
def ships(companion_data: dict[str, Any]) -> list[ShipRet]:
|
||||
"""
|
||||
Return a list of 5 tuples of ship information.
|
||||
|
||||
:param data: [description]
|
||||
:return: A 5 tuple of strings containing: Ship ID, Ship Type Name (internal), Ship Name, System, Station, and Value
|
||||
"""
|
||||
ships: List[Dict[str, Any]] = companion.listify(cast(list, companion_data.get('ships')))
|
||||
ships: list[dict[str, Any]] = companion.listify(cast(list, companion_data.get('ships')))
|
||||
current = companion_data['commander'].get('currentShipId')
|
||||
|
||||
if isinstance(current, int) and current < len(ships) and ships[current]:
|
||||
ships.insert(0, ships.pop(current)) # Put current ship first
|
||||
|
||||
if not companion_data['commander'].get('docked'):
|
||||
out: List[ShipRet] = []
|
||||
out: list[ShipRet] = []
|
||||
# Set current system, not last docked
|
||||
out.append(ShipRet(
|
||||
id=str(ships[0]['id']),
|
||||
@@ -285,7 +285,7 @@ def ships(companion_data: Dict[str, Any]) -> List[ShipRet]:
|
||||
]
|
||||
|
||||
|
||||
def export_ships(companion_data: Dict[str, Any], filename: AnyStr) -> None:
|
||||
def export_ships(companion_data: dict[str, Any], filename: AnyStr) -> None:
|
||||
"""
|
||||
Export the current ships to a CSV file.
|
||||
|
||||
@@ -335,8 +335,6 @@ class StatsDialog():
|
||||
elif (
|
||||
not capi_data.get('lastSystem')
|
||||
or not capi_data['lastSystem'].get('name', '').strip()
|
||||
or not capi_data.get('lastStarport')
|
||||
or not capi_data['lastStarport'].get('name', '').strip()
|
||||
):
|
||||
# Shouldn't happen
|
||||
# LANG: Unknown location
|
||||
@@ -358,7 +356,7 @@ class StatsDialog():
|
||||
class StatsResults(tk.Toplevel):
|
||||
"""Status window."""
|
||||
|
||||
def __init__(self, parent: tk.Tk, data: Dict[str, Any]) -> None:
|
||||
def __init__(self, parent: tk.Tk, data: dict[str, Any]) -> None:
|
||||
tk.Toplevel.__init__(self, parent)
|
||||
|
||||
self.parent = parent
|
||||
@@ -442,7 +440,9 @@ class StatsResults(tk.Toplevel):
|
||||
):
|
||||
self.geometry(f"+{position.left}+{position.top}")
|
||||
|
||||
def addpage(self, parent, header: List[str] = None, align: Optional[str] = None) -> tk.Frame:
|
||||
def addpage(
|
||||
self, parent, header: list[str] | None = None, align: str | None = None
|
||||
) -> ttk.Frame:
|
||||
"""
|
||||
Add a page to the StatsResults screen.
|
||||
|
||||
@@ -462,7 +462,7 @@ class StatsResults(tk.Toplevel):
|
||||
|
||||
return page
|
||||
|
||||
def addpageheader(self, parent: tk.Frame, header: Sequence[str], align: Optional[str] = None) -> None:
|
||||
def addpageheader(self, parent: ttk.Frame, header: Sequence[str], align: str | None = None) -> None:
|
||||
"""
|
||||
Add the column headers to the page, followed by a separator.
|
||||
|
||||
@@ -478,7 +478,7 @@ class StatsResults(tk.Toplevel):
|
||||
self.addpagerow(parent, [''])
|
||||
|
||||
def addpagerow(
|
||||
self, parent: tk.Frame, content: Sequence[str], align: Optional[str] = None, with_copy: bool = False
|
||||
self, parent: ttk.Frame, content: Sequence[str], align: str | None = None, with_copy: bool = False
|
||||
):
|
||||
"""
|
||||
Add a single row to parent.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# type: ignore
|
||||
import numbers
|
||||
import sys
|
||||
import warnings
|
||||
@@ -138,7 +139,7 @@ class OldConfig():
|
||||
self.identifier = f'uk.org.marginal.{appname.lower()}'
|
||||
NSBundle.mainBundle().infoDictionary()['CFBundleIdentifier'] = self.identifier
|
||||
|
||||
self.default_journal_dir = join(
|
||||
self.default_journal_dir: str | None = join(
|
||||
NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0],
|
||||
'Frontier Developments',
|
||||
'Elite Dangerous'
|
||||
@@ -222,13 +223,13 @@ class OldConfig():
|
||||
|
||||
journaldir = known_folder_path(FOLDERID_SavedGames)
|
||||
if journaldir:
|
||||
self.default_journal_dir = join(journaldir, 'Frontier Developments', 'Elite Dangerous')
|
||||
self.default_journal_dir: str | None = join(journaldir, 'Frontier Developments', 'Elite Dangerous')
|
||||
|
||||
else:
|
||||
self.default_journal_dir = None
|
||||
|
||||
self.identifier = applongname
|
||||
self.hkey = HKEY()
|
||||
self.hkey: ctypes.c_void_p | None = HKEY()
|
||||
disposition = DWORD()
|
||||
if RegCreateKeyEx(
|
||||
HKEY_CURRENT_USER,
|
||||
@@ -376,7 +377,7 @@ class OldConfig():
|
||||
mkdir(self.plugin_dir)
|
||||
|
||||
self.internal_plugin_dir = join(dirname(__file__), 'plugins')
|
||||
self.default_journal_dir = None
|
||||
self.default_journal_dir: str | None = None
|
||||
self.home = expanduser('~')
|
||||
self.respath = dirname(__file__)
|
||||
self.identifier = f'uk.org.marginal.{appname.lower()}'
|
||||
|
||||
@@ -88,7 +88,7 @@ class TestNewConfig:
|
||||
if sys.platform != 'linux':
|
||||
return
|
||||
|
||||
from config.linux import LinuxConfig
|
||||
from config.linux import LinuxConfig # type: ignore
|
||||
|
||||
if isinstance(config, LinuxConfig) and config.config is not None:
|
||||
config.config.read(config.filename)
|
||||
@@ -179,7 +179,7 @@ class TestOldNewConfig:
|
||||
if sys.platform != 'linux':
|
||||
return
|
||||
|
||||
from config.linux import LinuxConfig
|
||||
from config.linux import LinuxConfig # type: ignore
|
||||
if isinstance(config, LinuxConfig) and config.config is not None:
|
||||
config.config.read(config.filename)
|
||||
|
||||
|
||||
@@ -3,11 +3,10 @@ import multiprocessing as mp
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
from typing import Generator
|
||||
|
||||
import pytest
|
||||
# Import as other names else they get picked up when used as fixtures
|
||||
from _pytest import monkeypatch as _pytest_monkeypatch
|
||||
from _pytest import tmpdir as _pytest_tmpdir
|
||||
from pytest import MonkeyPatch, TempdirFactory, TempPathFactory
|
||||
|
||||
from config import config
|
||||
from journal_lock import JournalLock, JournalLockResult
|
||||
@@ -117,11 +116,11 @@ class TestJournalLock:
|
||||
|
||||
@pytest.fixture
|
||||
def mock_journaldir(
|
||||
self, monkeypatch: _pytest_monkeypatch,
|
||||
tmp_path_factory: _pytest_tmpdir.TempPathFactory
|
||||
) -> _pytest_tmpdir.TempPathFactory:
|
||||
self, monkeypatch: MonkeyPatch,
|
||||
tmp_path_factory: TempdirFactory
|
||||
) -> Generator:
|
||||
"""Fixture for mocking config.get_str('journaldir')."""
|
||||
def get_str(key: str, *, default: str = None) -> str:
|
||||
def get_str(key: str, *, default: str | None = None) -> str:
|
||||
"""Mock config.*Config get_str to provide fake journaldir."""
|
||||
if key == 'journaldir':
|
||||
return str(tmp_path_factory.getbasetemp())
|
||||
@@ -136,11 +135,11 @@ class TestJournalLock:
|
||||
@pytest.fixture
|
||||
def mock_journaldir_changing(
|
||||
self,
|
||||
monkeypatch: _pytest_monkeypatch,
|
||||
tmp_path_factory: _pytest_tmpdir.TempPathFactory
|
||||
) -> _pytest_tmpdir.TempPathFactory:
|
||||
monkeypatch: MonkeyPatch,
|
||||
tmp_path_factory: TempdirFactory
|
||||
) -> Generator:
|
||||
"""Fixture for mocking config.get_str('journaldir')."""
|
||||
def get_str(key: str, *, default: str = None) -> str:
|
||||
def get_str(key: str, *, default: str | None = None) -> str:
|
||||
"""Mock config.*Config get_str to provide fake journaldir."""
|
||||
if key == 'journaldir':
|
||||
return tmp_path_factory.mktemp("changing")
|
||||
@@ -154,7 +153,7 @@ class TestJournalLock:
|
||||
|
||||
###########################################################################
|
||||
# Tests against JournalLock.__init__()
|
||||
def test_journal_lock_init(self, mock_journaldir: _pytest_tmpdir.TempPathFactory):
|
||||
def test_journal_lock_init(self, mock_journaldir: TempPathFactory):
|
||||
"""Test JournalLock instantiation."""
|
||||
print(f'{type(mock_journaldir)=}')
|
||||
tmpdir = str(mock_journaldir.getbasetemp())
|
||||
@@ -176,14 +175,14 @@ class TestJournalLock:
|
||||
jlock.set_path_from_journaldir()
|
||||
assert jlock.journal_dir_path is None
|
||||
|
||||
def test_path_from_journaldir_with_tmpdir(self, mock_journaldir: _pytest_tmpdir.TempPathFactory):
|
||||
def test_path_from_journaldir_with_tmpdir(self, mock_journaldir: TempPathFactory):
|
||||
"""Test JournalLock.set_path_from_journaldir() with tmpdir."""
|
||||
tmpdir = mock_journaldir
|
||||
|
||||
jlock = JournalLock()
|
||||
|
||||
# Check that an actual journaldir is handled correctly.
|
||||
jlock.journal_dir = tmpdir
|
||||
jlock.journal_dir = str(tmpdir)
|
||||
jlock.set_path_from_journaldir()
|
||||
assert isinstance(jlock.journal_dir_path, pathlib.Path)
|
||||
|
||||
@@ -200,7 +199,7 @@ class TestJournalLock:
|
||||
locked = jlock.obtain_lock()
|
||||
assert locked == JournalLockResult.JOURNALDIR_IS_NONE
|
||||
|
||||
def test_obtain_lock_with_tmpdir(self, mock_journaldir: _pytest_tmpdir.TempPathFactory):
|
||||
def test_obtain_lock_with_tmpdir(self, mock_journaldir: TempPathFactory):
|
||||
"""Test JournalLock.obtain_lock() with tmpdir."""
|
||||
jlock = JournalLock()
|
||||
|
||||
@@ -213,7 +212,7 @@ class TestJournalLock:
|
||||
assert jlock.release_lock()
|
||||
os.unlink(str(jlock.journal_dir_lockfile_name))
|
||||
|
||||
def test_obtain_lock_with_tmpdir_ro(self, mock_journaldir: _pytest_tmpdir.TempPathFactory):
|
||||
def test_obtain_lock_with_tmpdir_ro(self, mock_journaldir: TempPathFactory):
|
||||
"""Test JournalLock.obtain_lock() with read-only tmpdir."""
|
||||
tmpdir = str(mock_journaldir.getbasetemp())
|
||||
print(f'{tmpdir=}')
|
||||
@@ -280,7 +279,7 @@ class TestJournalLock:
|
||||
|
||||
assert locked == JournalLockResult.JOURNALDIR_READONLY
|
||||
|
||||
def test_obtain_lock_already_locked(self, mock_journaldir: _pytest_tmpdir.TempPathFactory):
|
||||
def test_obtain_lock_already_locked(self, mock_journaldir: TempPathFactory):
|
||||
"""Test JournalLock.obtain_lock() with tmpdir."""
|
||||
continue_q: mp.Queue = mp.Queue()
|
||||
exit_q: mp.Queue = mp.Queue()
|
||||
@@ -312,7 +311,7 @@ class TestJournalLock:
|
||||
|
||||
###########################################################################
|
||||
# Tests against JournalLock.release_lock()
|
||||
def test_release_lock(self, mock_journaldir: _pytest_tmpdir.TempPathFactory):
|
||||
def test_release_lock(self, mock_journaldir: TempPathFactory):
|
||||
"""Test JournalLock.release_lock()."""
|
||||
# First actually obtain the lock, and check it worked
|
||||
jlock = JournalLock()
|
||||
@@ -330,12 +329,12 @@ class TestJournalLock:
|
||||
# Cleanup, to avoid side-effect on other tests
|
||||
os.unlink(str(jlock.journal_dir_lockfile_name))
|
||||
|
||||
def test_release_lock_not_locked(self, mock_journaldir: _pytest_tmpdir.TempPathFactory):
|
||||
def test_release_lock_not_locked(self, mock_journaldir: TempPathFactory):
|
||||
"""Test JournalLock.release_lock() when not locked."""
|
||||
jlock = JournalLock()
|
||||
assert jlock.release_lock()
|
||||
|
||||
def test_release_lock_lie_locked(self, mock_journaldir: _pytest_tmpdir.TempPathFactory):
|
||||
def test_release_lock_lie_locked(self, mock_journaldir: TempPathFactory):
|
||||
"""Test JournalLock.release_lock() when not locked, but lie we are."""
|
||||
jlock = JournalLock()
|
||||
jlock.locked = True
|
||||
@@ -345,7 +344,7 @@ class TestJournalLock:
|
||||
# Tests against JournalLock.update_lock()
|
||||
def test_update_lock(
|
||||
self,
|
||||
mock_journaldir_changing: _pytest_tmpdir.TempPathFactory):
|
||||
mock_journaldir_changing: TempPathFactory):
|
||||
"""
|
||||
Test JournalLock.update_lock().
|
||||
|
||||
@@ -373,7 +372,7 @@ class TestJournalLock:
|
||||
# And the old_journaldir's lockfile too
|
||||
os.unlink(str(old_journaldir_lockfile_name))
|
||||
|
||||
def test_update_lock_same(self, mock_journaldir: _pytest_tmpdir.TempPathFactory):
|
||||
def test_update_lock_same(self, mock_journaldir: TempPathFactory):
|
||||
"""
|
||||
Test JournalLock.update_lock().
|
||||
|
||||
|
||||
@@ -131,14 +131,14 @@ class _Theme(object):
|
||||
THEME_TRANSPARENT = 2
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.active = None # Starts out with no theme
|
||||
self.active: int | None = None # Starts out with no theme
|
||||
self.minwidth: Optional[int] = None
|
||||
self.widgets: Dict[tk.Widget | tk.BitmapImage, Set] = {}
|
||||
self.widgets_pair: List = []
|
||||
self.defaults: Dict = {}
|
||||
self.current: Dict = {}
|
||||
self.default_ui_scale = None # None == not yet known
|
||||
self.startup_ui_scale = None
|
||||
self.default_ui_scale: float | None = None # None == not yet known
|
||||
self.startup_ui_scale: int | None = None
|
||||
|
||||
def register(self, widget: tk.Widget | tk.BitmapImage) -> None: # noqa: CCR001, C901
|
||||
# Note widget and children for later application of a theme. Note if
|
||||
|
||||
+3
-1
@@ -25,7 +25,9 @@ class TimeoutAdapter(HTTPAdapter):
|
||||
return super().send(*args, **kwargs)
|
||||
|
||||
|
||||
def new_session(timeout: int = REQUEST_TIMEOUT, session: requests.Session = None) -> requests.Session:
|
||||
def new_session(
|
||||
timeout: int = REQUEST_TIMEOUT, session: requests.Session | None = None
|
||||
) -> requests.Session:
|
||||
"""
|
||||
Create a new requests.Session and override the default HTTPAdapter with a TimeoutAdapter.
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import tkinter as tk
|
||||
import webbrowser
|
||||
from tkinter import font as tk_font
|
||||
from tkinter import ttk
|
||||
from typing import TYPE_CHECKING, Any, Optional
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
def _(x: str) -> str: ...
|
||||
@@ -29,7 +29,7 @@ if TYPE_CHECKING:
|
||||
class HyperlinkLabel(sys.platform == 'darwin' and tk.Label or ttk.Label, object): # type: ignore
|
||||
"""Clickable label for HTTP links."""
|
||||
|
||||
def __init__(self, master: Optional[tk.Tk] = None, **kw: Any) -> None:
|
||||
def __init__(self, master: tk.Frame | None = None, **kw: Any) -> None:
|
||||
self.url = 'url' in kw and kw.pop('url') or None
|
||||
self.popup_copy = kw.pop('popup_copy', False)
|
||||
self.underline = kw.pop('underline', None) # override ttk.Label's underline
|
||||
|
||||
Reference in new issue
Block a user