From 34fe5917ae9458b594d3c78573475b39ac274440 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 14 Dec 2022 15:32:10 +0000 Subject: [PATCH 001/257] develop: Bump appversion to 5.7.1-alpha0 --- config/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/__init__.py b/config/__init__.py index 955cab4a..b3b240ed 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -52,7 +52,7 @@ appcmdname = 'EDMC' # # Major.Minor.Patch(-prerelease)(+buildmetadata) # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() -_static_appversion = '5.7.0-rc1' +_static_appversion = '5.7.1-alpha0' _cached_version: Optional[semantic_version.Version] = None copyright = '© 2015-2019 Jonathan Harris, 2020-2022 EDCD' From 28071181a19eaa63841f0b6a84522c3ec3df3562 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Dec 2022 17:01:07 +0000 Subject: [PATCH 002/257] build(deps-dev): bump isort from 5.11.1 to 5.11.2 Bumps [isort](https://github.com/pycqa/isort) from 5.11.1 to 5.11.2. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.11.1...5.11.2) --- updated-dependencies: - dependency-name: isort dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index d5188fd3..a34a16bf 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -13,7 +13,7 @@ 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 +isort==5.11.2 flake8-isort==5.0.3 flake8-json==21.7.0 flake8-noqa==1.3.0 From 395dde1c0969ce108428bc908589be8c85c8ea7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Dec 2022 17:00:54 +0000 Subject: [PATCH 003/257] build(deps-dev): bump autopep8 from 2.0.0 to 2.0.1 Bumps [autopep8](https://github.com/hhatto/autopep8) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/hhatto/autopep8/releases) - [Commits](https://github.com/hhatto/autopep8/compare/v2.0.0...v2.0.1) --- updated-dependencies: - dependency-name: autopep8 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index a34a16bf..a0edf2a0 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -26,7 +26,7 @@ safety==2.3.5 types-requests==2.28.11.5 # Code formatting tools -autopep8==2.0.0 +autopep8==2.0.1 # HTML changelogs grip==4.6.1 From f789ad6e24d55fb1ce8b242056399a096f5c7b8e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 13:22:30 +0000 Subject: [PATCH 004/257] companion: A start on adding CAPI killswitches --- companion.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/companion.py b/companion.py index 3aa085ae..b8b0a662 100644 --- a/companion.py +++ b/companion.py @@ -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 @@ -325,6 +326,11 @@ class Auth(object): """ logger.debug(f'Trying for "{self.cmdr}"') + 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 +399,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: @@ -655,6 +663,11 @@ class Session(object): :return: True if login succeeded, False if re-authorization initiated. """ + 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') @@ -946,7 +959,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 <>') - self.tk_master.event_generate('<>') + if self.tk_master is not None: + self.tk_master.event_generate('<>') logger.info('CAPI worker thread DONE') From 98527e7aa0d310090f47c6458a2c4a07069cc67a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 13:24:50 +0000 Subject: [PATCH 005/257] pre-commit: Bump mypy to current latest version * The older version didn't like `check_untyped_defs = True` in .mypy.ini. * Trying `-repo: local` lead to an error about config options. * We really need a way to have this track the non-pre-commit version of mypy. --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 50d91e96..d841cda1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: # mypy - static type checking # mypy --follow-imports skip - repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v0.931' + rev: 'v0.991' hooks: - id: mypy # verbose: true From f1b2022aa23213945dfb64c30e4e28092269f32f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 13:27:21 +0000 Subject: [PATCH 006/257] .mypy.ini: s/-/_/g on check-untyped-defs --- .mypy.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mypy.ini b/.mypy.ini index 38afbb67..10ef53b7 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -5,5 +5,5 @@ scripts_are_modules = True ; Without this bare `mypy ` may get warnings for e.g. ; ` = ` ; i.e. no typing info. -check-untyped-defs = True +check_untyped_defs = True ; platform = darwin From 12ee3deb59bed4f62ce9538154ec853860d94a1d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 14:02:59 +0000 Subject: [PATCH 007/257] killswitches: Implement `--killswitches-file` CL arg * New CL arge `--killswitches-file`. This needs to reference a file either with an absolute path, or relative to the CWD of the process. * Internally if the argument is provided it is prefixed with `"file:"` in order to actually be loaded. This is because `requests` doesn't have an adapter for `file:` URLs. * Also fixes a visual bug with reporting of active killswitches. The entire SingleKill object was used instead of just its `reason` property. mypy type checks caught this. --- EDMarketConnector.py | 19 ++++++++++++++----- docs/Killswitches.md | 13 ++++++++++--- killswitch.py | 18 ++++++++++++++++-- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 21531679..470ead9c 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -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() @@ -1859,10 +1864,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,9 +1899,9 @@ 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 @@ -2026,7 +2034,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) diff --git a/docs/Killswitches.md b/docs/Killswitches.md index d90607a1..bae03c2d 100644 --- a/docs/Killswitches.md +++ b/docs/Killswitches.md @@ -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 +``` +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 diff --git a/killswitch.py b/killswitch.py index a7701739..42d02844 100644 --- a/killswitch.py +++ b/killswitch.py @@ -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 From 1cc4a9d0af5323a074ccac3511cc3cc679779eb9 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 14:17:00 +0000 Subject: [PATCH 008/257] CAPI killswitches: 'capi.auth' now preventing all CAPI actions. --- EDMarketConnector.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 470ead9c..c88fd162 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -912,6 +912,12 @@ class AppWindow(object): def login(self): """Initiate CAPI/Frontier login and set other necessary state.""" + should_return, new_data = killswitch.check_killswitch('capi.auth', {}) + if should_return: + logger.warning('capi.auth has been disabled via killswitch. Returning.') + 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...') @@ -997,6 +1003,13 @@ class AppWindow(object): :param event: Tk generated event details. """ logger.trace_if('capi.worker', 'Begin') + should_return, new_data = killswitch.check_killswitch('capi.auth', {}) + if should_return: + logger.warning('capi.auth has been disabled via killswitch. Returning.') + 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') @@ -1465,7 +1478,9 @@ class AppWindow(object): auto_update = True 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'] == 'ShutDown': # Enable WinSparkle automatic update checks From ba68397b3f1a79e46a71ab43979efbe770a803c2 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 15:06:01 +0000 Subject: [PATCH 009/257] CAPI killswitches: endpoint killswitches & eddn export ones too * Added `capi.request.` killswitches at appropriate call points. * Added `eddn.capi_export.` killswitches. This allows for killing just the EDDN export of such CAPI-derived data, without stopping the actual queries, as other plugins/functionality might still have harmless use of the data. * PLUGINS.md: Actually describe the contents of `data` passed to plugins, and point out it might not always contain market or shipyard data. This is not only because of the new killswitches, but could already have happened if the station/port docked at didn't have the services. * Some misc typing cleanups. --- EDMarketConnector.py | 13 +++++++++---- PLUGINS.md | 17 +++++++++++++---- companion.py | 21 +++++++++++++++++++-- plugins/eddn.py | 32 +++++++++++++++++++++++++++++++- 4 files changed, 72 insertions(+), 11 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index c88fd162..f8c676df 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1228,10 +1228,15 @@ 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, 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 diff --git a/PLUGINS.md b/PLUGINS.md index dc23752d..dd71ca28 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -910,10 +910,9 @@ 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. - +has just fetched fresh Cmdr and station 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 @@ -948,6 +947,16 @@ 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.** +The contents of `data` will always have at least the data returned by a CAPI +`/profile` query. 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. **But do not assume this +will always be the case**. + +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 diff --git a/companion.py b/companion.py index b8b0a662..9c1ec02c 100644 --- a/companion.py +++ b/companion.py @@ -601,7 +601,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: BaseException = exception # Exception that recipient should raise. class Session(object): @@ -772,7 +772,12 @@ 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, 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...') if conf_module.capi_pretend_down: @@ -854,6 +859,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 @@ -894,6 +903,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() @@ -904,6 +917,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() diff --git a/plugins/eddn.py b/plugins/eddn.py index 2f2ccc78..afe54047 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -636,6 +636,16 @@ class EDDN: :param data: a dict containing the starport data :param is_beta: whether or not we're currently in beta mode """ + 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', {}), @@ -757,6 +767,16 @@ class EDDN: :param data: dict containing the outfitting data :param is_beta: whether or not we're currently in beta mode """ + 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"), @@ -813,6 +833,16 @@ class EDDN: :param data: dict containing the shipyard data :param is_beta: whether or not we are in beta mode """ + 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( @@ -1857,7 +1887,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. From 729016cf38261f6b8df3df160560d9e332715291 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 15:35:59 +0000 Subject: [PATCH 010/257] companion.py: Fix exception type & initialise a requests_session * Use `Exception` not `BaseException` for `EDMCCAPIFailedRequest.exception`. * Initialise Auth.request_session in its `__init__()`. This *should* fix #1727 - as there'll then be no way for a `Session` to have methods invoked without this set up. --- companion.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/companion.py b/companion.py index 9c1ec02c..cab1640f 100644 --- a/companion.py +++ b/companion.py @@ -601,7 +601,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: BaseException = exception # Exception that recipient should raise. + self.exception: Exception = exception # Exception that recipient should raise. class Session(object): @@ -619,7 +619,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: Optional[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 From 5070c3686f6c18ee3f39a6519233bf416cecd1bf Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 15:40:48 +0000 Subject: [PATCH 011/257] companion.Session: Don't double-initaliase requests_session I forgot to remove the `requests.Session()` call in `start_frontier_auth()`. And upon removing that we need a `None` trap to make mypy happy. --- companion.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/companion.py b/companion.py index cab1640f..1c68e38b 100644 --- a/companion.py +++ b/companion.py @@ -652,9 +652,10 @@ 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 + if self.requests_session is not None: + 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: From 3e0da4b537d03d91f46e9e90f15a222388648d50 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 17:24:11 +0000 Subject: [PATCH 012/257] github/submodule-update: Needs an 'else' to actually work * Somehow this had been left in a state where it would always signal "no changes". --- .github/workflows/submodule-update.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 8ed83d31..11082721 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -33,12 +33,14 @@ jobs: continue-on-error: true run: | changes=$(git status --porcelain) + git status --porcelain if [ -n "${changes}" ]; then echo '::set-output changes=true' + else + echo '::set-output changes=false' + exit 0 fi - echo '::set-output changes=false' - exit 0 - name: Create submodules changes branch if: steps.check_for_changes.outputs.changes == 'true' From 859fe81d71bf012ac151a94d7ab78e4c74ed7ce2 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 16 Dec 2022 17:27:13 +0000 Subject: [PATCH 013/257] github/submodule-update: Ensure `exit 0` on the update check I *think* the `exit 0` is to ensure the 'Check for changes' isn't considered failed due to `git` exit code. --- .github/workflows/submodule-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 11082721..692de46a 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -39,8 +39,8 @@ jobs: echo '::set-output changes=true' else echo '::set-output changes=false' - exit 0 fi + exit 0 - name: Create submodules changes branch if: steps.check_for_changes.outputs.changes == 'true' From ede69a90122f427a9eb4d7fb1b08c176794278dc Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 09:34:33 +0000 Subject: [PATCH 014/257] github/submodule-update: steps.check_for_changes condition not working * Now I'm guessing at what the syntax needs to be, but the bare `steps.check_for_changes.outputs.changes` results in it being considerd `null` for the check. --- .github/workflows/submodule-update.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 692de46a..d5f907bd 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -43,14 +43,14 @@ jobs: exit 0 - name: Create submodules changes branch - if: steps.check_for_changes.outputs.changes == 'true' + if: ${{ steps.check_for_changes.outputs.changes }} == 'true' run: | git checkout -b $GITHUB_RUN_ID git commit -am "updating submodules" git push --set-upstream origin $GITHUB_RUN_ID - name: Create pull request against target branch - if: steps.check_for_changes.outputs.changes == 'true' + if: ${{ steps.check_for_changes.outputs.changes }} == 'true' uses: actions/github-script@v6 with: github-token: ${{ inputs.github_token }} @@ -65,7 +65,7 @@ jobs: }); - name: Add labels - if: steps.check_for_changes.outputs.changes == 'true' + if: ${{ steps.check_for_changes.outputs.changes }} == 'true' uses: actions/github-script@v6 with: github-token: ${{ inputs.github_token }} From acbb8b229435a2b6761dda68843a2c85c778f422 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 09:42:22 +0000 Subject: [PATCH 015/257] github/submodule-update: Switch to 'environment' style As per --- .github/workflows/submodule-update.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index d5f907bd..9def9e0f 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -36,21 +36,21 @@ jobs: git status --porcelain if [ -n "${changes}" ]; then - echo '::set-output changes=true' + echo 'changes=true' >> $GITHUB_OUTPUT else - echo '::set-output changes=false' + echo 'changes=false' >> $GITHUB_OUTPUT fi exit 0 - name: Create submodules changes branch - if: ${{ steps.check_for_changes.outputs.changes }} == 'true' + if: steps.check_for_changes.outputs.changes == 'true' run: | git checkout -b $GITHUB_RUN_ID git commit -am "updating submodules" git push --set-upstream origin $GITHUB_RUN_ID - name: Create pull request against target branch - if: ${{ steps.check_for_changes.outputs.changes }} == 'true' + if: steps.check_for_changes.outputs.changes == 'true' uses: actions/github-script@v6 with: github-token: ${{ inputs.github_token }} @@ -65,7 +65,7 @@ jobs: }); - name: Add labels - if: ${{ steps.check_for_changes.outputs.changes }} == 'true' + if: steps.check_for_changes.outputs.changes == 'true' uses: actions/github-script@v6 with: github-token: ${{ inputs.github_token }} From e0f6f353115e4c0f102bfe6c8e16fe709eb2bdca Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 09:48:21 +0000 Subject: [PATCH 016/257] github/submodule-update: Change to `secrets.GITHUB_TOKEN` That works in the windows-build.yml workflow. --- .github/workflows/submodule-update.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 9def9e0f..451793b6 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -53,7 +53,7 @@ jobs: 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 }}', @@ -68,7 +68,7 @@ jobs: 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: | const res = await github.rest.issues.listForRepo({ owner: '${{ inputs.owner }}', From 8831d15220e73b2efed336cc859141f372c54bd7 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 09:56:40 +0000 Subject: [PATCH 017/257] github/submodule-update: Switch to `process.env` for owner, repo, base --- .github/workflows/submodule-update.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 451793b6..d3cc2fb2 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -56,10 +56,10 @@ jobs: github-token: "${{ secrets.GITHUB_TOKEN }}" script: | await github.rest.pulls.create({ - owner: '${{ inputs.owner }}', - repo: '${{ inputs.parent_repository }}'.split('/')[1].trim(), + owner: '${{ process.env.OWNER }}', + repo: '${{ process.env.PARENT_REPOSITORY }}'.split('/')[1].trim(), head: process.env.GITHUB_RUN_ID, - base: '${{ inputs.pr_against_branch }}', + base: '${{ process.env.PR_AGAINST_BRANCH }}', title: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, body: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, }); @@ -71,14 +71,14 @@ jobs: github-token: "${{ secrets.GITHUB_TOKEN }}" script: | const res = await github.rest.issues.listForRepo({ - owner: '${{ inputs.owner }}', - repo: '${{ inputs.parent_repository }}'.split('/')[1].trim(), + owner: '${{ process.env.OWNER }}', + repo: '${{ process.env.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(), + owner: '${{ process.env.OWNER }}', + repo: '${{ process.env.PARENT_REPOSITORY }}'.split('/')[1].trim(), labels: ['${{ inputs.label }}'] }); From a68c23e52514ead5d08dce9485d4d99960aef3e4 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 09:59:17 +0000 Subject: [PATCH 018/257] github/submodule-update: Fix process.env syntax ? --- .github/workflows/submodule-update.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index d3cc2fb2..ac1823e4 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -56,10 +56,10 @@ jobs: github-token: "${{ secrets.GITHUB_TOKEN }}" script: | await github.rest.pulls.create({ - owner: '${{ process.env.OWNER }}', - repo: '${{ process.env.PARENT_REPOSITORY }}'.split('/')[1].trim(), + owner: '${process.env.OWNER}', + repo: '${process.env.PARENT_REPOSITORY}'.split('/')[1].trim(), head: process.env.GITHUB_RUN_ID, - base: '${{ process.env.PR_AGAINST_BRANCH }}', + base: '${process.env.PR_AGAINST_BRANCH}', title: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, body: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, }); @@ -71,14 +71,14 @@ jobs: github-token: "${{ secrets.GITHUB_TOKEN }}" script: | const res = await github.rest.issues.listForRepo({ - owner: '${{ process.env.OWNER }}', - repo: '${{ process.env.PARENT_REPOSITORY }}'.split('/')[1].trim(), + owner: '${process.env.OWNER}', + repo: '${process.env.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: '${{ process.env.OWNER }}', - repo: '${{ process.env.PARENT_REPOSITORY }}'.split('/')[1].trim(), + owner: '${process.env.OWNER}', + repo: '${process.env.PARENT_REPOSITORY}'.split('/')[1].trim(), labels: ['${{ inputs.label }}'] }); From 424e9754b1ac82d2eb4a9c1c70bca07922de5c0c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 11:14:18 +0000 Subject: [PATCH 019/257] github/submodule-update: Let's try `github` contexts --- .github/workflows/submodule-update.yml | 42 +++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index ac1823e4..b47812ca 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -56,29 +56,29 @@ jobs: github-token: "${{ secrets.GITHUB_TOKEN }}" script: | await github.rest.pulls.create({ - owner: '${process.env.OWNER}', - repo: '${process.env.PARENT_REPOSITORY}'.split('/')[1].trim(), + owner: '${{ github.repository_owner }}', + repo: '${{ github.repository }}'.split('/')[1].trim(), head: process.env.GITHUB_RUN_ID, - base: '${process.env.PR_AGAINST_BRANCH}', + base: '${{ github.ref }}', 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: "${{ secrets.GITHUB_TOKEN }}" - script: | - const res = await github.rest.issues.listForRepo({ - owner: '${process.env.OWNER}', - repo: '${process.env.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: '${process.env.OWNER}', - repo: '${process.env.PARENT_REPOSITORY}'.split('/')[1].trim(), - labels: ['${{ inputs.label }}'] - }); +# - name: Add labels +# if: steps.check_for_changes.outputs.changes == 'true' +# uses: actions/github-script@v6 +# with: +# github-token: "${{ secrets.GITHUB_TOKEN }}" +# script: | +# const res = await github.rest.issues.listForRepo({ +# owner: '${{ github.repository_owner }}', +# repo: '${{ github.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: '${{ github.repository_owner }}', +# repo: '${{ github.repository }}'.split('/')[1].trim(), +# labels: ['${{ inputs.label }}'] +# }); From 130bda0cc9485e2217e61fd7adc9154ae5453c44 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 11:21:03 +0000 Subject: [PATCH 020/257] github/submodule-update: Try to use `git status` output in PR body --- .github/workflows/submodule-update.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index b47812ca..3d0b5d57 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -37,6 +37,7 @@ jobs: if [ -n "${changes}" ]; then echo 'changes=true' >> $GITHUB_OUTPUT + echo "changes_text=${changes}" >> $GITHUB_OUTPUT else echo 'changes=false' >> $GITHUB_OUTPUT fi @@ -61,7 +62,7 @@ jobs: head: process.env.GITHUB_RUN_ID, base: '${{ github.ref }}', title: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, - body: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, + body: '${{ steps.check_for_changes.outputs.changes_text }}', }); # - name: Add labels From 8fab1fa8111d512b7856385d7b68fe2266c20d4b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 11:25:16 +0000 Subject: [PATCH 021/257] github/submodule-update: Make better branch names --- .github/workflows/submodule-update.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 3d0b5d57..407f567d 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -46,9 +46,9 @@ jobs: - 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" 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' @@ -59,7 +59,7 @@ jobs: await github.rest.pulls.create({ owner: '${{ github.repository_owner }}', repo: '${{ github.repository }}'.split('/')[1].trim(), - head: process.env.GITHUB_RUN_ID, + head: 'submodule-change/${{ github.run_id }}', base: '${{ github.ref }}', title: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, body: '${{ steps.check_for_changes.outputs.changes_text }}', From 640223472b481841095705d500fb8bccad2435ae Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 11:26:51 +0000 Subject: [PATCH 022/257] github/submodule-update: Remove unused 'Add labels' step 1. This was commented out. 2. It's not necessarily up to date with what *works*, so just delete it. --- .github/workflows/submodule-update.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 407f567d..9af87368 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -64,22 +64,3 @@ jobs: title: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, body: '${{ steps.check_for_changes.outputs.changes_text }}', }); - -# - name: Add labels -# if: steps.check_for_changes.outputs.changes == 'true' -# uses: actions/github-script@v6 -# with: -# github-token: "${{ secrets.GITHUB_TOKEN }}" -# script: | -# const res = await github.rest.issues.listForRepo({ -# owner: '${{ github.repository_owner }}', -# repo: '${{ github.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: '${{ github.repository_owner }}', -# repo: '${{ github.repository }}'.split('/')[1].trim(), -# labels: ['${{ inputs.label }}'] -# }); From 70a9c7d8abdbd1e8ccc501e713fd60d02ea20237 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 11:30:56 +0000 Subject: [PATCH 023/257] github/submodule-update: Run every day at mid-day. --- .github/workflows/submodule-update.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 9af87368..691e250e 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -2,9 +2,8 @@ name: Submodule Updates on: - # We might want this on a schedule once this is in `main` - push: - branches: [ develop ] + schedule: + - cron: '00 12 * * *' jobs: check_submodules: From de16284b25e119b73220ea33ba1fb56fcd29bc0b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 12:04:51 +0000 Subject: [PATCH 024/257] github/submodule-update: Run *every* hour for test purposes --- .github/workflows/submodule-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 691e250e..38f23f3f 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -3,7 +3,7 @@ name: Submodule Updates on: schedule: - - cron: '00 12 * * *' + - cron: '10 * * * *' jobs: check_submodules: From 06d83399c067eaf26d4e2fcd602d34993b6d8b36 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 12:40:35 +0000 Subject: [PATCH 025/257] Revert "github/submodule-update: Run *every* hour for test purposes" This reverts commit ee1c739ee15208980ea0554e9b172b614ec18869. --- .github/workflows/submodule-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 38f23f3f..691e250e 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -3,7 +3,7 @@ name: Submodule Updates on: schedule: - - cron: '10 * * * *' + - cron: '00 12 * * *' jobs: check_submodules: From 414f9d8dae753d317e4a84d2670a3d98a1852404 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 12:40:48 +0000 Subject: [PATCH 026/257] github/submodule-update: Use single `0` in cron spec Just in case that `00` was the issue. It ran fine with `10 * * * *`. --- .github/workflows/submodule-update.yml | 2 +- FDevIDs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 691e250e..85f45ff0 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -3,7 +3,7 @@ name: Submodule Updates on: schedule: - - cron: '00 12 * * *' + - cron: '0 12 * * *' jobs: check_submodules: diff --git a/FDevIDs b/FDevIDs index 3fd5d202..726fb916 160000 --- a/FDevIDs +++ b/FDevIDs @@ -1 +1 @@ -Subproject commit 3fd5d202e529c52748b1e9b94433262810f6e295 +Subproject commit 726fb91654edb020491e57ce8c07041296645cd0 From 273962e67952d0a3383585c194d29e71f1e38df8 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 12:48:29 +0000 Subject: [PATCH 027/257] github/submodule-update: Move back to using our defined `env` We need to run against `develop`, even when on `main` using a cron, so actually use the environment vars we define. --- .github/workflows/submodule-update.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 85f45ff0..79819a67 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -25,6 +25,7 @@ jobs: run: | git config user.name github-actions git config user.email github-actions@github.com + git checkout $CHECKOUT_BRANCH git submodule update --remote - name: Check for changes @@ -45,7 +46,7 @@ jobs: - name: Create submodules changes branch if: steps.check_for_changes.outputs.changes == 'true' run: | - git checkout -b "submodule-change/$GITHUB_RUN_ID" + git checkout -b "submodule-change/$GITHUB_RUN_ID" $CHECKOUT_BRANCH git commit -am "updating submodules" git push --set-upstream origin "submodule-change/$GITHUB_RUN_ID" @@ -59,7 +60,7 @@ jobs: owner: '${{ github.repository_owner }}', repo: '${{ github.repository }}'.split('/')[1].trim(), head: 'submodule-change/${{ github.run_id }}', - base: '${{ github.ref }}', + base: '$PR_AGAINST_BRANCH', title: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, body: '${{ steps.check_for_changes.outputs.changes_text }}', }); From c3100b1fd5efaa27cb5d225e43d8a0f4986491c0 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 12:50:48 +0000 Subject: [PATCH 028/257] github/submodule-update: Also run on `develop` pushes --- .github/workflows/submodule-update.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 79819a67..16bc5511 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -2,6 +2,8 @@ name: Submodule Updates on: + push: + branches: [ develop ] schedule: - cron: '0 12 * * *' From 7bffb1fa3b9d0fccfd889ad2f3315f4f76480e04 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 12:53:38 +0000 Subject: [PATCH 029/257] FDevIDs: reset back to before recent commits for workflow testing --- FDevIDs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FDevIDs b/FDevIDs index 726fb916..3fd5d202 160000 --- a/FDevIDs +++ b/FDevIDs @@ -1 +1 @@ -Subproject commit 726fb91654edb020491e57ce8c07041296645cd0 +Subproject commit 3fd5d202e529c52748b1e9b94433262810f6e295 From f27d0bf74dc636ee482898b02c307073fb643ed2 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 12:56:11 +0000 Subject: [PATCH 030/257] github/submodule-update: Tweak reference to PR_AGAINST_BRANCH --- .github/workflows/submodule-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 16bc5511..1ce2c214 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -62,7 +62,7 @@ jobs: owner: '${{ github.repository_owner }}', repo: '${{ github.repository }}'.split('/')[1].trim(), head: 'submodule-change/${{ github.run_id }}', - base: '$PR_AGAINST_BRANCH', + base: '${ process.env.PR_AGAINST_BRANCH }', title: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, body: '${{ steps.check_for_changes.outputs.changes_text }}', }); From 6ec68c50344a03796e8fece81e7a03cb07d8a479 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 12:59:20 +0000 Subject: [PATCH 031/257] github/submodule-update: Reference `env` as a context thing. --- .github/workflows/submodule-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 1ce2c214..f3c6cfa7 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -62,7 +62,7 @@ jobs: owner: '${{ github.repository_owner }}', repo: '${{ github.repository }}'.split('/')[1].trim(), head: 'submodule-change/${{ github.run_id }}', - base: '${ process.env.PR_AGAINST_BRANCH }', + base: '${{ env.PR_AGAINST_BRANCH }}', title: `[Auto-generated] Submodule Updates ${process.env.GITHUB_RUN_ID}`, body: '${{ steps.check_for_changes.outputs.changes_text }}', }); From ceed5886a8f9f0a1ea0d5263988b6bd7af4fb940 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 17 Dec 2022 13:02:48 +0000 Subject: [PATCH 032/257] github/submodule-update: Disable push/develop trigger --- .github/workflows/submodule-update.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index f3c6cfa7..6142c054 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -2,8 +2,8 @@ name: Submodule Updates on: - push: - branches: [ develop ] + # push: + # branches: [ develop ] schedule: - cron: '0 12 * * *' From a9695aa1ee153de4cb407717667796af947aaadf Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 18 Dec 2022 13:10:45 +0000 Subject: [PATCH 033/257] github/submodule-update: Direct actions/checkout to use `develop` --- .github/workflows/submodule-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/submodule-update.yml b/.github/workflows/submodule-update.yml index 6142c054..5a84fde6 100644 --- a/.github/workflows/submodule-update.yml +++ b/.github/workflows/submodule-update.yml @@ -20,6 +20,7 @@ jobs: steps: - uses: actions/checkout@v3 with: + ref: '${{ env.CHECKOUT_BRANCH }}' submodules: true - name: Update submodules @@ -27,7 +28,6 @@ jobs: run: | git config user.name github-actions git config user.email github-actions@github.com - git checkout $CHECKOUT_BRANCH git submodule update --remote - name: Check for changes From 18b54ee5596e54af73b5a9250c7200bb29086e71 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 19 Dec 2022 12:12:10 +0000 Subject: [PATCH 034/257] updating submodules --- FDevIDs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FDevIDs b/FDevIDs index 3fd5d202..726fb916 160000 --- a/FDevIDs +++ b/FDevIDs @@ -1 +1 @@ -Subproject commit 3fd5d202e529c52748b1e9b94433262810f6e295 +Subproject commit 726fb91654edb020491e57ce8c07041296645cd0 From a729d4d500729a073d958e3f36a1e471cba1881b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 19 Dec 2022 12:32:04 +0000 Subject: [PATCH 035/257] docs/Releasing: Always run ./coriolis.py for a build --- docs/Releasing.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/Releasing.md b/docs/Releasing.md index 7e7d818a..9840c694 100644 --- a/docs/Releasing.md +++ b/docs/Releasing.md @@ -191,14 +191,16 @@ 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. 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`. **NB: The + submodule might have been updated by a GitHub workflow/PR/merge, so + be sure to perform this step for every build.** + 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). # Preparing to Package From 46083054a01b274c6dfc6ad18a5c6feae9f1cc4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 17:01:32 +0000 Subject: [PATCH 036/257] build(deps-dev): bump isort from 5.11.2 to 5.11.3 Bumps [isort](https://github.com/pycqa/isort) from 5.11.2 to 5.11.3. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.11.2...5.11.3) --- updated-dependencies: - dependency-name: isort dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index a0edf2a0..e82e2925 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -13,7 +13,7 @@ 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.2 +isort==5.11.3 flake8-isort==5.0.3 flake8-json==21.7.0 flake8-noqa==1.3.0 From 868c1d8e577be227b4492fa93c07bc2c13f8db7f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 20 Dec 2022 16:51:58 +0000 Subject: [PATCH 037/257] docs: Fix up references to setup.py to be to Build-exe-and-msi.py --- Contributing.md | 7 ++++--- docs/Windows-Manifest.md | 2 +- plugins/coriolis.py | 7 +++---- plugins/eddn.py | 7 +++---- plugins/inara.py | 7 +++---- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/Contributing.md b/Contributing.md index 29135804..1514f1a5 100644 --- a/Contributing.md +++ b/Contributing.md @@ -296,7 +296,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 +316,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). --- diff --git a/docs/Windows-Manifest.md b/docs/Windows-Manifest.md index 68136778..ab0014a7 100644 --- a/docs/Windows-Manifest.md +++ b/docs/Windows-Manifest.md @@ -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 diff --git a/plugins/coriolis.py b/plugins/coriolis.py index 78ae1b41..fef683b9 100644 --- a/plugins/coriolis.py +++ b/plugins/coriolis.py @@ -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. # # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# diff --git a/plugins/eddn.py b/plugins/eddn.py index afe54047..b1df07b7 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -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. # # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# diff --git a/plugins/inara.py b/plugins/inara.py index dc39d530..f3f32741 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -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. # # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# From 8db61dc76cd2e5c5f870fb8c2f9e50d2ff4e2658 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 20 Dec 2022 16:55:57 +0000 Subject: [PATCH 038/257] requirements-dev: Add pre-commit==2.20.0 --- requirements-dev.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/requirements-dev.txt b/requirements-dev.txt index e82e2925..4dd84284 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -28,6 +28,9 @@ types-requests==2.28.11.5 # Code formatting tools autopep8==2.0.1 +# Git pre-commit checking +pre-commit==2.20.0 + # HTML changelogs grip==4.6.1 From 0abd4665ff172af800f77e24d9b39cf0693de11d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 17:00:54 +0000 Subject: [PATCH 039/257] build(deps-dev): bump pep8-naming from 0.13.2 to 0.13.3 Bumps [pep8-naming](https://github.com/PyCQA/pep8-naming) from 0.13.2 to 0.13.3. - [Release notes](https://github.com/PyCQA/pep8-naming/releases) - [Changelog](https://github.com/PyCQA/pep8-naming/blob/main/CHANGELOG.rst) - [Commits](https://github.com/PyCQA/pep8-naming/compare/0.13.2...0.13.3) --- updated-dependencies: - dependency-name: pep8-naming dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 4dd84284..89c64f2e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -21,7 +21,7 @@ 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 From 8386487dc1f7a3738abf84d5d68adbc26fa555e3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 20 Dec 2022 17:58:38 +0000 Subject: [PATCH 040/257] Tweak non-developer-running-develop check This allows for someone running a custom branch, with working `git branch`, even if it's an `-alpha0` version. --- EDMarketConnector.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index f8c676df..779aa006 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -387,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' @@ -397,7 +399,7 @@ if __name__ == '__main__': # noqa: C901 or ( sys.platform == 'win32' and environ.get('USERNAME') is not None - and environ['USERNAME'] not in ['Athan'] + and environ['USERNAME'] not in ['XAthan'] ) ) ): From 579c95024b91aeb4b3744c2233e9549c8f133116 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 21 Dec 2022 10:45:55 +0000 Subject: [PATCH 041/257] 'develop only for devs': d'oh, re-allow Athan on Windows --- EDMarketConnector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 779aa006..8dd45f8c 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -399,7 +399,7 @@ if __name__ == '__main__': # noqa: C901 or ( sys.platform == 'win32' and environ.get('USERNAME') is not None - and environ['USERNAME'] not in ['XAthan'] + and environ['USERNAME'] not in ['Athan'] ) ) ): From 87b48031a0c7e3d321c2e432642ee1e902b1043d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 21 Dec 2022 12:30:53 +0000 Subject: [PATCH 042/257] development: Also exclude `.venv/` as that's VSCode default --- .flake8 | 2 +- .gitignore | 3 ++- pyproject.toml | 2 +- scripts/find_localised_strings.py | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.flake8 b/.flake8 index bf632685..c8dc0cc6 100644 --- a/.flake8 +++ b/.flake8 @@ -6,7 +6,7 @@ exclude = dist.win32/ FDevIDs/ venv/ - venv-py39/ + .venv/ wix/ # Show exactly where in a line the error happened diff --git a/.gitignore b/.gitignore index 9bea3d5a..4b13d5c3 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,8 @@ EDMarketConnector.VisualElementsManifest.xml .idea .vscode -venv +.venv/ +venv/ *.code-workspace htmlcov/ .ignored diff --git a/pyproject.toml b/pyproject.toml index 91c6e7e3..16f8d6dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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] diff --git a/scripts/find_localised_strings.py b/scripts/find_localised_strings.py index ff5dc693..74cfe1b4 100644 --- a/scripts/find_localised_strings.py +++ b/scripts/find_localised_strings.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') From 255b1913d82e6c9d93b4fed7ae43acd8146e9e76 Mon Sep 17 00:00:00 2001 From: aussig Date: Wed, 21 Dec 2022 12:50:13 +0000 Subject: [PATCH 043/257] Initial implementation of CAPI /fleetcarrier endpoint --- EDMarketConnector.py | 5 +++++ companion.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 8dd45f8c..bc8d2f29 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1081,6 +1081,11 @@ class AppWindow(object): query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME, play_sound=play_sound ) + 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, + play_sound=play_sound + ) def capi_handle_response(self, event=None): # noqa: C901, CCR001 """Handle the resulting data from a CAPI query.""" diff --git a/companion.py b/companion.py index 1c68e38b..650aa2c9 100644 --- a/companion.py +++ b/companion.py @@ -612,6 +612,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' @@ -949,6 +951,9 @@ 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) + else: capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_PROFILE) @@ -1020,6 +1025,35 @@ class Session(object): auto_update=auto_update ) ) + + def fleetcarrier( + self, query_time: int, tk_response_event: Optional[str] = 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 + ) + ) ###################################################################### ###################################################################### From 254988fd803ebce379d7faa2c14f1cb8799ad669 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 21 Dec 2022 13:05:36 +0000 Subject: [PATCH 044/257] Contributing.md: Add 'Python Environment' section. --- Contributing.md | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/Contributing.md b/Contributing.md index 1514f1a5..ce100ee4 100644 --- a/Contributing.md +++ b/Contributing.md @@ -196,6 +196,95 @@ 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. + +### 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: +# +# + +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 From 2b79b89803bf8e984bb347a01bb8a8a3f3b860dc Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 21 Dec 2022 13:10:01 +0000 Subject: [PATCH 045/257] Contributing/Python-env: Note VSCode issue with pre-commit. --- Contributing.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Contributing.md b/Contributing.md index ce100ee4..119f8957 100644 --- a/Contributing.md +++ b/Contributing.md @@ -245,6 +245,10 @@ 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 From 5b38a96828c1a3b8fe5b95e146223702794820b7 Mon Sep 17 00:00:00 2001 From: aussig Date: Wed, 21 Dec 2022 13:15:08 +0000 Subject: [PATCH 046/257] Initial implementation of CAPI /fleetcarrier endpoint --- EDMarketConnector.py | 5 +++++ companion.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 8dd45f8c..bc8d2f29 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1081,6 +1081,11 @@ class AppWindow(object): query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME, play_sound=play_sound ) + 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, + play_sound=play_sound + ) def capi_handle_response(self, event=None): # noqa: C901, CCR001 """Handle the resulting data from a CAPI query.""" diff --git a/companion.py b/companion.py index 1c68e38b..650aa2c9 100644 --- a/companion.py +++ b/companion.py @@ -612,6 +612,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' @@ -949,6 +951,9 @@ 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) + else: capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_PROFILE) @@ -1020,6 +1025,35 @@ class Session(object): auto_update=auto_update ) ) + + def fleetcarrier( + self, query_time: int, tk_response_event: Optional[str] = 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 + ) + ) ###################################################################### ###################################################################### From e65a1e6afa16e83a2e4f065a9bca2ce144833748 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 21 Dec 2022 13:27:53 +0000 Subject: [PATCH 047/257] companion: Have `Session.close()` actually open a new one by default Both current callers to this are in code paths where it is expected that Session.requests_session will be valid later. Rather than assign a new session at the call sites just make this by default open a new session. --- companion.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/companion.py b/companion.py index 1c68e38b..9cf69b42 100644 --- a/companion.py +++ b/companion.py @@ -733,7 +733,7 @@ class Session(object): self.auth = None raise # Bad thing happened - def close(self) -> None: + def close(self, reopen: bool = True) -> None: """Close Frontier authorization session.""" self.state = Session.STATE_INIT if self.requests_session: @@ -742,8 +742,11 @@ class Session(object): except Exception as e: logger.debug('Frontier Auth: closing', exc_info=e) + self.requests_session = None - self.requests_session = None + # 2022-12-21: Current callers all need a *new* session. + if reopen: + self.requests_session = requests.Session() def invalidate(self) -> None: """Invalidate Frontier authorization credentials.""" From df384c73a1292a086baf9f1025e24bf771067f96 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 21 Dec 2022 13:36:39 +0000 Subject: [PATCH 048/257] companion: Refactor Session.close() to Session.reinit_session() This way it's *never* `None`, and the type can be tightend up as well. --- companion.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/companion.py b/companion.py index 9cf69b42..adff3db6 100644 --- a/companion.py +++ b/companion.py @@ -619,7 +619,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] = requests.Session() + 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 @@ -652,9 +652,8 @@ class Session(object): def start_frontier_auth(self, access_token: str) -> None: """Start an oAuth2 session.""" logger.debug('Starting session') - if self.requests_session is not None: - self.requests_session.headers['Authorization'] = f'Bearer {access_token}' - self.requests_session.headers['User-Agent'] = user_agent + self.requests_session.headers['Authorization'] = f'Bearer {access_token}' + self.requests_session.headers['User-Agent'] = user_agent self.state = Session.STATE_OK @@ -694,7 +693,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 @@ -733,26 +732,27 @@ class Session(object): self.auth = None raise # Bad thing happened - def close(self, reopen: bool = True) -> None: - """Close Frontier authorization session.""" + 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() + try: + self.requests_session.close() - except Exception as e: - logger.debug('Frontier Auth: closing', exc_info=e) - self.requests_session = None + except Exception as e: + logger.debug('Frontier Auth: closing', exc_info=e) - # 2022-12-21: Current callers all need a *new* session. - if reopen: - self.requests_session = requests.Session() + 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 ###################################################################### From d6c74c269db091bd33e383b70e6d60f882b977eb Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 21 Dec 2022 13:41:07 +0000 Subject: [PATCH 049/257] companion: Cite endpoint in capi_single_query() logging --- companion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/companion.py b/companion.py index adff3db6..725c9101 100644 --- a/companion.py +++ b/companion.py @@ -783,7 +783,7 @@ class Session(object): 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}') From 8b30ba83316345a004139cff32b8e6098629ee5e Mon Sep 17 00:00:00 2001 From: aussig Date: Wed, 21 Dec 2022 13:43:38 +0000 Subject: [PATCH 050/257] Initial implementation of CAPI /fleetcarrier endpoint --- EDMarketConnector.py | 5 +++++ companion.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 8dd45f8c..bc8d2f29 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1081,6 +1081,11 @@ class AppWindow(object): query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME, play_sound=play_sound ) + 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, + play_sound=play_sound + ) def capi_handle_response(self, event=None): # noqa: C901, CCR001 """Handle the resulting data from a CAPI query.""" diff --git a/companion.py b/companion.py index 725c9101..ebdbe868 100644 --- a/companion.py +++ b/companion.py @@ -612,6 +612,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' @@ -952,6 +954,9 @@ 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) + else: capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_PROFILE) @@ -1023,6 +1028,35 @@ class Session(object): auto_update=auto_update ) ) + + def fleetcarrier( + self, query_time: int, tk_response_event: Optional[str] = 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 + ) + ) ###################################################################### ###################################################################### From 4f488e237d78aa04f48ad058f73c21ff9b9665ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Dec 2022 17:01:17 +0000 Subject: [PATCH 051/257] build(deps-dev): bump types-requests from 2.28.11.5 to 2.28.11.6 Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.5 to 2.28.11.6. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 89c64f2e..e0098f88 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -23,7 +23,7 @@ flake8-use-fstring==1.4 mypy==0.991 pep8-naming==0.13.3 safety==2.3.5 -types-requests==2.28.11.5 +types-requests==2.28.11.6 # Code formatting tools autopep8==2.0.1 From f7e0575167cd9084dc089c88f9e5b4d65966923d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 21 Dec 2022 18:26:42 +0000 Subject: [PATCH 052/257] LICENSE: Linting EOF blank line added. --- LICENSE | 1 - 1 file changed, 1 deletion(-) diff --git a/LICENSE b/LICENSE index 8cdb8451..23cb7903 100644 --- a/LICENSE +++ b/LICENSE @@ -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. - From fb78ff3820dc1635fccaa8902d19bd85fc4af177 Mon Sep 17 00:00:00 2001 From: aussig Date: Wed, 21 Dec 2022 20:20:14 +0000 Subject: [PATCH 053/257] Handling of /fleetcarrier CAPI endpoint and implementation of plugin callback function --- EDMarketConnector.py | 23 ++++++++++++++++++++++- plug.py | 26 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index bc8d2f29..5193a0d6 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1112,7 +1112,28 @@ class AppWindow(object): raise ValueError(msg) # Validation - if 'commander' not in capi_response.capi_data: + if capi_response.capi_data.source_endpoint == companion.session.FRONTIER_CAPI_PATH_FLEETCARRIER: + 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, monitor.is_beta) + self.status['text'] = err and err or '' + if err: + play_bad = True + + # TODO: Need to set a different holdoff time for the FC CAPI request + self.capi_query_holdoff_time = capi_response.query_time + companion.capi_query_cooldown + + 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') diff --git a/plug.py b/plug.py index deeb6ebe..9b68082c 100644 --- a/plug.py +++ b/plug.py @@ -401,6 +401,32 @@ def notify_capidata( return error +def notify_capi_fleetcarrierdata( + data: companion.CAPIData, + is_beta: bool +) -> Optional[str]: + """ + Send the latest CAPI Fleetcarrier data from the FD servers to each plugin. + + :param data: + :param is_beta: whether the player is in a Beta universe. + :returns: Error message from the first plugin that returns one (if any) + """ + error = None + for plugin in PLUGINS: + fc_data = plugin._get_func('capi_fleetcarrier') + + if fc_data: + try: + newerror = fc_data(data, is_beta) + error = error or 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. From c85ddbac9a6caec272ace3aad9ac1eca122b0958 Mon Sep 17 00:00:00 2001 From: aussig Date: Wed, 21 Dec 2022 22:58:25 +0000 Subject: [PATCH 054/257] Fleetcarrier CAPI now triggered by certain carrier journal events, and throttled on its own cooldown (15 mins) --- EDMarketConnector.py | 65 ++++++++++++++++++++++++++++++++++++++++---- companion.py | 1 + 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 5193a0d6..0373d4b4 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -476,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) @@ -1081,10 +1083,55 @@ class AppWindow(object): query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME, 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, new_data = killswitch.check_killswitch('capi.fleetcarrier', {}) + if should_return: + logger.warning('capi.fleetcarrier has been disabled via killswitch. Returning.') + 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 queries aborted because Cmdr name is unknown + self.status['text'] = _('CAPI query aborted: Cmdr name unknown') + return + + if not monitor.mode: + logger.trace_if('capi.worker', 'Aborting Query: Game Mode unknown') + # LANG: CAPI queries aborted because game mode unknown + self.status['text'] = _('CAPI query aborted: Game mode unknown') + return + + if monitor.state['GameVersion'] is None: + logger.trace_if('capi.worker', 'Aborting Query: GameVersion unknown') + # LANG: CAPI queries 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 + 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, - play_sound=play_sound + query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME ) def capi_handle_response(self, event=None): # noqa: C901, CCR001 @@ -1111,8 +1158,9 @@ class AppWindow(object): logger.error(msg) raise ValueError(msg) - # Validation 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') @@ -1130,9 +1178,11 @@ class AppWindow(object): if err: play_bad = True - # TODO: Need to set a different holdoff time for the FC CAPI request - self.capi_query_holdoff_time = capi_response.query_time + companion.capi_query_cooldown + self.capi_fleetcarrier_query_holdoff_time = capi_response.query_time \ + + companion.capi_fleetcarrier_query_cooldown + # Other CAPI response + # Validation 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 @@ -1515,6 +1565,11 @@ class AppWindow(object): if not should_return: self.w.after(int(SERVER_RETRY * 1000), self.capi_request_data) + if entry['event'] in ['CarrierBuy', 'CarrierStats', 'CarrierTradeOrder']: # 'CargoTransfer' too? + should_return, new_data = killswitch.check_killswitch('capi.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 diff --git a/companion.py b/companion.py index ebdbe868..49c20057 100644 --- a/companion.py +++ b/companion.py @@ -46,6 +46,7 @@ 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 auth_timeout = 30 # timeout for initial auth From eedf4febdf33de8fd99be5e95c3f8a62323a7a4f Mon Sep 17 00:00:00 2001 From: aussig Date: Wed, 21 Dec 2022 23:00:35 +0000 Subject: [PATCH 055/257] Initial implementation of CAPI /fleetcarrier endpoint --- EDMarketConnector.py | 5 +++++ companion.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 8dd45f8c..bc8d2f29 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1081,6 +1081,11 @@ class AppWindow(object): query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME, play_sound=play_sound ) + 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, + play_sound=play_sound + ) def capi_handle_response(self, event=None): # noqa: C901, CCR001 """Handle the resulting data from a CAPI query.""" diff --git a/companion.py b/companion.py index 725c9101..ebdbe868 100644 --- a/companion.py +++ b/companion.py @@ -612,6 +612,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' @@ -952,6 +954,9 @@ 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) + else: capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_PROFILE) @@ -1023,6 +1028,35 @@ class Session(object): auto_update=auto_update ) ) + + def fleetcarrier( + self, query_time: int, tk_response_event: Optional[str] = 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 + ) + ) ###################################################################### ###################################################################### From 8e5953408e5b4c288d40431ad9af30cb65c38d1a Mon Sep 17 00:00:00 2001 From: aussig Date: Wed, 21 Dec 2022 23:00:35 +0000 Subject: [PATCH 056/257] Handling of /fleetcarrier CAPI endpoint and implementation of plugin callback function --- EDMarketConnector.py | 23 ++++++++++++++++++++++- plug.py | 26 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index bc8d2f29..5193a0d6 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1112,7 +1112,28 @@ class AppWindow(object): raise ValueError(msg) # Validation - if 'commander' not in capi_response.capi_data: + if capi_response.capi_data.source_endpoint == companion.session.FRONTIER_CAPI_PATH_FLEETCARRIER: + 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, monitor.is_beta) + self.status['text'] = err and err or '' + if err: + play_bad = True + + # TODO: Need to set a different holdoff time for the FC CAPI request + self.capi_query_holdoff_time = capi_response.query_time + companion.capi_query_cooldown + + 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') diff --git a/plug.py b/plug.py index deeb6ebe..9b68082c 100644 --- a/plug.py +++ b/plug.py @@ -401,6 +401,32 @@ def notify_capidata( return error +def notify_capi_fleetcarrierdata( + data: companion.CAPIData, + is_beta: bool +) -> Optional[str]: + """ + Send the latest CAPI Fleetcarrier data from the FD servers to each plugin. + + :param data: + :param is_beta: whether the player is in a Beta universe. + :returns: Error message from the first plugin that returns one (if any) + """ + error = None + for plugin in PLUGINS: + fc_data = plugin._get_func('capi_fleetcarrier') + + if fc_data: + try: + newerror = fc_data(data, is_beta) + error = error or 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. From 6ebdea1a6cd262c8d83bb1a0af614ccc04e26a43 Mon Sep 17 00:00:00 2001 From: aussig Date: Wed, 21 Dec 2022 23:00:36 +0000 Subject: [PATCH 057/257] Fleetcarrier CAPI now triggered by certain carrier journal events, and throttled on its own cooldown (15 mins) --- EDMarketConnector.py | 65 ++++++++++++++++++++++++++++++++++++++++---- companion.py | 1 + 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 5193a0d6..0373d4b4 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -476,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) @@ -1081,10 +1083,55 @@ class AppWindow(object): query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME, 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, new_data = killswitch.check_killswitch('capi.fleetcarrier', {}) + if should_return: + logger.warning('capi.fleetcarrier has been disabled via killswitch. Returning.') + 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 queries aborted because Cmdr name is unknown + self.status['text'] = _('CAPI query aborted: Cmdr name unknown') + return + + if not monitor.mode: + logger.trace_if('capi.worker', 'Aborting Query: Game Mode unknown') + # LANG: CAPI queries aborted because game mode unknown + self.status['text'] = _('CAPI query aborted: Game mode unknown') + return + + if monitor.state['GameVersion'] is None: + logger.trace_if('capi.worker', 'Aborting Query: GameVersion unknown') + # LANG: CAPI queries 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 + 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, - play_sound=play_sound + query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME ) def capi_handle_response(self, event=None): # noqa: C901, CCR001 @@ -1111,8 +1158,9 @@ class AppWindow(object): logger.error(msg) raise ValueError(msg) - # Validation 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') @@ -1130,9 +1178,11 @@ class AppWindow(object): if err: play_bad = True - # TODO: Need to set a different holdoff time for the FC CAPI request - self.capi_query_holdoff_time = capi_response.query_time + companion.capi_query_cooldown + self.capi_fleetcarrier_query_holdoff_time = capi_response.query_time \ + + companion.capi_fleetcarrier_query_cooldown + # Other CAPI response + # Validation 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 @@ -1515,6 +1565,11 @@ class AppWindow(object): if not should_return: self.w.after(int(SERVER_RETRY * 1000), self.capi_request_data) + if entry['event'] in ['CarrierBuy', 'CarrierStats', 'CarrierTradeOrder']: # 'CargoTransfer' too? + should_return, new_data = killswitch.check_killswitch('capi.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 diff --git a/companion.py b/companion.py index ebdbe868..49c20057 100644 --- a/companion.py +++ b/companion.py @@ -46,6 +46,7 @@ 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 auth_timeout = 30 # timeout for initial auth From a551da59a35777738a505e6886acca5a45194c1a Mon Sep 17 00:00:00 2001 From: aussig Date: Thu, 22 Dec 2022 08:57:50 +0000 Subject: [PATCH 058/257] Documentation for capi_fleetcarrier() plugin callback function --- PLUGINS.md | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index dd71ca28..f768b7aa 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -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 @@ -940,6 +940,37 @@ 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 | + +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`, `CarrierStats` or `CarrierTradeOrder` 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). + +```python +from companion import CAPIData, SERVER_LIVE, SERVER_LEGACY, SERVER_BETA + +def capi_fleetcarrier(data, is_beta): + """ + 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 | +| `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 @@ -947,12 +978,14 @@ 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.** -The contents of `data` will always have at least the data returned by a CAPI +In the `cmdr_data()` callback, the contents of `data` will always have at least the data returned by a CAPI `/profile` query. 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. **But do not assume this will always be the case**. +In the `capi_fleetcarrier()` callback, the contents of `data` will be the unmodified response from the CAPI `/fleetcarrier` query. 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. + 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. @@ -1082,7 +1115,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). @@ -1311,7 +1344,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. From 292b449cf68be4b189986bf2b867d6c30c041785 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 09:15:16 +0000 Subject: [PATCH 059/257] Fix up companion.Session.close() refactor * When PyCharm made a mess I accidentally undid two renames in EDMarketConnector.py... * ... but one of those actually *does* need to only close the session. So made a new Session.close() that performs only the closing, with Session.reinit_session() now utilising that. --- EDMarketConnector.py | 2 +- companion.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 8dd45f8c..bed58e99 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1253,7 +1253,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(): diff --git a/companion.py b/companion.py index 725c9101..41fc3b7d 100644 --- a/companion.py +++ b/companion.py @@ -732,6 +732,14 @@ class Session(object): self.auth = None raise # Bad thing happened + def close(self) -> None: + """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()`. @@ -739,11 +747,7 @@ class Session(object): :param reopen: Whether to open a new session. """ self.state = Session.STATE_INIT - try: - self.requests_session.close() - - except Exception as e: - logger.debug('Frontier Auth: closing', exc_info=e) + self.close() if reopen: self.requests_session = requests.Session() From 9e17c46b25e258c4a150147d48e5dde1d0b2c230 Mon Sep 17 00:00:00 2001 From: aussig Date: Thu, 22 Dec 2022 16:21:42 +0000 Subject: [PATCH 060/257] Implement suggestions from PR #1773. --- EDMarketConnector.py | 23 +++++++++-------------- PLUGINS.md | 5 ++--- companion.py | 4 +++- plug.py | 14 ++++++-------- 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index fc4bca2c..f2d6ac4d 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -916,7 +916,7 @@ class AppWindow(object): def login(self): """Initiate CAPI/Frontier login and set other necessary state.""" - should_return, new_data = killswitch.check_killswitch('capi.auth', {}) + should_return, __ = killswitch.check_killswitch('capi.auth', {}) if should_return: logger.warning('capi.auth has been disabled via killswitch. Returning.') self.status['text'] = 'CAPI auth disabled by killswitch' @@ -1007,7 +1007,7 @@ class AppWindow(object): :param event: Tk generated event details. """ logger.trace_if('capi.worker', 'Begin') - should_return, new_data = killswitch.check_killswitch('capi.auth', {}) + should_return, __ = killswitch.check_killswitch('capi.auth', {}) if should_return: logger.warning('capi.auth has been disabled via killswitch. Returning.') self.status['text'] = 'CAPI auth disabled by killswitch' @@ -1093,7 +1093,7 @@ class AppWindow(object): :param event: Tk generated event details. """ logger.trace_if('capi.worker', 'Begin') - should_return, new_data = killswitch.check_killswitch('capi.fleetcarrier', {}) + should_return, __ = killswitch.check_killswitch('capi.request.fleetcarrier', {}) if should_return: logger.warning('capi.fleetcarrier has been disabled via killswitch. Returning.') self.status['text'] = 'CAPI fleetcarrier disabled by killswitch' @@ -1106,12 +1106,6 @@ class AppWindow(object): self.status['text'] = _('CAPI query aborted: Cmdr name unknown') return - if not monitor.mode: - logger.trace_if('capi.worker', 'Aborting Query: Game Mode unknown') - # LANG: CAPI queries aborted because game mode unknown - self.status['text'] = _('CAPI query aborted: Game mode unknown') - return - if monitor.state['GameVersion'] is None: logger.trace_if('capi.worker', 'Aborting Query: GameVersion unknown') # LANG: CAPI queries aborted because GameVersion unknown @@ -1120,6 +1114,7 @@ class AppWindow(object): 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 @@ -1173,7 +1168,7 @@ class AppWindow(object): if __debug__: # Recording companion.session.dump_capi_data(capi_response.capi_data) - err = plug.notify_capi_fleetcarrierdata(capi_response.capi_data, monitor.is_beta) + err = plug.notify_capi_fleetcarrierdata(capi_response.capi_data) self.status['text'] = err and err or '' if err: play_bad = True @@ -1306,7 +1301,7 @@ class AppWindow(object): if err: play_bad = True - should_return, new_data = killswitch.check_killswitch('capi.request./market', {}) + should_return, __ = killswitch.check_killswitch('capi.request./market', {}) if should_return: logger.warning("capi.request./market has been disabled by killswitch. Returning.") @@ -1561,12 +1556,12 @@ class AppWindow(object): auto_update = True if auto_update: - should_return, new_data = killswitch.check_killswitch('capi.auth', {}) + should_return, __ = 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', 'CarrierTradeOrder']: # 'CargoTransfer' too? - should_return, new_data = killswitch.check_killswitch('capi.fleetcarrier', {}) + if entry['event'] in ('CarrierBuy', 'CarrierStats'): + should_return, __ = killswitch.check_killswitch('capi.request.fleetcarrier', {}) if not should_return: self.w.after(int(SERVER_RETRY * 1000), self.capi_request_fleetcarrier_data) diff --git a/PLUGINS.md b/PLUGINS.md index f768b7aa..3bb6f2ee 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -941,12 +941,12 @@ 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 | -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`, `CarrierStats` or `CarrierTradeOrder` 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). +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, is_beta): +def capi_fleetcarrier(data): """ We have new data on our Fleet Carrier """ @@ -969,7 +969,6 @@ def capi_fleetcarrier(data, is_beta): | Parameter | Type | Description | | :-------- | :--------------: | :------------------------------------------------------------------------------------------------------- | | `data` | `CAPIData` | `/fleetcarrier` API response | -| `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 diff --git a/companion.py b/companion.py index 26f46287..70b7e1cc 100644 --- a/companion.py +++ b/companion.py @@ -48,6 +48,7 @@ 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 @@ -960,7 +961,8 @@ class Session(object): 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) + 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) diff --git a/plug.py b/plug.py index 9b68082c..d77c5fa9 100644 --- a/plug.py +++ b/plug.py @@ -402,23 +402,21 @@ def notify_capidata( def notify_capi_fleetcarrierdata( - data: companion.CAPIData, - is_beta: bool + data: companion.CAPIData ) -> Optional[str]: """ Send the latest CAPI Fleetcarrier data from the FD servers to each plugin. - :param data: - :param is_beta: whether the player is in a Beta universe. + :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_data = plugin._get_func('capi_fleetcarrier') - - if fc_data: + fc_callback = plugin._get_func('capi_fleetcarrier') + if fc_callback is not None and callable(fc_callback): try: - newerror = fc_data(data, is_beta) + # Pass a copy of the CAPIData in case the callee modifies it + newerror = fc_callback(copy.deepcopy(data)) error = error or newerror except Exception: From 3c0d7d1c0a105206f214a24b89f283b1862a8079 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:00:59 +0000 Subject: [PATCH 061/257] build(deps-dev): bump isort from 5.11.3 to 5.11.4 Bumps [isort](https://github.com/pycqa/isort) from 5.11.3 to 5.11.4. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.11.3...5.11.4) --- updated-dependencies: - dependency-name: isort dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index e0098f88..94b941b3 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -13,7 +13,7 @@ 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.3 +isort==5.11.4 flake8-isort==5.0.3 flake8-json==21.7.0 flake8-noqa==1.3.0 From 62b0a392bd2c65b15de8ba5c5d0ade15f9b01020 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:01:04 +0000 Subject: [PATCH 062/257] build(deps-dev): bump coverage-conditional-plugin from 0.7.0 to 0.8.0 Bumps [coverage-conditional-plugin](https://github.com/wemake-services/coverage-conditional-plugin) from 0.7.0 to 0.8.0. - [Release notes](https://github.com/wemake-services/coverage-conditional-plugin/releases) - [Changelog](https://github.com/wemake-services/coverage-conditional-plugin/blob/master/CHANGELOG.md) - [Commits](https://github.com/wemake-services/coverage-conditional-plugin/compare/0.7.0...0.8.0) --- updated-dependencies: - dependency-name: coverage-conditional-plugin dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index e0098f88..de633c6a 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -46,7 +46,7 @@ py2exe==0.13.0.0; sys_platform == 'win32' pytest==7.2.0 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-conditional-plugin==0.8.0 # For manipulating folder permissions and the like. pywin32==305; sys_platform == 'win32' From 70a9609ef0e56f149c0ea079c83618e1d4090a0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:01:12 +0000 Subject: [PATCH 063/257] build(deps-dev): bump types-requests from 2.28.11.6 to 2.28.11.7 Bumps [types-requests](https://github.com/python/typeshed) from 2.28.11.6 to 2.28.11.7. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index e0098f88..00bb8867 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -23,7 +23,7 @@ flake8-use-fstring==1.4 mypy==0.991 pep8-naming==0.13.3 safety==2.3.5 -types-requests==2.28.11.6 +types-requests==2.28.11.7 # Code formatting tools autopep8==2.0.1 From 07474304cfedfd5e70d8a3649da26710f7d7267c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:35:52 +0000 Subject: [PATCH 064/257] build(deps-dev): bump coverage[toml] from 6.5.0 to 7.0.0 Bumps [coverage[toml]](https://github.com/nedbat/coveragepy) from 6.5.0 to 7.0.0. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/6.5.0...7.0.0) --- updated-dependencies: - dependency-name: coverage[toml] dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 76958aaf..ceacac8e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -45,7 +45,7 @@ py2exe==0.13.0.0; sys_platform == 'win32' # Testing pytest==7.2.0 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[toml]==7.0.0 # 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' From 3e295db06149686571740ced6459f71d643a22a6 Mon Sep 17 00:00:00 2001 From: aussig Date: Thu, 22 Dec 2022 17:39:20 +0000 Subject: [PATCH 065/257] Typing of return values from killswitch.check_killswitch() --- EDMarketConnector.py | 29 ++++++++++++++++++++++------- companion.py | 11 ++++++++++- plugins/eddb.py | 5 ++++- plugins/eddn.py | 15 +++++++++++++++ plugins/edsm.py | 11 ++++++++++- plugins/inara.py | 5 +++++ 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index f2d6ac4d..4cabfa94 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -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, Dict, 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 @@ -916,7 +916,10 @@ class AppWindow(object): def login(self): """Initiate CAPI/Frontier login and set other necessary state.""" - should_return, __ = killswitch.check_killswitch('capi.auth', {}) + 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.') self.status['text'] = 'CAPI auth disabled by killswitch' @@ -1007,7 +1010,10 @@ class AppWindow(object): :param event: Tk generated event details. """ logger.trace_if('capi.worker', 'Begin') - should_return, __ = killswitch.check_killswitch('capi.auth', {}) + 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.') self.status['text'] = 'CAPI auth disabled by killswitch' @@ -1093,7 +1099,10 @@ class AppWindow(object): :param event: Tk generated event details. """ logger.trace_if('capi.worker', 'Begin') - should_return, __ = killswitch.check_killswitch('capi.request.fleetcarrier', {}) + 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.') self.status['text'] = 'CAPI fleetcarrier disabled by killswitch' @@ -1301,7 +1310,10 @@ class AppWindow(object): if err: play_bad = True - should_return, __ = killswitch.check_killswitch('capi.request./market', {}) + 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.") @@ -1555,13 +1567,16 @@ 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: - should_return, __ = killswitch.check_killswitch('capi.auth', {}) + 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'): - should_return, __ = killswitch.check_killswitch('capi.request.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) diff --git a/companion.py b/companion.py index 70b7e1cc..e81e4b39 100644 --- a/companion.py +++ b/companion.py @@ -328,6 +328,9 @@ 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.') @@ -667,6 +670,9 @@ 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.') @@ -785,6 +791,9 @@ class Session(object): :return: The resulting CAPI data, of type 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.") @@ -962,7 +971,7 @@ class Session(object): 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) + timeout=capi_fleetcarrier_requests_timeout) else: capi_data = capi_single_query(query.capi_host, self.FRONTIER_CAPI_PATH_PROFILE) diff --git a/plugins/eddb.py b/plugins/eddb.py index e050df32..55ba4be3 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -42,7 +42,7 @@ # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# import tkinter -from typing import TYPE_CHECKING, Any, Mapping, MutableMapping, Optional +from typing import TYPE_CHECKING, Any, Dict, Mapping, MutableMapping, Optional import requests @@ -168,6 +168,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 diff --git a/plugins/eddn.py b/plugins/eddn.py index b1df07b7..cecdd0e0 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -402,6 +402,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.') @@ -635,6 +638,9 @@ 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.") @@ -766,6 +772,9 @@ 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.") @@ -832,6 +841,9 @@ 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.") @@ -2164,6 +2176,9 @@ def journal_entry( # noqa: C901, CCR001 :param state: `dict` - Current `monitor.state` data. :return: `str` - Error message, or `None` if no errors. """ + should_return: bool + new_data: Dict[str, Any] = {} + should_return, new_data = killswitch.check_killswitch('plugins.eddn.journal', entry) if should_return: plug.show_error(_('EDDN journal handler disabled. See Log.')) # LANG: Killswitch disabled EDDN diff --git a/plugins/edsm.py b/plugins/edsm.py index 130a794d..4c6ba02b 100644 --- a/plugins/edsm.py +++ b/plugins/edsm.py @@ -38,7 +38,7 @@ 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 typing import TYPE_CHECKING, Any, Dict, List, Literal, Mapping, MutableMapping, Optional, Set, Tuple, Union, cast import requests @@ -479,6 +479,9 @@ def journal_entry( # noqa: C901, 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.edsm.journal', entry, logger) if should_return: # LANG: EDSM plugin - Journal handling disabled by killswitch @@ -759,6 +762,9 @@ def worker() -> None: # noqa: CCR001 C901 # Cant be broken up currently retrying = 0 while retrying < 3: + should_skip: bool + new_item: Dict[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]], ("", {})), @@ -795,6 +801,9 @@ def worker() -> None: # noqa: CCR001 C901 # Cant be broken up currently # drop events if required by killswitch new_pending = [] for e in pending: + skip: bool + new: Dict[str, Any] = {} + skip, new = killswitch.check_killswitch(f'plugin.edsm.worker.{e["event"]}', e, logger) if skip: continue diff --git a/plugins/inara.py b/plugins/inara.py index f3f32741..163fdcb7 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -385,6 +385,9 @@ def journal_entry( # noqa: C901, CCR001 return '' + 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 @@ -1536,6 +1539,8 @@ 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 = [] + bad: bool + new_event: Dict[str, Any] = {} for e in event_list: bad, new_event = killswitch.check_killswitch(f'plugins.inara.worker.{e.name}', e.data, logger) From 7e726e606a81f9672b73b70f88e87b26318fc1e2 Mon Sep 17 00:00:00 2001 From: aussig Date: Fri, 23 Dec 2022 12:47:35 +0000 Subject: [PATCH 066/257] Store original request cmdr name in 'request_cmdr' in CAPIData --- PLUGINS.md | 99 +++++++++++++++++++++++++++------------------------- companion.py | 17 ++++++--- 2 files changed, 64 insertions(+), 52 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index 3bb6f2ee..0deff4f5 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -31,7 +31,7 @@ then you'll need to be using an appropriate version of Python. The current version is listed in the [Environment section of Releasing.md](https://github.com/EDCD/EDMarketConnector/blob/main/docs/Releasing.md#environment). If you're developing your plugin simply against an install of EDMarketConnector -then you'll be relying on the bundled version of Python (it's baked +then you'll be relying on the bundled version of Python (it's baked into the .exe via the py2exe build process). Please be sure to read the [Avoiding potential pitfalls](#avoiding-potential-pitfalls) @@ -40,21 +40,21 @@ EDMarketConnector code including whole application crashes. ## Being aware of core application changes -It is highly advisable to ensure you are aware of all EDMarketConnector -releases, including the pre-releases. The -beta and -rc changelogs will +It is highly advisable to ensure you are aware of all EDMarketConnector +releases, including the pre-releases. The -beta and -rc changelogs will contain valuable information about any forthcoming changes that affect plugins. The easiest way is: 1. Login to [GitHub](https://github.com). 2. Navigate to [EDMarketConnector](https://github.com/EDCD/EDMarketConnector). - 3. Click the 'Watch' (or 'Unwatch' if you previously set up any watches on - us). It's currently (2021-05-13) the left-most button of 3 near the + 3. Click the 'Watch' (or 'Unwatch' if you previously set up any watches on + us). It's currently (2021-05-13) the left-most button of 3 near the top-right of the page. 4. Click 'Custom'. 5. Ensure 'Releases' is selected. 6. Click 'Apply'. -And, of course, either ensure you check your GitHub messages regularly, or +And, of course, either ensure you check your GitHub messages regularly, or have it set up to email you such notifications. You should also keep an eye on [our GitHub Discussions](https://github.com/EDCD/EDMarketConnector/discussions) @@ -113,13 +113,13 @@ from the original files unless specified as allowed in this section. Use `monitor.game_running()` as follows in case a plugin needs to know if we think the game is running. *NB: This is a function, and should be called as such. Using the bare word `game_running` will always be `True`.* - + ``` from monitor import monitor ... if monitor.game_running(): ... -``` +``` `import timeout_session` - provides a method called `new_session` that creates a requests.session with a default timeout on all requests. Recommended to @@ -128,7 +128,7 @@ reduce noise in HTTP requests `from ttkHyperlinkLabel import HyperlinkLabel` and `import myNotebook as nb` - For creating UI elements. -In addition to the above we also explicitly package the following python +In addition to the above we also explicitly package the following python modules for plugin use: - shutil @@ -245,7 +245,7 @@ include variables, and even the returns of functions, in the output. ## Checking core EDMC version -If you have code that needs to act differently under different versions of +If you have code that needs to act differently under different versions of this application then you can check utilise `config.appversion`. Prior to version 5.0.0 this was a simple string. From 5.0.0 onwards it is, @@ -306,7 +306,7 @@ Mac, and `$TMP/EDMarketConnector.log` on Linux. ## Avoiding potential pitfalls -There are a number of things that your code should either do or avoiding +There are a number of things that your code should either do or avoiding doing so as to play nicely with the core EDMarketConnector code and not risk causing application crashes or hangs. @@ -317,12 +317,12 @@ See the section on [packaging extra modules](#your-plugin-directory-name-must-be ### Use a thread for long-running code -By default, your plugin code will be running in the main thread. So, if you -perform some operation that takes significant time (more than a second) you -will be blocking both the core code from continuing *and* any other plugins +By default, your plugin code will be running in the main thread. So, if you +perform some operation that takes significant time (more than a second) you +will be blocking both the core code from continuing *and* any other plugins from running their main-thread code. -This includes any connections to remote services, such as a website or +This includes any connections to remote services, such as a website or remote database. So please place such code within its own thread. See the [EDSM plugin](https://github.com/EDCD/EDMarketConnector/blob/main/plugins/edsm.py) @@ -331,20 +331,20 @@ with a queue to send data, and telling the sub-thread to stop during shutdown. ### All tkinter calls in main thread -The only tkinter calls that should ever be made from a sub-thread are +The only tkinter calls that should ever be made from a sub-thread are `event_generate()` calls to send data back to the main thread. -Any attempt to manipulate tkinter UI elements directly from a sub-thread +Any attempt to manipulate tkinter UI elements directly from a sub-thread will most likely crash the whole program. See the [EDSM plugin](https://github.com/EDCD/EDMarketConnector/blob/main/plugins/edsm.py) -code for an example of using `event_generate()` to cause the plugin main -thread code to update a UI element. Start from the `plugin_app()` +code for an example of using `event_generate()` to cause the plugin main +thread code to update a UI element. Start from the `plugin_app()` implementation. ### Do not call tkinter `event_generate` during shutdown. -However, you must **not** make *any* tkinter `event_generate()` call whilst +However, you must **not** make *any* tkinter `event_generate()` call whilst the application is shutting down. The application shutdown sequence is itself triggered from the `<>` event @@ -352,8 +352,8 @@ handler, and generating another event from any code in, or called from, there causes the application to hang somewhere in the tk libraries. You can detect if the application is shutting down with the boolean -`config.shutting_down`. Note that although this is technically a function -its implementation is of a property on `config.AbstractConfig` and thus you +`config.shutting_down`. Note that although this is technically a function +its implementation is of a property on `config.AbstractConfig` and thus you should treat it as a variable. **Do NOT use**: @@ -365,7 +365,7 @@ should treat it as a variable. # During shutdown ``` -as this will cause the 'During shutdown' branch to *always* be taken, as in +as this will cause the 'During shutdown' branch to *always* be taken, as in this context you're testing if the function exists, and that is always True. So instead use: @@ -396,8 +396,8 @@ your plugin's settings in a platform-independent way. Previously this was done with a single set and two get methods, the new methods provide better type safety. -If you want to maintain compatibility with pre-5.0.0 versions of this -application (please encourage plugin users to update!) then you'll need to +If you want to maintain compatibility with pre-5.0.0 versions of this +application (please encourage plugin users to update!) then you'll need to include this code in at least once in your plugin (no harm in putting it in all modules/files): @@ -670,8 +670,8 @@ cause `state['NavRoute'] = None`, but if you open the galaxy map in-game and cause an automatic re-plot of last route, then a new `NavRoute` event will also be generated and passed to plugins. -[2] - Some data from the CAPI is sometimes returned as a `list` (when all -members are present) and other times as an integer-keyed `dict` (when at +[2] - Some data from the CAPI is sometimes returned as a `list` (when all +members are present) and other times as an integer-keyed `dict` (when at 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. @@ -697,7 +697,7 @@ Journal `ModuleInfo` event. `OnFoot` is an indication as to if the player is on-foot, rather than in a vehicle. -`Component`, `Item`, `Consumable` & `Data` are `dict`s tracking your +`Component`, `Item`, `Consumable` & `Data` are `dict`s tracking your Odyssey MicroResources in your Ship Locker. `BacKPack` contains `dict`s for the same when you're on-foot. @@ -706,10 +706,10 @@ relating to suits and their loadouts. New in version 5.0.1: -`Odyssey` boolean based on the presence of such a flag in the `LoadGame` +`Odyssey` boolean based on the presence of such a flag in the `LoadGame` event. Defaults to `False`, i.e. if no such key in the event. -The previously undocumented `Horizons` boolean is similarly from `LoadGame`, +The previously undocumented `Horizons` boolean is similarly from `LoadGame`, but blindly retrieves the value rather than having a strict default. There'd be an exception if it wasn't there, and the value would be `None`. Note that this is **NOT** the same as the return from @@ -786,8 +786,8 @@ react to either in your plugin code then either compare in a case insensitive manner or check for both. The difference in case allows you to differentiate between the two scenarios. -**NB: Any of these events are passing to `journal_entry_cqc` rather than to -`journal_entry` if player has loaded into Arena (CQC).** +**NB: Any of these events are passing to `journal_entry_cqc` rather than to +`journal_entry` if player has loaded into Arena (CQC).** This event is not sent when EDMarketConnector is running on a different machine so you should not *rely* on receiving this event. @@ -804,15 +804,15 @@ Examples of this are: 1. Every `NavRoute` event contains the full `Route` array as loaded from `NavRoute.json`. - + *NB: There is no indication available when a player cancels a route.* The game itself does not provide any such, not in a Journal event, not in a `Status.json` flag. - + The Journal documentation v28 is incorrect about the event and file being `Route(.json)` the word is `NavRoute`. Also the format of the data is, e.g. - + ```json { "timestamp":"2021-03-10T11:31:37Z", "event":"NavRoute", @@ -826,9 +826,9 @@ Examples of this are: ``` 1. Every `ModuleInfo` event contains the full data as loaded from the - `ModulesInfo.json` file. Note that we use the singular form here to + `ModulesInfo.json` file. Note that we use the singular form here to stay consistent with the Journal event name. - + --- ### Journal entry in CQC @@ -888,7 +888,7 @@ def dashboard_entry(cmdr: str, is_beta: bool, entry: Dict[str, Any]): sys.stderr.write("Hardpoints {}\n".format(is_deployed and "deployed" or "stowed")) ``` -`dashboard_entry()` is called with the latest data from the `Status.json` +`dashboard_entry()` is called with the latest data from the `Status.json` file when an update to that file is detected. This will be when something on the player's cockpit display changes - @@ -983,7 +983,12 @@ services are available then the `lastStarport` key's value will have been augmented with `/market` and/or `/shipyard` data. **But do not assume this will always be the case**. -In the `capi_fleetcarrier()` callback, the contents of `data` will be the unmodified response from the CAPI `/fleetcarrier` query. 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. +In the `capi_fleetcarrier()` callback, the contents of `data` will be the response from the CAPI `/fleetcarrier` query. 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. + +In all cases, `data` will include a `request_cmdr` entry, which will be 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. 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 @@ -1197,11 +1202,11 @@ Any modules the core application code uses will naturally be packaged, and we explicitly include a small number of additional modules for the use of plugins. -Whilst we would like to make all of the `stdlib` of Python available it is -not automatically packaged into our releases by py2exe. We hope to address -this in the 5.3 release series. In the meantime, if there's anything -missing that you'd like to use, please ask. Yes, this very much means you -need to test your plugins against a Windows installation of the application +Whilst we would like to make all of the `stdlib` of Python available it is +not automatically packaged into our releases by py2exe. We hope to address +this in the 5.3 release series. In the meantime, if there's anything +missing that you'd like to use, please ask. Yes, this very much means you +need to test your plugins against a Windows installation of the application to be sure it will work. See @@ -1351,7 +1356,7 @@ versions of EDMarketConnector: [2to3](https://docs.python.org/3/library/2to3.html) tool can automate much of this work. -We advise *against* making any attempt to have a plugin's code work under -both Python 2.7 and 3.x. We no longer maintain the Python 2.7-based -versions of this application, and you shouldn't support use of them with +We advise *against* making any attempt to have a plugin's code work under +both Python 2.7 and 3.x. We no longer maintain the Python 2.7-based +versions of this application, and you shouldn't support use of them with your plugin. diff --git a/companion.py b/companion.py index e81e4b39..fe12ecde 100644 --- a/companion.py +++ b/companion.py @@ -575,7 +575,8 @@ class EDMCCAPIRequest(EDMCCAPIReturn): self, capi_host: str, endpoint: str, query_time: int, tk_response_event: Optional[str] = None, - play_sound: bool = False, auto_update: bool = False + play_sound: bool = False, auto_update: bool = False, + cmdr: Optional[str] = None ): super().__init__( query_time=query_time, tk_response_event=tk_response_event, @@ -583,6 +584,7 @@ class EDMCCAPIRequest(EDMCCAPIReturn): ) self.capi_host: str = capi_host # The CAPI host to use. self.endpoint: str = endpoint # The CAPI query to perform. + self.cmdr: Optional[str] = cmdr # The CMDR name used for the request. class EDMCCAPIResponse(EDMCCAPIReturn): @@ -590,10 +592,12 @@ class EDMCCAPIResponse(EDMCCAPIReturn): def __init__( self, capi_data: CAPIData, - query_time: int, play_sound: bool = False, auto_update: bool = False + query_time: int, play_sound: bool = False, auto_update: bool = False, + cmdr: Optional[str] = None ): super().__init__(query_time=query_time, play_sound=play_sound, auto_update=auto_update) self.capi_data: CAPIData = capi_data # Frontier CAPI response, possibly augmented (station query) + self.capi_data['request_cmdr'] = cmdr # Inject the CMDR name used for the original request into the data class EDMCCAPIFailedRequest(EDMCCAPIReturn): @@ -993,7 +997,8 @@ class Session(object): capi_data=capi_data, query_time=query.query_time, play_sound=query.play_sound, - auto_update=query.auto_update + auto_update=query.auto_update, + cmdr=query.cmdr ) ) @@ -1041,7 +1046,8 @@ class Session(object): tk_response_event=tk_response_event, query_time=query_time, play_sound=play_sound, - auto_update=auto_update + auto_update=auto_update, + cmdr=monitor.cmdr ) ) @@ -1070,7 +1076,8 @@ class Session(object): tk_response_event=tk_response_event, query_time=query_time, play_sound=play_sound, - auto_update=auto_update + auto_update=auto_update, + cmdr=monitor.cmdr ) ) ###################################################################### From 3c8eca16afd25d432f697ffd9edafeab4babfe46 Mon Sep 17 00:00:00 2001 From: aussig Date: Fri, 23 Dec 2022 13:01:47 +0000 Subject: [PATCH 067/257] Revert unnoticed whitespace modifications to PLUGINS.py --- PLUGINS.md | 97 ++++++++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index 0deff4f5..df6d011f 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -31,7 +31,7 @@ then you'll need to be using an appropriate version of Python. The current version is listed in the [Environment section of Releasing.md](https://github.com/EDCD/EDMarketConnector/blob/main/docs/Releasing.md#environment). If you're developing your plugin simply against an install of EDMarketConnector -then you'll be relying on the bundled version of Python (it's baked +then you'll be relying on the bundled version of Python (it's baked into the .exe via the py2exe build process). Please be sure to read the [Avoiding potential pitfalls](#avoiding-potential-pitfalls) @@ -40,21 +40,21 @@ EDMarketConnector code including whole application crashes. ## Being aware of core application changes -It is highly advisable to ensure you are aware of all EDMarketConnector -releases, including the pre-releases. The -beta and -rc changelogs will +It is highly advisable to ensure you are aware of all EDMarketConnector +releases, including the pre-releases. The -beta and -rc changelogs will contain valuable information about any forthcoming changes that affect plugins. The easiest way is: 1. Login to [GitHub](https://github.com). 2. Navigate to [EDMarketConnector](https://github.com/EDCD/EDMarketConnector). - 3. Click the 'Watch' (or 'Unwatch' if you previously set up any watches on - us). It's currently (2021-05-13) the left-most button of 3 near the + 3. Click the 'Watch' (or 'Unwatch' if you previously set up any watches on + us). It's currently (2021-05-13) the left-most button of 3 near the top-right of the page. 4. Click 'Custom'. 5. Ensure 'Releases' is selected. 6. Click 'Apply'. -And, of course, either ensure you check your GitHub messages regularly, or +And, of course, either ensure you check your GitHub messages regularly, or have it set up to email you such notifications. You should also keep an eye on [our GitHub Discussions](https://github.com/EDCD/EDMarketConnector/discussions) @@ -113,13 +113,13 @@ from the original files unless specified as allowed in this section. Use `monitor.game_running()` as follows in case a plugin needs to know if we think the game is running. *NB: This is a function, and should be called as such. Using the bare word `game_running` will always be `True`.* - + ``` from monitor import monitor ... if monitor.game_running(): ... -``` +``` `import timeout_session` - provides a method called `new_session` that creates a requests.session with a default timeout on all requests. Recommended to @@ -128,7 +128,7 @@ reduce noise in HTTP requests `from ttkHyperlinkLabel import HyperlinkLabel` and `import myNotebook as nb` - For creating UI elements. -In addition to the above we also explicitly package the following python +In addition to the above we also explicitly package the following python modules for plugin use: - shutil @@ -245,7 +245,7 @@ include variables, and even the returns of functions, in the output. ## Checking core EDMC version -If you have code that needs to act differently under different versions of +If you have code that needs to act differently under different versions of this application then you can check utilise `config.appversion`. Prior to version 5.0.0 this was a simple string. From 5.0.0 onwards it is, @@ -306,7 +306,7 @@ Mac, and `$TMP/EDMarketConnector.log` on Linux. ## Avoiding potential pitfalls -There are a number of things that your code should either do or avoiding +There are a number of things that your code should either do or avoiding doing so as to play nicely with the core EDMarketConnector code and not risk causing application crashes or hangs. @@ -317,12 +317,12 @@ See the section on [packaging extra modules](#your-plugin-directory-name-must-be ### Use a thread for long-running code -By default, your plugin code will be running in the main thread. So, if you -perform some operation that takes significant time (more than a second) you -will be blocking both the core code from continuing *and* any other plugins +By default, your plugin code will be running in the main thread. So, if you +perform some operation that takes significant time (more than a second) you +will be blocking both the core code from continuing *and* any other plugins from running their main-thread code. -This includes any connections to remote services, such as a website or +This includes any connections to remote services, such as a website or remote database. So please place such code within its own thread. See the [EDSM plugin](https://github.com/EDCD/EDMarketConnector/blob/main/plugins/edsm.py) @@ -331,20 +331,20 @@ with a queue to send data, and telling the sub-thread to stop during shutdown. ### All tkinter calls in main thread -The only tkinter calls that should ever be made from a sub-thread are +The only tkinter calls that should ever be made from a sub-thread are `event_generate()` calls to send data back to the main thread. -Any attempt to manipulate tkinter UI elements directly from a sub-thread +Any attempt to manipulate tkinter UI elements directly from a sub-thread will most likely crash the whole program. See the [EDSM plugin](https://github.com/EDCD/EDMarketConnector/blob/main/plugins/edsm.py) -code for an example of using `event_generate()` to cause the plugin main -thread code to update a UI element. Start from the `plugin_app()` +code for an example of using `event_generate()` to cause the plugin main +thread code to update a UI element. Start from the `plugin_app()` implementation. ### Do not call tkinter `event_generate` during shutdown. -However, you must **not** make *any* tkinter `event_generate()` call whilst +However, you must **not** make *any* tkinter `event_generate()` call whilst the application is shutting down. The application shutdown sequence is itself triggered from the `<>` event @@ -352,8 +352,8 @@ handler, and generating another event from any code in, or called from, there causes the application to hang somewhere in the tk libraries. You can detect if the application is shutting down with the boolean -`config.shutting_down`. Note that although this is technically a function -its implementation is of a property on `config.AbstractConfig` and thus you +`config.shutting_down`. Note that although this is technically a function +its implementation is of a property on `config.AbstractConfig` and thus you should treat it as a variable. **Do NOT use**: @@ -365,7 +365,7 @@ should treat it as a variable. # During shutdown ``` -as this will cause the 'During shutdown' branch to *always* be taken, as in +as this will cause the 'During shutdown' branch to *always* be taken, as in this context you're testing if the function exists, and that is always True. So instead use: @@ -396,8 +396,8 @@ your plugin's settings in a platform-independent way. Previously this was done with a single set and two get methods, the new methods provide better type safety. -If you want to maintain compatibility with pre-5.0.0 versions of this -application (please encourage plugin users to update!) then you'll need to +If you want to maintain compatibility with pre-5.0.0 versions of this +application (please encourage plugin users to update!) then you'll need to include this code in at least once in your plugin (no harm in putting it in all modules/files): @@ -670,8 +670,8 @@ cause `state['NavRoute'] = None`, but if you open the galaxy map in-game and cause an automatic re-plot of last route, then a new `NavRoute` event will also be generated and passed to plugins. -[2] - Some data from the CAPI is sometimes returned as a `list` (when all -members are present) and other times as an integer-keyed `dict` (when at +[2] - Some data from the CAPI is sometimes returned as a `list` (when all +members are present) and other times as an integer-keyed `dict` (when at 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. @@ -697,7 +697,7 @@ Journal `ModuleInfo` event. `OnFoot` is an indication as to if the player is on-foot, rather than in a vehicle. -`Component`, `Item`, `Consumable` & `Data` are `dict`s tracking your +`Component`, `Item`, `Consumable` & `Data` are `dict`s tracking your Odyssey MicroResources in your Ship Locker. `BacKPack` contains `dict`s for the same when you're on-foot. @@ -706,10 +706,10 @@ relating to suits and their loadouts. New in version 5.0.1: -`Odyssey` boolean based on the presence of such a flag in the `LoadGame` +`Odyssey` boolean based on the presence of such a flag in the `LoadGame` event. Defaults to `False`, i.e. if no such key in the event. -The previously undocumented `Horizons` boolean is similarly from `LoadGame`, +The previously undocumented `Horizons` boolean is similarly from `LoadGame`, but blindly retrieves the value rather than having a strict default. There'd be an exception if it wasn't there, and the value would be `None`. Note that this is **NOT** the same as the return from @@ -786,8 +786,8 @@ react to either in your plugin code then either compare in a case insensitive manner or check for both. The difference in case allows you to differentiate between the two scenarios. -**NB: Any of these events are passing to `journal_entry_cqc` rather than to -`journal_entry` if player has loaded into Arena (CQC).** +**NB: Any of these events are passing to `journal_entry_cqc` rather than to +`journal_entry` if player has loaded into Arena (CQC).** This event is not sent when EDMarketConnector is running on a different machine so you should not *rely* on receiving this event. @@ -804,15 +804,15 @@ Examples of this are: 1. Every `NavRoute` event contains the full `Route` array as loaded from `NavRoute.json`. - + *NB: There is no indication available when a player cancels a route.* The game itself does not provide any such, not in a Journal event, not in a `Status.json` flag. - + The Journal documentation v28 is incorrect about the event and file being `Route(.json)` the word is `NavRoute`. Also the format of the data is, e.g. - + ```json { "timestamp":"2021-03-10T11:31:37Z", "event":"NavRoute", @@ -826,9 +826,9 @@ Examples of this are: ``` 1. Every `ModuleInfo` event contains the full data as loaded from the - `ModulesInfo.json` file. Note that we use the singular form here to + `ModulesInfo.json` file. Note that we use the singular form here to stay consistent with the Journal event name. - + --- ### Journal entry in CQC @@ -888,7 +888,7 @@ def dashboard_entry(cmdr: str, is_beta: bool, entry: Dict[str, Any]): sys.stderr.write("Hardpoints {}\n".format(is_deployed and "deployed" or "stowed")) ``` -`dashboard_entry()` is called with the latest data from the `Status.json` +`dashboard_entry()` is called with the latest data from the `Status.json` file when an update to that file is detected. This will be when something on the player's cockpit display changes - @@ -985,10 +985,7 @@ will always be the case**. In the `capi_fleetcarrier()` callback, the contents of `data` will be the response from the CAPI `/fleetcarrier` query. 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. -In all cases, `data` will include a `request_cmdr` entry, which will be 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. +In all cases, `data` will include a `request_cmdr` entry, which will be 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. 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 @@ -1202,11 +1199,11 @@ Any modules the core application code uses will naturally be packaged, and we explicitly include a small number of additional modules for the use of plugins. -Whilst we would like to make all of the `stdlib` of Python available it is -not automatically packaged into our releases by py2exe. We hope to address -this in the 5.3 release series. In the meantime, if there's anything -missing that you'd like to use, please ask. Yes, this very much means you -need to test your plugins against a Windows installation of the application +Whilst we would like to make all of the `stdlib` of Python available it is +not automatically packaged into our releases by py2exe. We hope to address +this in the 5.3 release series. In the meantime, if there's anything +missing that you'd like to use, please ask. Yes, this very much means you +need to test your plugins against a Windows installation of the application to be sure it will work. See @@ -1356,7 +1353,7 @@ versions of EDMarketConnector: [2to3](https://docs.python.org/3/library/2to3.html) tool can automate much of this work. -We advise *against* making any attempt to have a plugin's code work under -both Python 2.7 and 3.x. We no longer maintain the Python 2.7-based -versions of this application, and you shouldn't support use of them with +We advise *against* making any attempt to have a plugin's code work under +both Python 2.7 and 3.x. We no longer maintain the Python 2.7-based +versions of this application, and you shouldn't support use of them with your plugin. From 204ded5b105084b867b9872a7b37441e1cbc03d6 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 08:56:34 +0000 Subject: [PATCH 068/257] pre-commit: Add types-urllib3 to additional_dependencies It's in `pip freeze | grep types`, so might as well be explicit. --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d841cda1..778c2161 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,7 +51,7 @@ repos: - id: mypy # verbose: true # log_file: 'pre-commit_mypy.log' - additional_dependencies: [ types-requests ] + additional_dependencies: [ types-requests, types-urllib3 ] # args: [ "--follow-imports", "skip", "--ignore-missing-imports", "--scripts-are-modules" ] ### # pydocstyle.exe From 48763890fe651b7c68f8f056e79fd51a7fd8eb78 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 08:57:31 +0000 Subject: [PATCH 069/257] config: Fix "could be None" types in __init__.py --- config/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/config/__init__.py b/config/__init__.py index b3b240ed..ffc635e3 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -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: Union[list, str, bool, int, None] = None + ) -> Union[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. From 61bdb54eb12bdc40439bc10bd323f4811359da9f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 09:08:03 +0000 Subject: [PATCH 070/257] .mypy.ini: Add `--explicit-package-bases` to help with pre-commit invocation --- .mypy.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/.mypy.ini b/.mypy.ini index 10ef53b7..d3a0d2e2 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -7,3 +7,4 @@ scripts_are_modules = True ; i.e. no typing info. check_untyped_defs = True ; platform = darwin +explicit_package_bases = True From 7440c9a064e8212aeffedd7eaadbd189eeebd403 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 09:08:31 +0000 Subject: [PATCH 071/257] Renamed coriolis.py so it'll never clash with plugins/coriolis.py --- coriolis.py => coriolis-update-files.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename coriolis.py => coriolis-update-files.py (100%) diff --git a/coriolis.py b/coriolis-update-files.py similarity index 100% rename from coriolis.py rename to coriolis-update-files.py From 5f4f524fec71daa0e23f73ac0f055ffbbf8c6217 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 09:10:52 +0000 Subject: [PATCH 072/257] And update reference to renamed coriolis.py in docs/Releasing.md --- docs/Releasing.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/Releasing.md b/docs/Releasing.md index 9840c694..7524ebbb 100644 --- a/docs/Releasing.md +++ b/docs/Releasing.md @@ -166,7 +166,7 @@ that it's actually included in the installer. ``` - + | None Note that you only need `Id=""` if the filename itself is not a valid Id, e.g. because it contains spaces. @@ -191,17 +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 +2. 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`. **NB: The - submodule might have been updated by a GitHub workflow/PR/merge, so - be sure to perform this step for every build.** - 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). + 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 From d76e827dc589414a1b63f3066f4b711b04b1ae55 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 11:27:45 +0000 Subject: [PATCH 073/257] config/windows: Fix up types --- config/windows.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/config/windows.py b/config/windows.py index d29a2b42..f7590a92 100644 --- a/config/windows.py +++ b/config/windows.py @@ -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) From 3ed84bcad81d5a6e54246410d103caa1c9ad5cc3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 11:30:52 +0000 Subject: [PATCH 074/257] examples/plugintest: Drop the 'pre-5.0.0' config fixups It's a pain for typing, and should be long since irrelevant. --- docs/examples/plugintest/load.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docs/examples/plugintest/load.py b/docs/examples/plugintest/load.py index 2639cfd9..314eef19 100644 --- a/docs/examples/plugintest/load.py +++ b/docs/examples/plugintest/load.py @@ -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__)) From 19f3df77f215e77691c163a5ab65bf70794a24b1 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 11:44:48 +0000 Subject: [PATCH 075/257] examples/click_counter: Types *should* be fixed up NB: Didn't run this at all to test. --- docs/examples/click_counter/load.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/examples/click_counter/load.py b/docs/examples/click_counter/load.py index 776e9d4b..b1ea6ac5 100644 --- a/docs/examples/click_counter/load.py +++ b/docs/examples/click_counter/load.py @@ -6,6 +6,7 @@ It adds a single button to the EDMC interface that displays the number of times import logging import tkinter as tk +import tkinter.ttk as ttk from typing import Optional import myNotebook as nb # noqa: N813 @@ -27,7 +28,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: @@ -48,7 +49,7 @@ class ClickCounter: """ self.on_preferences_closed("", False) # Save our prefs - def setup_preferences(self, parent: nb.Notebook, cmdr: str, is_beta: bool) -> Optional[tk.Frame]: + def setup_preferences(self, parent: ttk.Frame, cmdr: str, is_beta: bool) -> Optional[tk.Frame]: """ setup_preferences is called by plugin_prefs below. @@ -99,8 +100,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 @@ -127,7 +128,7 @@ def plugin_stop() -> None: return cc.on_unload() -def plugin_prefs(parent: nb.Notebook, cmdr: str, is_beta: bool) -> Optional[tk.Frame]: +def plugin_prefs(parent: ttk.Frame, cmdr: str, is_beta: bool) -> Optional[tk.Frame]: """ Handle preferences tab for the plugin. From acbe1231ef871a49b318ca60a6151240d731a5f1 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 12:05:19 +0000 Subject: [PATCH 076/257] EDMCLogging: loglevel is `str | int` --- EDMCLogging.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EDMCLogging.py b/EDMCLogging.py index 1bf83bc7..8bde0760 100644 --- a/EDMCLogging.py +++ b/EDMCLogging.py @@ -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. @@ -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 From 4db416567698a0d4cb9b5e57abd1524912f2ba6b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 12:09:34 +0000 Subject: [PATCH 077/257] config/linux: Fix `pre-commit run --all-files`-only issue When run this way mypy thinks `config.linux` has no attribute `LinuxConfig`. --- tests/config/test_config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/config/test_config.py b/tests/config/test_config.py index b6637623..ad6bbd6f 100644 --- a/tests/config/test_config.py +++ b/tests/config/test_config.py @@ -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) From d40bb4f09c4b46abe99b8a21a1b2563e9d594f44 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 12:11:22 +0000 Subject: [PATCH 078/257] dashboard: Minor `process()` type fix --- dashboard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dashboard.py b/dashboard.py index c371e2b7..c88f9a21 100644 --- a/dashboard.py +++ b/dashboard.py @@ -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. From f7cba59e61a2da418fe04c3c7b28d1d881b98fed Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:21:14 +0000 Subject: [PATCH 079/257] hotkey: Re-factor into a module, per-arch files This helps avoid some pre-commit/mypy carping. --- hotkey.py | 703 --------------------------------------------- hotkey/__init__.py | 59 ++++ hotkey/darwin.py | 274 ++++++++++++++++++ hotkey/linux.py | 29 ++ hotkey/windows.py | 359 +++++++++++++++++++++++ 5 files changed, 721 insertions(+), 703 deletions(-) delete mode 100644 hotkey.py create mode 100644 hotkey/__init__.py create mode 100644 hotkey/darwin.py create mode 100644 hotkey/linux.py create mode 100644 hotkey/windows.py diff --git a/hotkey.py b/hotkey.py deleted file mode 100644 index 5a72cde1..00000000 --- a/hotkey.py +++ /dev/null @@ -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('<>', 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('', 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 <>') - self.root.event_generate('<>', 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() diff --git a/hotkey/__init__.py b/hotkey/__init__.py new file mode 100644 index 00000000..782a16fa --- /dev/null +++ b/hotkey/__init__.py @@ -0,0 +1,59 @@ +"""Handle keyboard input for manual update triggering.""" +# -*- coding: utf-8 -*- + +import abc +import sys +from abc import abstractmethod + + +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 + + +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() diff --git a/hotkey/darwin.py b/hotkey/darwin.py new file mode 100644 index 00000000..9989b4f9 --- /dev/null +++ b/hotkey/darwin.py @@ -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 + +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, 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 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('<>', 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 + + 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('', 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() diff --git a/hotkey/linux.py b/hotkey/linux.py new file mode 100644 index 00000000..9a60515f --- /dev/null +++ b/hotkey/linux.py @@ -0,0 +1,29 @@ +"""Linux implementation of hotkey.AbstractHotkeyMgr.""" +from EDMCLogging import get_main_logger +from hotkey import AbstractHotkeyMgr + +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 play_good(self) -> None: + """Play the 'good' sound.""" + pass + + def play_bad(self) -> None: + """Play the 'bad' sound.""" + pass diff --git a/hotkey/windows.py b/hotkey/windows.py new file mode 100644 index 00000000..4dd110af --- /dev/null +++ b/hotkey/windows.py @@ -0,0 +1,359 @@ +"""Windows implementation of hotkey.AbstractHotkeyMgr.""" +import atexit +import ctypes +import pathlib +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 + +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: 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 <>') + self.root.event_generate('<>', 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) From a08eef32440378b6e50835f34f701d4649af8b88 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:24:01 +0000 Subject: [PATCH 080/257] flake8, hotkey/darwin: Just ignore this file for now It'll take digging into macOS-specific documents to type things sufficiently to pass the flake8 TAE001 "too few type annotations" check. --- .flake8 | 1 + hotkey/darwin.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.flake8 b/.flake8 index c8dc0cc6..7207bf81 100644 --- a/.flake8 +++ b/.flake8 @@ -8,6 +8,7 @@ exclude = venv/ .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 diff --git a/hotkey/darwin.py b/hotkey/darwin.py index 9989b4f9..102a73fa 100644 --- a/hotkey/darwin.py +++ b/hotkey/darwin.py @@ -56,7 +56,7 @@ class MacHotkeyMgr(AbstractHotkeyMgr): pathlib.Path(config.respath_path) / 'snd_bad.wav', False ) - def register(self, root: tk.Tk, keycode, modifiers) -> None: + def register(self, root: tk.Tk, keycode: int, modifiers: int) -> None: """ Register current hotkey for monitoring. From 85fc308d427b116cdb31546ec44ebe902d608a5c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:29:53 +0000 Subject: [PATCH 081/257] outfitting.py: Correct indexing into two maps The current data literally only uses strings as indexes. --- outfitting.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/outfitting.py b/outfitting.py index e59aa8d0..174e24b8 100644 --- a/outfitting.py +++ b/outfitting.py @@ -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]}"') From 36bd08d7150d5320aa3983e7175f550b72b3238e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:31:24 +0000 Subject: [PATCH 082/257] l10n.py: Two minor typing fixes --- l10n.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/l10n.py b/l10n.py index 83600383..e2c1143f 100755 --- a/l10n.py +++ b/l10n.py @@ -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 From 777b38e179e21265f7d530a0aa4f0b68c8bb12d8 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:32:52 +0000 Subject: [PATCH 083/257] theme.py: Minor typing fix --- theme.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/theme.py b/theme.py index e9ace26f..45886f16 100644 --- a/theme.py +++ b/theme.py @@ -131,7 +131,7 @@ 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 = [] From 4041890f391d9bcdc5ec9d3c81e7d445f85879a8 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:39:59 +0000 Subject: [PATCH 084/257] tests/config/_old_config.py: Minor typing fixes. --- tests/config/_old_config.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/config/_old_config.py b/tests/config/_old_config.py index b0952903..0226bc36 100644 --- a/tests/config/_old_config.py +++ b/tests/config/_old_config.py @@ -138,7 +138,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 +222,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 +376,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()}' From 872ab1b814630145d9d5952d5408180d1fe93892 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:43:51 +0000 Subject: [PATCH 085/257] hotkey/darwin: No need to sys.platform gate within this And it gets rid of a `pre-commit run --all-files mypy` error. --- hotkey/darwin.py | 175 +++++++++++++++++++++++------------------------ 1 file changed, 87 insertions(+), 88 deletions(-) diff --git a/hotkey/darwin.py b/hotkey/darwin.py index 102a73fa..a053a55f 100644 --- a/hotkey/darwin.py +++ b/hotkey/darwin.py @@ -153,117 +153,116 @@ class MacHotkeyMgr(AbstractHotkeyMgr): self.keycode = 0 self.modifiers = 0 - 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'): + @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 - 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_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_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 - 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('', keycode=self.acquire_key) + self.acquire_state = MacHotkeyMgr.ACQUIRE_ACTIVE + self.root.after(50, self._acquire_poll) - # 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('', 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. - 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 - :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 - # 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 - # 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) - return (keycode, modifiers) + def display(self, keycode, modifiers) -> str: + """ + Return displayable form of given hotkey + 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'⌃' - :param keycode: - :param modifiers: - :return: string form - """ - text = '' - if modifiers & NSControlKeyMask: - text += u'⌃' + if modifiers & NSAlternateKeyMask: + text += u'⌥' - if modifiers & NSAlternateKeyMask: - text += u'⌥' + if modifiers & NSShiftKeyMask: + text += u'⇧' - if modifiers & NSShiftKeyMask: - text += u'⇧' + if modifiers & NSCommandKeyMask: + text += u'⌘' - if modifiers & NSCommandKeyMask: - text += u'⌘' + if (modifiers & NSNumericPadKeyMask) and keycode <= 0x7f: + text += u'№' - if (modifiers & NSNumericPadKeyMask) and keycode <= 0x7f: - text += u'№' + if not keycode: + pass - if not keycode: - pass + elif ord(NSF1FunctionKey) <= keycode <= ord(NSF35FunctionKey): + text += f'F{keycode + 1 - ord(NSF1FunctionKey)}' - 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 in MacHotkeyMgr.DISPLAY: # specials - text += MacHotkeyMgr.DISPLAY[keycode] + elif keycode < 0x20: # control keys + text += chr(keycode + 0x40) - elif keycode < 0x20: # control keys - text += chr(keycode + 0x40) + elif keycode < 0xf700: # key char + text += chr(keycode).upper() - elif keycode < 0xf700: # key char - text += chr(keycode).upper() + else: + text += u'⁈' - else: - text += u'⁈' - - return text + return text def play_good(self): """Play the 'good' sound.""" From f52ffce79fa49575c4d467d4ef37d4cd25764c93 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:45:37 +0000 Subject: [PATCH 086/257] timeout_session: Minor typing fix --- timeout_session.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/timeout_session.py b/timeout_session.py index 6faf54bb..8a4656ce 100644 --- a/timeout_session.py +++ b/timeout_session.py @@ -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. From 25dfb0588a978a3bcbdcea1741ee3a9f82ced1f4 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:50:15 +0000 Subject: [PATCH 087/257] tests/journal_lock: Minor typing fixes. --- journal_lock.py | 2 +- tests/journal_lock.py/test_journal_lock.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/journal_lock.py b/journal_lock.py index b8882a51..7945ef91 100644 --- a/journal_lock.py +++ b/journal_lock.py @@ -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 diff --git a/tests/journal_lock.py/test_journal_lock.py b/tests/journal_lock.py/test_journal_lock.py index 72252e9f..7bfd4ea8 100644 --- a/tests/journal_lock.py/test_journal_lock.py +++ b/tests/journal_lock.py/test_journal_lock.py @@ -121,7 +121,7 @@ class TestJournalLock: tmp_path_factory: _pytest_tmpdir.TempPathFactory ) -> _pytest_tmpdir.TempPathFactory: """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()) @@ -140,7 +140,7 @@ class TestJournalLock: tmp_path_factory: _pytest_tmpdir.TempPathFactory ) -> _pytest_tmpdir.TempPathFactory: """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") From 9377bbf225e239eae156f08c238696f05d0423c0 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 13:58:23 +0000 Subject: [PATCH 088/257] edshipyard: Minor typing fix --- edshipyard.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edshipyard.py b/edshipyard.py index d709a2e1..1bfa77e6 100644 --- a/edshipyard.py +++ b/edshipyard.py @@ -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 From 7fe86c586212e12691aeef163cbb03ba27cafbe4 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 14:00:31 +0000 Subject: [PATCH 089/257] companion.py: Minor typing fixes --- companion.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/companion.py b/companion.py index 41fc3b7d..c89e6319 100644 --- a/companion.py +++ b/companion.py @@ -326,7 +326,7 @@ class Auth(object): """ logger.debug(f'Trying for "{self.cmdr}"') - should_return, new_data = killswitch.check_killswitch('capi.auth', {}) + should_return, _ = killswitch.check_killswitch('capi.auth', {}) if should_return: logger.warning('capi.auth has been disabled via killswitch. Returning.') return None @@ -663,7 +663,7 @@ class Session(object): :return: True if login succeeded, False if re-authorization initiated. """ - should_return, new_data = killswitch.check_killswitch('capi.auth', {}) + should_return, _ = killswitch.check_killswitch('capi.auth', {}) if should_return: logger.warning('capi.auth has been disabled via killswitch. Returning.') return False @@ -781,7 +781,7 @@ class Session(object): :return: The resulting CAPI data, of type CAPIData. """ capi_data: CAPIData = CAPIData() - should_return, new_data = killswitch.check_killswitch('capi.request.' + capi_endpoint, {}) + should_return, _ = 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 From 95b442cf028e90a9b9e2fc46ebf8ae0e88ee4b26 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 14:04:34 +0000 Subject: [PATCH 090/257] stats.py: Minor typing fixes. --- stats.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stats.py b/stats.py index 6886eb23..f7f15b86 100644 --- a/stats.py +++ b/stats.py @@ -442,7 +442,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 +464,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: Optional[str] = None) -> None: """ Add the column headers to the page, followed by a separator. @@ -478,7 +480,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: Optional[str] = None, with_copy: bool = False ): """ Add a single row to parent. From fb065c5b788fd865196cc2c00eff6fff67bf25e8 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 14:06:40 +0000 Subject: [PATCH 091/257] collate.py: file paths/names should be pathlib.Path --- collate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/collate.py b/collate.py index 3ab5224b..48007527 100755 --- a/collate.py +++ b/collate.py @@ -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') From 26b12f5b14a6ef14287141047424d58b3bcebcec Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 14:10:25 +0000 Subject: [PATCH 092/257] plugins/inara, plug.py: Minor typing fixes --- plug.py | 2 +- plugins/inara.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plug.py b/plug.py index deeb6ebe..01f2fc2c 100644 --- a/plug.py +++ b/plug.py @@ -198,7 +198,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: Tuple ) -> Optional[str]: """ Invoke a function on a named plugin. diff --git a/plugins/inara.py b/plugins/inara.py index f3f32741..3501727c 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -35,6 +35,7 @@ from typing import OrderedDict as OrderedDictT from typing import Sequence, Union, cast import requests +import ttk import edmc_data import killswitch @@ -130,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 @@ -235,7 +236,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.Frame, cmdr: str, is_beta: bool) -> tk.Frame: """Plugin Preferences UI hook.""" x_padding = 10 x_button_padding = 12 # indent Checkbuttons and Radiobuttons From 9e605d31c73d40b71750f93e6dcaf5237a944e5e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 14:22:06 +0000 Subject: [PATCH 093/257] EDMC.py: Fix up other call to companion.session.station() * Opening of latest journal file didn't match how done in monitor.py. This caused `str` instead of `bytes` being passed to `monitor.parse_entry()`. * It was assuming pre-threaded return of data. Now properly gets it from the queue. --- EDMC.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/EDMC.py b/EDMC.py index 4daf4af3..2a7d7cd4 100755 --- a/EDMC.py +++ b/EDMC.py @@ -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}') @@ -410,7 +413,23 @@ sys.path: {sys.path}''' # Retry for shipyard sleep(SERVER_RETRY) - new_data = companion.session.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.system and \ From 3b0c7370cc8804bb8d0dde544c7e1243b262373a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 14:43:51 +0000 Subject: [PATCH 094/257] hotkey: Make more of the windows methods abstract ones in parent Without this mypy objects to calling them due to not being in the visible AbstractKetkeyMgr type. --- hotkey/__init__.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/hotkey/__init__.py b/hotkey/__init__.py index 782a16fa..5162621c 100644 --- a/hotkey/__init__.py +++ b/hotkey/__init__.py @@ -4,6 +4,7 @@ import abc import sys from abc import abstractmethod +from typing import Optional, Tuple, Union class AbstractHotkeyMgr(abc.ABC): @@ -19,6 +20,41 @@ class AbstractHotkeyMgr(abc.ABC): """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.""" From f4b150960cbd4b8e5a748a167b90b1fc116e8dfe Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 14:50:05 +0000 Subject: [PATCH 095/257] prefs.py & related files: Fix up mypy type checking * Some trivial. * As myNotebook.py's class is based on `ttk.Notebook`, typing changed to that. --- EDMCLogging.py | 4 ++-- myNotebook.py | 2 +- plug.py | 8 +++++--- prefs.py | 19 +++++++++---------- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/EDMCLogging.py b/EDMCLogging.py index 8bde0760..e698b35b 100644 --- a/EDMCLogging.py +++ b/EDMCLogging.py @@ -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. diff --git a/myNotebook.py b/myNotebook.py index eb17bf2f..1989141f 100644 --- a/myNotebook.py +++ b/myNotebook.py @@ -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) diff --git a/plug.py b/plug.py index 01f2fc2c..68a2d26b 100644 --- a/plug.py +++ b/plug.py @@ -9,6 +9,8 @@ import tkinter as tk from builtins import object, str from typing import Any, Callable, List, Mapping, MutableMapping, Optional, Tuple +import ttk + import companion import myNotebook as nb # noqa: N813 from config import config @@ -118,7 +120,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. @@ -248,7 +250,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 +267,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. diff --git a/prefs.py b/prefs.py index 985ef581..e5ab242b 100644 --- a/prefs.py +++ b/prefs.py @@ -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 @@ -279,7 +278,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('<>', self.tabchanged) # Recompute on tab change self.PADX = 10 @@ -333,7 +332,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 +417,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) @@ -675,7 +674,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 +696,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 +886,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) @@ -1188,8 +1187,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: From ca233a40a8a13203e90b8cf889b013d4e9d320ac Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 14:54:08 +0000 Subject: [PATCH 096/257] plugins/coriolis: Minor type fixes. --- plugins/coriolis.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/coriolis.py b/plugins/coriolis.py index fef683b9..29fddf26 100644 --- a/plugins/coriolis.py +++ b/plugins/coriolis.py @@ -26,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. @@ -79,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 @@ -126,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() From 71cbfb835854843cddf4922bad5d88d8181ae473 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 16:35:02 +0000 Subject: [PATCH 097/257] plugins/edsm: Lots of type fixing, inc. conditionals where None is possible --- plug.py | 7 +- plugins/edsm.py | 250 +++++++++++++++++++++++++++--------------------- 2 files changed, 146 insertions(+), 111 deletions(-) diff --git a/plug.py b/plug.py index 68a2d26b..e6c4cd34 100644 --- a/plug.py +++ b/plug.py @@ -7,9 +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 - -import ttk +from tkinter import ttk +from typing import Any, Callable, List, Mapping, MutableMapping, Optional import companion import myNotebook as nb # noqa: N813 @@ -200,7 +199,7 @@ def provides(fn_name: str) -> List[str]: def invoke( - plugin_name: str, fallback: str | None, 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. diff --git a/plugins/edsm.py b/plugins/edsm.py index 130a794d..635b3559 100644 --- a/plugins/edsm.py +++ b/plugins/edsm.py @@ -38,12 +38,14 @@ 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 @@ -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: 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: 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() @@ -267,7 +269,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 +302,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 +318,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 +397,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 +409,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 +429,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 +438,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) @@ -545,12 +570,13 @@ entry: {entry!r}''' 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), str(this.station)) + 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() @@ -639,7 +665,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. @@ -663,27 +689,29 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]: # 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 + # 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: + this.station_link['text'] = this.station - 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 +787,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 +869,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'] = '' - 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 +893,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 +928,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('<>', when="tail") if r['msgnum'] // 100 != 1: # type: ignore @@ -996,18 +1031,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 From e66bae090bc6f1a02f842cc106bce56279cebf24 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 16:35:42 +0000 Subject: [PATCH 098/257] plugins/inara: Minor typing fixes --- plugins/inara.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/inara.py b/plugins/inara.py index 3501727c..51b7e270 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -30,12 +30,12 @@ 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 import requests -import ttk import edmc_data import killswitch @@ -236,7 +236,7 @@ def plugin_stop() -> None: logger.debug('Done.') -def plugin_prefs(parent: ttk.Frame, 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 From 2c11aef1be7cc1ef0269d429c17fd67b769d3a98 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 16:46:39 +0000 Subject: [PATCH 099/257] plugins/eddn: Use correct `logging` function & `new_data` typing * `logger.INFO` will, at best, be a constant, it should be `logger.info()`. * When we're not interested in the `new_data` 2nd part of the tuple from `killswitches.check_killswitch()` we can't use `_` as there's a potential class with the `l10n.py` injection of `_()` as a builtin. And you can't declare types withing first-use in a return-tuple. So, declare them on their own lines, with throwaway default values instead. --- plugins/eddn.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index b1df07b7..33ee1802 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -379,7 +379,7 @@ 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 @@ -635,6 +635,8 @@ 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 = False + 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.") @@ -766,6 +768,8 @@ class EDDN: :param data: dict containing the outfitting data :param is_beta: whether or not we're currently in beta mode """ + should_return: bool = False + 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.") @@ -832,6 +836,8 @@ class EDDN: :param data: dict containing the shipyard data :param is_beta: whether or not we are in beta mode """ + should_return: bool = False + 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.") From ce4a6ff898138fdeb41896a8aa35db2e31505284 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 16:54:03 +0000 Subject: [PATCH 100/257] plugins/eddn: Remove the 'default values' from should_retrn & new_data In *this* case the variables *are* used in the scope so become bound, so we can get away with bare type declaration. --- plugins/eddn.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index 33ee1802..3cd2d819 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -635,8 +635,8 @@ 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 = False - new_data: Dict[str, Any] = {} + 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.") @@ -768,8 +768,8 @@ class EDDN: :param data: dict containing the outfitting data :param is_beta: whether or not we're currently in beta mode """ - should_return: bool = False - new_data: Dict[str, Any] = {} + 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.") @@ -836,8 +836,8 @@ class EDDN: :param data: dict containing the shipyard data :param is_beta: whether or not we are in beta mode """ - should_return: bool = False - new_data: Dict[str, Any] = {} + 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.") From 37b054b3d36a0cad3bade6577e6ae77d759bd436 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 16:58:53 +0000 Subject: [PATCH 101/257] Fix type of `master` passed to `plug.load_plugins()` --- plug.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plug.py b/plug.py index e6c4cd34..8e19a6cf 100644 --- a/plug.py +++ b/plug.py @@ -27,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 @@ -141,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 From e45a89d97016dceaea1c647f9fda634cee8ab693 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 17:03:07 +0000 Subject: [PATCH 102/257] EDMarketConnector.py: Minor type fixes & ttkHyperlink.py too --- EDMarketConnector.py | 10 +++++++--- ttkHyperlinkLabel.py | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index bed58e99..11f103b4 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -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, Dict, 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 @@ -592,7 +592,7 @@ class AppWindow(object): # The type needs defining for adding the menu entry, but won't be # properly set until later - self.updater: update.Updater = None + self.updater: update.Updater | None = None self.menubar = tk.Menu() if sys.platform == 'darwin': @@ -647,7 +647,9 @@ class AppWindow(object): 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()) + if self.updater is not None: + self.help_menu.add_command(command=lambda: self.updater.check_for_updates()) + self.help_menu.add_command(command=lambda: not self.HelpAbout.showing and self.HelpAbout(self.w)) self.menubar.add_cascade(menu=self.help_menu) @@ -1005,6 +1007,8 @@ 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.') diff --git a/ttkHyperlinkLabel.py b/ttkHyperlinkLabel.py index 43071732..44cd38b0 100644 --- a/ttkHyperlinkLabel.py +++ b/ttkHyperlinkLabel.py @@ -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 From 69d764c0274ab693a5bc61050a12c7e90574435c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 17:06:24 +0000 Subject: [PATCH 103/257] EDMarketConnector: More misc type fixes --- EDMarketConnector.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 11f103b4..58d075a8 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1425,7 +1425,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 @@ -1443,7 +1443,9 @@ class AppWindow(object): # 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 @@ -1455,12 +1457,16 @@ 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 monitor.cmdr and monitor.system and monitor.station: + 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'): @@ -1496,7 +1502,9 @@ class AppWindow(object): 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: @@ -1539,7 +1547,9 @@ 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 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'): From 4de83747f89988446bd31c743ec41751ff55677f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 17:18:58 +0000 Subject: [PATCH 104/257] EDMarketConnector: More minor type fixes Also, the killswitch popup ends up un-themed *anyway*, so don't even call `theme.apply()`. That function expects a `tk.Tk` not, `Toplevel`, and doesn't even do anything for a `Toplevel` anyway. --- EDMarketConnector.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 58d075a8..388659ee 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1557,13 +1557,13 @@ class AppWindow(object): 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.') @@ -1590,11 +1590,11 @@ 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) - 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) @@ -1671,7 +1671,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 @@ -1684,7 +1684,7 @@ class AppWindow(object): ############################################################ # version - 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) @@ -1792,7 +1792,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 @@ -1941,11 +1942,9 @@ def show_killswitch_poppup(root=None): 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 From eaaa6fead08d95b6b58a5c24ca2c7e12cebf5ddd Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 17:25:13 +0000 Subject: [PATCH 105/257] Correctly type `theme` ui_scale variables Technically `theme.startup_ui_scale` should be `float` to match with `default_ui_scale` from tkinter, but we store it in the config as `int`, so go with that. --- EDMarketConnector.py | 5 ++++- theme.py | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 388659ee..c5831e74 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -2089,10 +2089,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(): diff --git a/theme.py b/theme.py index 45886f16..b5d51484 100644 --- a/theme.py +++ b/theme.py @@ -137,8 +137,8 @@ class _Theme(object): 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 From 63a1337bedfd8839768b4dca298a2f56cc3356f0 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 17:37:55 +0000 Subject: [PATCH 106/257] examples/click_counter: Minor type fixes. --- docs/examples/click_counter/load.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/examples/click_counter/load.py b/docs/examples/click_counter/load.py index b1ea6ac5..70c24f53 100644 --- a/docs/examples/click_counter/load.py +++ b/docs/examples/click_counter/load.py @@ -6,7 +6,6 @@ It adds a single button to the EDMC interface that displays the number of times import logging import tkinter as tk -import tkinter.ttk as ttk from typing import Optional import myNotebook as nb # noqa: N813 @@ -49,7 +48,7 @@ class ClickCounter: """ self.on_preferences_closed("", False) # Save our prefs - def setup_preferences(self, parent: ttk.Frame, cmdr: str, is_beta: bool) -> Optional[tk.Frame]: + def setup_preferences(self, parent: nb.Notebook, cmdr: str, is_beta: bool) -> Optional[tk.Frame]: """ setup_preferences is called by plugin_prefs below. @@ -128,7 +127,7 @@ def plugin_stop() -> None: return cc.on_unload() -def plugin_prefs(parent: ttk.Frame, cmdr: str, is_beta: bool) -> Optional[tk.Frame]: +def plugin_prefs(parent: nb.Notebook, cmdr: str, is_beta: bool) -> Optional[tk.Frame]: """ Handle preferences tab for the plugin. From 46d518986ca52a90f1b58c11dc6146d974bce83d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 17:41:01 +0000 Subject: [PATCH 107/257] hotkey/windows: Minor formatting cleanups --- hotkey/windows.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/hotkey/windows.py b/hotkey/windows.py index 4dd110af..27faba30 100644 --- a/hotkey/windows.py +++ b/hotkey/windows.py @@ -62,6 +62,7 @@ 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. @@ -77,6 +78,7 @@ def window_title(h) -> str: return '' + class MOUSEINPUT(ctypes.Structure): """Mouse Input structure.""" @@ -89,6 +91,7 @@ class MOUSEINPUT(ctypes.Structure): ('dwExtraInfo', ctypes.POINTER(ULONG)) ] + class KEYBDINPUT(ctypes.Structure): """Keyboard Input structure.""" @@ -100,6 +103,7 @@ class KEYBDINPUT(ctypes.Structure): ('dwExtraInfo', ctypes.POINTER(ULONG)) ] + class HARDWAREINPUT(ctypes.Structure): """Hardware Input structure.""" @@ -109,6 +113,7 @@ class HARDWAREINPUT(ctypes.Structure): ('wParamH', WORD) ] + class INPUTUNION(ctypes.Union): """Input union.""" @@ -118,6 +123,7 @@ class INPUTUNION(ctypes.Union): ('hi', HARDWAREINPUT) ] + class INPUT(ctypes.Structure): """Input structure.""" @@ -126,6 +132,7 @@ class INPUT(ctypes.Structure): ('union', INPUTUNION) ] + SendInput = ctypes.windll.user32.SendInput SendInput.argtypes = [ctypes.c_uint, ctypes.POINTER(INPUT), ctypes.c_int] @@ -268,10 +275,10 @@ class WindowsHotkeyMgr(AbstractHotkeyMgr): :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) + | ((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]: @@ -284,8 +291,9 @@ class WindowsHotkeyMgr(AbstractHotkeyMgr): 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 + 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 From 5609b908fb625c344c1427ece137415e2d775de3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 22 Dec 2022 17:41:35 +0000 Subject: [PATCH 108/257] ttkHyperlinkLabel: Remove un-used typing.Optional import --- ttkHyperlinkLabel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttkHyperlinkLabel.py b/ttkHyperlinkLabel.py index 44cd38b0..1d9749ac 100644 --- a/ttkHyperlinkLabel.py +++ b/ttkHyperlinkLabel.py @@ -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: ... From b3719347e8aac462cdf7f2829b61265d8cf05f53 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 11:50:15 +0000 Subject: [PATCH 109/257] EDMarketConnector: No need for Typing.Dict --- EDMarketConnector.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index c5831e74..b6bbcf11 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -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, Any, Dict, 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 @@ -1008,7 +1008,7 @@ class AppWindow(object): """ logger.trace_if('capi.worker', 'Begin') should_return: bool - new_data: Dict[str, Any] + 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.') From 1e0d99a61f5e605d14433d4455a0251987cf37b9 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 12:14:54 +0000 Subject: [PATCH 110/257] config/__init__: Remove use of typing.Union --- config/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/__init__.py b/config/__init__.py index ffc635e3..ae594c53 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -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, List, Optional, Type, TypeVar import semantic_version @@ -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: @@ -309,8 +309,8 @@ class AbstractConfig(abc.ABC): def get( self, key: str, - default: Union[list, str, bool, int, None] = None - ) -> Union[list, str, bool, int, None]: + default: list | str | bool | int | None = None + ) -> list | str | bool | int | None: """ Return the data for the requested key, or a default. @@ -399,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. From 299b42c55804c676959c15f2cbb91b28d1616838 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 12:15:25 +0000 Subject: [PATCH 111/257] config/__init__: Remove use of typing.List --- config/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/__init__.py b/config/__init__.py index ae594c53..ae2fad73 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -40,7 +40,7 @@ import sys import traceback import warnings from abc import abstractmethod -from typing import Any, Callable, List, Optional, Type, TypeVar +from typing import Any, Callable, Optional, Type, TypeVar import semantic_version @@ -59,10 +59,10 @@ copyright = '© 2015-2019 Jonathan Harris, 2020-2022 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: 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: @@ -399,7 +399,7 @@ class AbstractConfig(abc.ABC): raise NotImplementedError @abstractmethod - def set(self, key: str, val: 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. From fe5f68763b7c04b248a6651d85c9ffe9dcfcfc40 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 12:16:31 +0000 Subject: [PATCH 112/257] docs/Releasing: Remove paste error --- docs/Releasing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Releasing.md b/docs/Releasing.md index 7524ebbb..a8c4dc80 100644 --- a/docs/Releasing.md +++ b/docs/Releasing.md @@ -166,7 +166,7 @@ that it's actually included in the installer. ``` - | None + Note that you only need `Id=""` if the filename itself is not a valid Id, e.g. because it contains spaces. From 8a7a0fdf9a85b6dd47016b66f81bcb483478799d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 12:17:40 +0000 Subject: [PATCH 113/257] hotkey/windows: Remove un-necessary `u` tagging of strings --- hotkey/windows.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/hotkey/windows.py b/hotkey/windows.py index 27faba30..0bc54d1a 100644 --- a/hotkey/windows.py +++ b/hotkey/windows.py @@ -147,14 +147,14 @@ class WindowsHotkeyMgr(AbstractHotkeyMgr): # 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'↓', + 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: u'▤', 0x5f: u'☾', - 0x90: u'➀', 0x91: 'ScrLk', - 0xa6: u'⇦', 0xa7: u'⇨', 0xa9: u'⊗', 0xab: u'☆', 0xac: u'⌂', 0xb4: u'✉', + 0x5d: '▤', 0x5f: '☾', + 0x90: '➀', 0x91: 'ScrLk', + 0xa6: '⇦', 0xa7: '⇨', 0xa9: '⊗', 0xab: '☆', 0xac: '⌂', 0xb4: '✉', } def __init__(self) -> None: @@ -320,19 +320,19 @@ class WindowsHotkeyMgr(AbstractHotkeyMgr): """ text = '' if modifiers & MOD_WIN: - text += u'❖+' + text += '❖+' if modifiers & MOD_CONTROL: - text += u'Ctrl+' + text += 'Ctrl+' if modifiers & MOD_ALT: - text += u'Alt+' + text += 'Alt+' if modifiers & MOD_SHIFT: - text += u'⇧+' + text += '⇧+' if VK_NUMPAD0 <= keycode <= VK_DIVIDE: - text += u'№' + text += '№' if not keycode: pass @@ -346,7 +346,7 @@ class WindowsHotkeyMgr(AbstractHotkeyMgr): else: c = MapVirtualKey(keycode, 2) # printable ? if not c: # oops not printable - text += u'⁈' + text += '⁈' elif c < 0x20: # control keys text += chr(c + 0x40) From 5e19d3e9aa1103dd752017df2dc2fca41e0285f1 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 12:20:54 +0000 Subject: [PATCH 114/257] plugins/eddn: No need for typing.(Dict|List) usage --- plugins/eddn.py | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index 3cd2d819..f6591779 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -34,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 @@ -91,13 +91,13 @@ class This: # 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 @@ -612,7 +612,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,7 +636,7 @@ class EDDN: :param is_beta: whether or not we're currently in beta mode """ should_return: bool - new_data: Dict[str, Any] + 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.") @@ -653,7 +653,7 @@ class EDDN: 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) @@ -715,7 +715,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. @@ -726,7 +726,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?') @@ -743,7 +743,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') @@ -769,7 +769,7 @@ class EDDN: :param is_beta: whether or not we're currently in beta mode """ should_return: bool - new_data: Dict[str, Any] + 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.") @@ -796,7 +796,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 ) @@ -837,7 +837,7 @@ class EDDN: :param is_beta: whether or not we are in beta mode """ should_return: bool - new_data: Dict[str, Any] + 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.") @@ -856,7 +856,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 {}), @@ -899,8 +899,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']), @@ -947,11 +947,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) ) @@ -986,7 +986,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. @@ -1828,7 +1828,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", @@ -2576,7 +2576,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. From bc5cb48f8cfeccbde8b4092278541f27dc22a783 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 12:25:36 +0000 Subject: [PATCH 115/257] stats.py: Remove usage of un-necessary typing types. Dict, List, Optional --- stats.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/stats.py b/stats.py index f7f15b86..6b5d8d61 100644 --- a/stats.py +++ b/stats.py @@ -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. @@ -358,7 +358,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 @@ -443,7 +443,7 @@ class StatsResults(tk.Toplevel): self.geometry(f"+{position.left}+{position.top}") def addpage( - self, parent, header: List[str] | None = None, align: str | None = None + self, parent, header: list[str] | None = None, align: str | None = None ) -> ttk.Frame: """ Add a page to the StatsResults screen. @@ -464,7 +464,7 @@ class StatsResults(tk.Toplevel): return page - def addpageheader(self, parent: ttk.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. @@ -480,7 +480,7 @@ class StatsResults(tk.Toplevel): self.addpagerow(parent, ['']) def addpagerow( - self, parent: ttk.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. From 5064b10744976a9ffe9b084e6a1f951566e7fdd0 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 12:32:09 +0000 Subject: [PATCH 116/257] Bring in `scripts/pip_rev_deps.py` * This finds the pip-installed modules that depend on the specified module. Handy for cleaning things up. * Leads to needing types-pkg-resources for mypy (and via pre-commit). --- .pre-commit-config.yaml | 2 +- requirements-dev.txt | 1 + scripts/pip_rev_deps.py | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 scripts/pip_rev_deps.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 778c2161..5b534279 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -51,7 +51,7 @@ repos: - id: mypy # verbose: true # log_file: 'pre-commit_mypy.log' - additional_dependencies: [ types-requests, types-urllib3 ] + additional_dependencies: [ types-pkg-resources, types-requests, types-urllib3 ] # args: [ "--follow-imports", "skip", "--ignore-missing-imports", "--scripts-are-modules" ] ### # pydocstyle.exe diff --git a/requirements-dev.txt b/requirements-dev.txt index ceacac8e..cb25fbf8 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,6 +24,7 @@ mypy==0.991 pep8-naming==0.13.3 safety==2.3.5 types-requests==2.28.11.7 +types-pkg-resources==0.1.3 # Code formatting tools autopep8==2.0.1 diff --git a/scripts/pip_rev_deps.py b/scripts/pip_rev_deps.py new file mode 100644 index 00000000..b97757d5 --- /dev/null +++ b/scripts/pip_rev_deps.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])) From 90183554ef157f8a508d40a6979753044be2909c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 12:59:44 +0000 Subject: [PATCH 117/257] tests/journal_lock: Use proper `pytest` types in fixtures When I last typed this I couldn't find any official way to type `pytest` fixtures. Perhaps that was before: https://docs.pytest.org/en/6.2.x/changelog.html#improvements which now makes it clean and simple. --- tests/journal_lock.py/test_journal_lock.py | 39 +++++++++++----------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/tests/journal_lock.py/test_journal_lock.py b/tests/journal_lock.py/test_journal_lock.py index 7bfd4ea8..c617d52c 100644 --- a/tests/journal_lock.py/test_journal_lock.py +++ b/tests/journal_lock.py/test_journal_lock.py @@ -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,9 +116,9 @@ 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 = None) -> str: """Mock config.*Config get_str to provide fake journaldir.""" @@ -136,9 +135,9 @@ 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 = None) -> str: """Mock config.*Config get_str to provide fake journaldir.""" @@ -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(). From a499a22383521f6f47abb3015de966812d771e68 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 13:02:40 +0000 Subject: [PATCH 118/257] .mypy.ini: Set `follow_imports` explicitly to `normal` default We'd been using `skip` because when we started with mypy next to nothing passed it, and checking one file would spew errors with other files and it just wasn't conducive to making at least *some* progress. But now we should have every single file passing, so this is the right thing to do. --- .mypy.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mypy.ini b/.mypy.ini index d3a0d2e2..75f4ccdb 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -1,5 +1,5 @@ [mypy] -follow_imports = skip +follow_imports = normal ignore_missing_imports = True scripts_are_modules = True ; Without this bare `mypy ` may get warnings for e.g. From 841ae2006ed69194a6fe284f72bf04dc51346f76 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 15:06:47 +0000 Subject: [PATCH 119/257] mypy: Add script to run against all, and use in github/push-checks --- .github/workflows/push-checks.yml | 4 ++++ scripts/mypy-all.sh | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 scripts/mypy-all.sh diff --git a/.github/workflows/push-checks.yml b/.github/workflows/push-checks.yml index e0c98897..5fdd1a14 100644 --- a/.github/workflows/push-checks.yml +++ b/.github/workflows/push-checks.yml @@ -59,3 +59,7 @@ jobs: grep -E -z -Z '\.py$' | \ xargs -0 flake8 --count --statistics --extend-ignore D ####################################################################### + + - name: mypy type checks + run: | + ./scripts/mypy-all.sh diff --git a/scripts/mypy-all.sh b/scripts/mypy-all.sh new file mode 100644 index 00000000..71f2f958 --- /dev/null +++ b/scripts/mypy-all.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# + +mypy $(git ls-tree --full-tree -r --name-only HEAD | grep -E '\.py$') From 8bacbf77ff2f4e42daaa63b9fc47dc766d06158b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 15:11:56 +0000 Subject: [PATCH 120/257] github/push-checks: Run on any branch except main, stable, beta, releases --- .github/workflows/push-checks.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/push-checks.yml b/.github/workflows/push-checks.yml index 5fdd1a14..0ebd6dee 100644 --- a/.github/workflows/push-checks.yml +++ b/.github/workflows/push-checks.yml @@ -9,7 +9,12 @@ 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: From e70b3c99f2cd63d3e35c0b0167331b0bede33366 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 15:18:32 +0000 Subject: [PATCH 121/257] github/push-checks: Correct the job name, from `build` --- .github/workflows/push-checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push-checks.yml b/.github/workflows/push-checks.yml index 0ebd6dee..b483ebb0 100644 --- a/.github/workflows/push-checks.yml +++ b/.github/workflows/push-checks.yml @@ -17,7 +17,7 @@ on: - 'beta' jobs: - build: + push_checks: runs-on: ubuntu-22.04 From 862565e95507fcdbde5f30902cf8e3381b1e4159 Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 17:18:56 +0200 Subject: [PATCH 122/257] github/push-checks: set mypy-all script to be +x --- scripts/mypy-all.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/mypy-all.sh diff --git a/scripts/mypy-all.sh b/scripts/mypy-all.sh old mode 100644 new mode 100755 From 3d53b1a54d18b098e02642c83f60dbdeaa12f289 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 15:24:45 +0000 Subject: [PATCH 123/257] github/mypy: Specifically run for win32 platform --- .github/workflows/push-checks.yml | 2 +- scripts/mypy-all.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/push-checks.yml b/.github/workflows/push-checks.yml index b483ebb0..07f45e75 100644 --- a/.github/workflows/push-checks.yml +++ b/.github/workflows/push-checks.yml @@ -67,4 +67,4 @@ jobs: - name: mypy type checks run: | - ./scripts/mypy-all.sh + ./scripts/mypy-all.sh --platform win32 diff --git a/scripts/mypy-all.sh b/scripts/mypy-all.sh index 71f2f958..02a76a48 100755 --- a/scripts/mypy-all.sh +++ b/scripts/mypy-all.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash # -mypy $(git ls-tree --full-tree -r --name-only HEAD | grep -E '\.py$') +mypy $@ $(git ls-tree --full-tree -r --name-only HEAD | grep -E '\.py$') From db956cd68b5ea162c40e26562aafd66534c36fe9 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 15:32:09 +0000 Subject: [PATCH 124/257] scripts/mypy-all: Add a little comment documentation --- scripts/mypy-all.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/mypy-all.sh b/scripts/mypy-all.sh index 02a76a48..72a37f0b 100755 --- a/scripts/mypy-all.sh +++ b/scripts/mypy-all.sh @@ -1,4 +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$') From ee1df33cec16b9baaf657cc3520eeded33c7dbad Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 17 Nov 2022 15:45:18 +0000 Subject: [PATCH 125/257] TEMPORARY: Ignore venv-3.11_64 in LANG comment hook --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5b534279..f7f16901 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -82,7 +82,7 @@ repos: - id: LANG_comments name: 'LANG comments' language: system - entry: python scripts/find_localised_strings.py --compare-lang L10n/en.template --directory . --ignore coriolis-data --ignore dist.win32 + entry: python scripts/find_localised_strings.py --compare-lang L10n/en.template --directory . --ignore coriolis-data --ignore dist.win32 --ignore venv-3.11_64 pass_filenames: false always_run: true From f141fccd86ded08e503fb45463cd7d35d139a0f2 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 17 Nov 2022 17:39:09 +0000 Subject: [PATCH 126/257] protocol.py: Change definition of DefWindowProcW to work on 64-bit Given this is the form of definition in the official Python docs I'm wondering if this only ever worked on 32-bit by accident. So, it was nothing to do with the type needing to be changed for 64-bit. The error: ctypes.ArgumentError: argument 4: : int too long to convert was a red herring in those terms. --- protocol.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/protocol.py b/protocol.py index 290a7031..eddc6391 100644 --- a/protocol.py +++ b/protocol.py @@ -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 @@ -157,7 +157,13 @@ elif (config.auth_force_edmc_protocol CreateWindowExW.restype = HWND RegisterClassW = windll.user32.RegisterClassW RegisterClassW.argtypes = [POINTER(WNDCLASS)] - DefWindowProcW = windll.user32.DefWindowProcW + # DefWindowProcW + # Ref: + # LRESULT DefWindowProcW([in] HWND hWnd,[in] UINT Msg,[in] WPARAM wParam,[in] LPARAM lParam); + # As per example at + 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 From da530f135e4181d473cc5e72e51e4c52ee079bca Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 17 Nov 2022 20:52:25 +0000 Subject: [PATCH 127/257] prefs.py: Attempting to fix non-utf-8 case of "choose Output file location" 1. `SHGetPathFromIDListW` needing fixing, which was achieved, but... 2. ... then `SHBrowseForFolderW()` as-was returned `int` instead of a pointer to the correct structure. Trying to fix 2 has proven intractable: a. Trying to cast the `int` return just results in `exception: access violation reading
`. b. Trying to define `SHBrowseForFolderW` properly, so it returns the correct type results in a *writing* access violation when called, despite passing the exact same data in as for the 'raw' call version. So, this commit is a record, and I'm next going to try switching to `IFileDialog` as recommended by the docs for `SHBrowseForFolderW` ('For Windows Vista or later'). --- prefs.py | 81 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 11 deletions(-) diff --git a/prefs.py b/prefs.py index e5ab242b..e4964785 100644 --- a/prefs.py +++ b/prefs.py @@ -181,7 +181,10 @@ 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 import POINTER, WINFUNCTYPE, Structure + from ctypes.wintypes import ( + BOOL, BYTE, HINSTANCE, HWND, LPARAM, LPCWSTR, LPWSTR, MAX_PATH, POINT, RECT, SIZE, UINT, USHORT + ) is_wine = False try: WINE_REGISTRY_KEY = r'HKEY_LOCAL_MACHINE\Software\Wine' @@ -192,18 +195,68 @@ elif sys.platform == 'win32': except OSError: pass + ########################################################################### + # From + class _SHITEMID(ctypes.Structure): + _fields_ = [ + ("cb", USHORT), + ("abID", BYTE * (1)), + ] + + SHITEMID = _SHITEMID + + class _ITEMIDLIST(Structure): + _fields_ = [ + ("mkid", SHITEMID), + ] + + ITEMIDLIST = _ITEMIDLIST + PCIDLIST_ABSOLUTE = ctypes.POINTER(_ITEMIDLIST) + PIDLIST_ABSOLUTE = ctypes.POINTER(_ITEMIDLIST) + ########################################################################### + + ########################################################################### + # From: + BrowseCallbackProc = WINFUNCTYPE(ctypes.c_int, HWND, ctypes.c_uint, LPARAM, LPARAM) + + class BROWSEINFOW(ctypes.Structure): + """ + Windows file browser fields. + + Ref: + """ + + _fields_ = [ + ("hwndOwner", HWND), + ("pidlRoot", PCIDLIST_ABSOLUTE), + ("pszDisplayName", LPWSTR), + ("lpszTitle", LPCWSTR), + ("ulFlags", UINT), + ("lpfn", BrowseCallbackProc), + ("lParam", LPARAM), + ("iImage", ctypes.c_int) + ] + LPBROWSEINFOW = POINTER(BROWSEINFOW) + ########################################################################### + # 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) + # SHGetPathFromIDListW + # Ref: + # BOOL SHGetPathFromIDListW([in] PCIDLIST_ABSOLUTE pidl,[out] LPWSTR pszPath); + prototype = WINFUNCTYPE(BOOL, PCIDLIST_ABSOLUTE, LPCWSTR) + paramflags = (1, "pidl"), (2, "pszPath", "") + SHGetPathFromIDListW = prototype(("SHGetPathFromIDListW", ctypes.windll.shell32), paramflags) - 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)] + # SHBrowseForFolderW + # Ref: + # PIDLIST_ABSOLUTE SHBrowseForFolderW([in] LPBROWSEINFOWW lpbi); + prototype = WINFUNCTYPE(PIDLIST_ABSOLUTE, LPBROWSEINFOW) + paramflags2 = (1, "lpbi"), + SHBrowseForFolderW = prototype(("SHGetPathFromIDListW", ctypes.windll.shell32), paramflags2) CalculatePopupWindowPosition = None if not is_wine: @@ -1037,17 +1090,23 @@ class PreferencesDialog(tk.Toplevel): ctypes.windll.user32.SendMessageW(hwnd, BFFM_SETSELECTION, 1, lpData) return 0 - browseInfo = BROWSEINFO() # noqa: N806 # Windows convention + browseInfo = BROWSEINFOW() # noqa: N806 # Windows convention + # browseInfo.pidlRoot = None + browseInfo.pszDisplayName = ctypes.c_wchar_p("x" * MAX_PATH) 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() + # 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)) + # ctypes.ArgumentError: argument 1: : expected LP__ITEMIDLIST instance instead of int + # pidl = SHBrowseForFolderW(ctypes.byref(browseInfo)) + # OSError: exception: access violation writing 0x00007FFB582DC9BF if pidl: + pidl = ctypes.cast(pidl, PIDLIST_ABSOLUTE) path = ctypes.create_unicode_buffer(MAX_PATH) - ctypes.windll.shell32.SHGetPathFromIDListW(pidl, path) + path = SHGetPathFromIDListW(pidl) ctypes.windll.ole32.CoTaskMemFree(pidl) directory = path.value else: From 09ecdbb8495b3a79e70d03d41a2b15fc81aac994 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 18 Nov 2022 10:47:11 +0000 Subject: [PATCH 128/257] prefs.py: Always use `tkinter.filedialog` for Output File Location * I can't even get this code to be problematic, with a folder containing unicode heart characters, on 64-bit Python 3.7.9 (Release/4.1.6 adjusted to not set UTF-8 locale), let alone on 64-bit Python 3.11 and this branch. So, just always use the tkinter dialog. Bye-bye ctypes code which I just couldn't get to work under 64-bit Python. * I *think* the issue with the ctypes code was that under 32-bit an 'int' and a pointer are the same size. 'Raw' (not declaring types beforehand) the `SHBrowseForFolderW()` function causes ctypes to consider it returns an int. This works on 32-bit. But on 64-bit that int is still 32-bits, but pointers are 64-bit, so ctypes ends up coercing/casting/truncating the returned pointer into an int, which than can't even be cast back to a pointer. Meanwhile, attempting to properly define the signature of the function has only lead to it crashing on invocation, despite being passed the same BROWSEINFOW structure, defined in the same manner. This might be a matter of a type within it needing adjusting, but I was following the docs there. --- prefs.py | 49 +++++++------------------------------------------ 1 file changed, 7 insertions(+), 42 deletions(-) diff --git a/prefs.py b/prefs.py index e4964785..6683f297 100644 --- a/prefs.py +++ b/prefs.py @@ -1078,48 +1078,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 = BROWSEINFOW() # noqa: N806 # Windows convention - # browseInfo.pidlRoot = None - browseInfo.pszDisplayName = ctypes.c_wchar_p("x" * MAX_PATH) - 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)) - # ctypes.ArgumentError: argument 1: : expected LP__ITEMIDLIST instance instead of int - # pidl = SHBrowseForFolderW(ctypes.byref(browseInfo)) - # OSError: exception: access violation writing 0x00007FFB582DC9BF - if pidl: - pidl = ctypes.cast(pidl, PIDLIST_ABSOLUTE) - path = ctypes.create_unicode_buffer(MAX_PATH) - path = SHGetPathFromIDListW(pidl) - 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) From 12b77f696b2290e7efb383842a535dfa6175f03e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 18 Nov 2022 11:25:22 +0000 Subject: [PATCH 129/257] prefs.py: Remove the now un-used ctypes imports/definitions --- prefs.py | 68 +------------------------------------------------------- 1 file changed, 1 insertion(+), 67 deletions(-) diff --git a/prefs.py b/prefs.py index 6683f297..8b372683 100644 --- a/prefs.py +++ b/prefs.py @@ -181,10 +181,7 @@ if sys.platform == 'darwin': elif sys.platform == 'win32': import ctypes import winreg - from ctypes import POINTER, WINFUNCTYPE, Structure - from ctypes.wintypes import ( - BOOL, BYTE, HINSTANCE, HWND, LPARAM, LPCWSTR, LPWSTR, MAX_PATH, POINT, RECT, SIZE, UINT, USHORT - ) + 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' @@ -195,69 +192,6 @@ elif sys.platform == 'win32': except OSError: pass - ########################################################################### - # From - class _SHITEMID(ctypes.Structure): - _fields_ = [ - ("cb", USHORT), - ("abID", BYTE * (1)), - ] - - SHITEMID = _SHITEMID - - class _ITEMIDLIST(Structure): - _fields_ = [ - ("mkid", SHITEMID), - ] - - ITEMIDLIST = _ITEMIDLIST - PCIDLIST_ABSOLUTE = ctypes.POINTER(_ITEMIDLIST) - PIDLIST_ABSOLUTE = ctypes.POINTER(_ITEMIDLIST) - ########################################################################### - - ########################################################################### - # From: - BrowseCallbackProc = WINFUNCTYPE(ctypes.c_int, HWND, ctypes.c_uint, LPARAM, LPARAM) - - class BROWSEINFOW(ctypes.Structure): - """ - Windows file browser fields. - - Ref: - """ - - _fields_ = [ - ("hwndOwner", HWND), - ("pidlRoot", PCIDLIST_ABSOLUTE), - ("pszDisplayName", LPWSTR), - ("lpszTitle", LPCWSTR), - ("ulFlags", UINT), - ("lpfn", BrowseCallbackProc), - ("lParam", LPARAM), - ("iImage", ctypes.c_int) - ] - LPBROWSEINFOW = POINTER(BROWSEINFOW) - ########################################################################### - - # https://msdn.microsoft.com/en-us/library/windows/desktop/bb762115 - BIF_RETURNONLYFSDIRS = 0x00000001 - BIF_USENEWUI = 0x00000050 - BFFM_INITIALIZED = 1 - BFFM_SETSELECTION = 0x00000467 - # SHGetPathFromIDListW - # Ref: - # BOOL SHGetPathFromIDListW([in] PCIDLIST_ABSOLUTE pidl,[out] LPWSTR pszPath); - prototype = WINFUNCTYPE(BOOL, PCIDLIST_ABSOLUTE, LPCWSTR) - paramflags = (1, "pidl"), (2, "pszPath", "") - SHGetPathFromIDListW = prototype(("SHGetPathFromIDListW", ctypes.windll.shell32), paramflags) - - # SHBrowseForFolderW - # Ref: - # PIDLIST_ABSOLUTE SHBrowseForFolderW([in] LPBROWSEINFOWW lpbi); - prototype = WINFUNCTYPE(PIDLIST_ABSOLUTE, LPBROWSEINFOW) - paramflags2 = (1, "lpbi"), - SHBrowseForFolderW = prototype(("SHGetPathFromIDListW", ctypes.windll.shell32), paramflags2) - CalculatePopupWindowPosition = None if not is_wine: try: From f9d384cc6dfcc32a6fd0ddd28a468a92dc52072a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 18 Nov 2022 11:32:25 +0000 Subject: [PATCH 130/257] prefs.py: Comment why `except OSError` being thrown away (wine check) --- prefs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prefs.py b/prefs.py index 8b372683..91123350 100644 --- a/prefs.py +++ b/prefs.py @@ -189,7 +189,7 @@ 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 CalculatePopupWindowPosition = None From cdb61bcced1fb9cd31414310071df584e71b599f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 18 Nov 2022 12:39:32 +0000 Subject: [PATCH 131/257] stats.py: Checking CAPI lastStarport is un-necessary, as never used. The `lastSystem` *is* however used, for the 'current ship not currently docked' case. --- stats.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/stats.py b/stats.py index 6b5d8d61..d690dce6 100644 --- a/stats.py +++ b/stats.py @@ -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 From 3a8f3d62978edf0c3d24a01aa11fc4911bc73656 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 18 Nov 2022 15:31:07 +0000 Subject: [PATCH 132/257] Build: Switch to requiring 64-bit, not 32-bit, Python --- Build-exe-and-msi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Build-exe-and-msi.py b/Build-exe-and-msi.py index adc04432..516ac21f 100644 --- a/Build-exe-and-msi.py +++ b/Build-exe-and-msi.py @@ -22,7 +22,7 @@ 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' + assert platform.architecture()[0] == '64bit', 'A Python 64bit build is required' import py2exe # noqa: F401 # Yes, this *is* used dist_dir = 'dist.win32' From b678985fa6c9c61a35409c3b4c9021ea996bca8e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 18 Nov 2022 16:12:00 +0000 Subject: [PATCH 133/257] github: windows-build: Use x64 versions of WinSparkle files --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index dc0fc120..93091a7c 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -34,7 +34,7 @@ jobs: run: | Invoke-Webrequest -UseBasicParsing https://github.com/vslavik/winsparkle/releases/download/v0.7.0/WinSparkle-0.7.0.zip -OutFile out.zip Expand-Archive out.zip - Move-Item 'out\WinSparkle-0.7.0\Release\*' '.\' + Move-Item 'out\WinSparkle-0.7.0\x64\Release\*' '.\' - name: Build EDMC run: | From 7620bcdaaad375a724e5ab6651d6fcca41be367b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 18 Nov 2022 16:14:05 +0000 Subject: [PATCH 134/257] Revert "TEMPORARY: Ignore venv-3.11_64 in LANG comment hook" This reverts commit af785457edd0bc8139941157eeb1d2937a89899d. --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f7f16901..5b534279 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -82,7 +82,7 @@ repos: - id: LANG_comments name: 'LANG comments' language: system - entry: python scripts/find_localised_strings.py --compare-lang L10n/en.template --directory . --ignore coriolis-data --ignore dist.win32 --ignore venv-3.11_64 + entry: python scripts/find_localised_strings.py --compare-lang L10n/en.template --directory . --ignore coriolis-data --ignore dist.win32 pass_filenames: false always_run: true From 876afafcacf902f27ec2ad09cc75051e8de2f08b Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 17:49:07 +0200 Subject: [PATCH 135/257] config/linux.py Fix mypy complaints This wasn't updated to note optionals when the parent base class was --- config/linux.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/config/linux.py b/config/linux.py index 04087b32..3eee4c93 100644 --- a/config/linux.py +++ b/config/linux.py @@ -3,7 +3,7 @@ import os import pathlib import sys from configparser import ConfigParser -from typing import List, Optional, Union +from typing import Any, List, Optional, Union from config import AbstractConfig, appname, logger @@ -119,7 +119,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 +134,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 +168,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. From 50dd6035201c0b837e7d1c1b9e8bf0dc9158888f Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 17:53:58 +0200 Subject: [PATCH 136/257] tests/config: Disable mypy on _old_config.py This file is just for regression testing and will never be typed correctly, which is why we no longer use it :D --- tests/config/_old_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/config/_old_config.py b/tests/config/_old_config.py index 0226bc36..211c1e72 100644 --- a/tests/config/_old_config.py +++ b/tests/config/_old_config.py @@ -1,3 +1,4 @@ +# type: ignore import numbers import sys import warnings From 5dd2287e68fe320a50c0e86ea33751f7e9f1ef12 Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 17:55:23 +0200 Subject: [PATCH 137/257] build: add "dumb" platform check for mypy Mypy doesn't understand some clever version checks. This adds an otherwise un-needed assert to force mypy to ignore the file on linux --- Build-exe-and-msi.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Build-exe-and-msi.py b/Build-exe-and-msi.py index adc04432..71e1eace 100644 --- a/Build-exe-and-msi.py +++ b/Build-exe-and-msi.py @@ -28,6 +28,9 @@ if sys.platform == 'win32': else: raise AssertionError(f'Unsupported platform {sys.platform}') + +# This added to make mypy happy +assert sys.platform == 'win32' ########################################################################### ########################################################################### From fa99225b95df47aead771aa32d1cea625eb2343b Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 17:56:44 +0200 Subject: [PATCH 138/257] myNotebook.py: Make platform check simpler Mypy does not appear to understand the `x in ...` format for this chech --- myNotebook.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/myNotebook.py b/myNotebook.py index 1989141f..30f95274 100644 --- a/myNotebook.py +++ b/myNotebook.py @@ -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: From 470c9b2728d43dfa552050d280e661b0a4c41965 Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 18:02:55 +0200 Subject: [PATCH 139/257] hotkey/linux.py: Update stub This was missing some abstract methods --- hotkey/linux.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/hotkey/linux.py b/hotkey/linux.py index 9a60515f..5074c319 100644 --- a/hotkey/linux.py +++ b/hotkey/linux.py @@ -20,6 +20,37 @@ class LinuxHotKeyMgr(AbstractHotkeyMgr): """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 From 490bd9dbddbea6a2d309844de74804d9a65dcbde Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 18:07:39 +0200 Subject: [PATCH 140/257] hotkeys/windows.py: Add explicit platform check --- hotkey/windows.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hotkey/windows.py b/hotkey/windows.py index 0bc54d1a..8a1c7acd 100644 --- a/hotkey/windows.py +++ b/hotkey/windows.py @@ -2,6 +2,7 @@ import atexit import ctypes import pathlib +import sys import threading import tkinter as tk import winsound @@ -12,6 +13,8 @@ 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 From f94072a99e813b3928e122309d48d00c7c3dd73a Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 18:17:33 +0200 Subject: [PATCH 141/257] EDMarketConnector.py: Guard platform specific func Some callback functions are only used on windows, but defined for everyone, this causes mypy to fail in fun ways. --- EDMarketConnector.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index b6bbcf11..b9c7bdf2 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1617,10 +1617,11 @@ class AppWindow(object): monitor.system 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.""" @@ -1760,13 +1761,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.""" From a930f5b9024649efd7fb36a569c68683b9fe9802 Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 18:25:14 +0200 Subject: [PATCH 142/257] protocol.py: Make mypy happy This adds an assert that mypy will understand, and a type ignore because it seems to ignore those asserts in imports --- protocol.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/protocol.py b/protocol.py index 290a7031..f0e1b4a8 100644 --- a/protocol.py +++ b/protocol.py @@ -121,9 +121,13 @@ 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 From 4527177f9b753172e49c2b77a0e87cd933e428f5 Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 18:33:47 +0200 Subject: [PATCH 143/257] config/linux.py: Removed List and Optional usage Missed these in the initial PR -- using the python 3.10 versions --- config/linux.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/config/linux.py b/config/linux.py index 3eee4c93..5d543d3f 100644 --- a/config/linux.py +++ b/config/linux.py @@ -3,7 +3,6 @@ import os import pathlib import sys from configparser import ConfigParser -from typing import Any, 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. @@ -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)) From 08d28c6f3d5ad8ff0447dd22877ce330bbb97742 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 16:41:07 +0000 Subject: [PATCH 144/257] protocol: Properly prototype GetMessageW & comment about 'exception' * In trying to fix the return type 'exception' I first decided to properly prototype GetMessageW(). * But it turns out that you just can't get rid of that exception, so I just added a comment about it being harmless, because the functionality works as intended anyway. --- protocol.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/protocol.py b/protocol.py index eddc6391..0ce3bd76 100644 --- a/protocol.py +++ b/protocol.py @@ -125,8 +125,8 @@ elif (config.auth_force_edmc_protocol 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.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): @@ -161,13 +161,21 @@ elif (config.auth_force_edmc_protocol # Ref: # LRESULT DefWindowProcW([in] HWND hWnd,[in] UINT Msg,[in] WPARAM wParam,[in] LPARAM lParam); # As per example at + 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 + # + # 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 @@ -309,6 +317,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: + # 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: From ca915782f678101ee0e987a2d21345c7ec99e527 Mon Sep 17 00:00:00 2001 From: A_D Date: Fri, 23 Dec 2022 19:01:02 +0200 Subject: [PATCH 145/257] hotkey: add sys.platform guards to all files This both makes mypy happy and ensures that the wrong file is not imported in the wrong place --- hotkey/darwin.py | 3 ++- hotkey/linux.py | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hotkey/darwin.py b/hotkey/darwin.py index a053a55f..cbf9d260 100644 --- a/hotkey/darwin.py +++ b/hotkey/darwin.py @@ -3,6 +3,7 @@ import pathlib import sys import tkinter as tk from typing import Callable, Optional, Tuple, Union +assert sys.platform == 'darwin' import objc from AppKit import ( @@ -36,7 +37,7 @@ class MacHotkeyMgr(AbstractHotkeyMgr): def __init__(self): self.MODIFIERMASK = NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask \ - | NSNumericPadKeyMask + | NSNumericPadKeyMask self.root: tk.Tk self.keycode = 0 diff --git a/hotkey/linux.py b/hotkey/linux.py index 5074c319..927c4d26 100644 --- a/hotkey/linux.py +++ b/hotkey/linux.py @@ -1,7 +1,11 @@ """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() From f2b18ed871638335570e57f49754347f484d58f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Dec 2022 17:01:02 +0000 Subject: [PATCH 146/257] build(deps-dev): bump flake8-isort from 5.0.3 to 6.0.0 Bumps [flake8-isort](https://github.com/gforcada/flake8-isort) from 5.0.3 to 6.0.0. - [Release notes](https://github.com/gforcada/flake8-isort/releases) - [Changelog](https://github.com/gforcada/flake8-isort/blob/master/CHANGES.rst) - [Commits](https://github.com/gforcada/flake8-isort/compare/5.0.3...6.0.0) --- updated-dependencies: - dependency-name: flake8-isort dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index cb25fbf8..4207743e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -14,7 +14,7 @@ flake8-cognitive-complexity==0.1.0 flake8-comprehensions==3.10.1 flake8-docstrings==1.6.0 isort==5.11.4 -flake8-isort==5.0.3 +flake8-isort==6.0.0 flake8-json==21.7.0 flake8-noqa==1.3.0 flake8-polyfill==1.0.2 From ec90912d3143e307de173ada01bcdee4aecb9de7 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 23 Dec 2022 17:34:58 +0000 Subject: [PATCH 147/257] Build: Don't enforce any bit-ness of platform Testing shows this branch works (after build) on both 32-bit and 64-bit. --- Build-exe-and-msi.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Build-exe-and-msi.py b/Build-exe-and-msi.py index 516ac21f..ee157fdf 100644 --- a/Build-exe-and-msi.py +++ b/Build-exe-and-msi.py @@ -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,7 +21,6 @@ if sys.version_info[0:2] != (3, 11): raise AssertionError(f'Unexpected python version {sys.version}') if sys.platform == 'win32': - assert platform.architecture()[0] == '64bit', 'A Python 64bit build is required' import py2exe # noqa: F401 # Yes, this *is* used dist_dir = 'dist.win32' From 754367618ff273b94ae459544a7c73b86a182499 Mon Sep 17 00:00:00 2001 From: aussig Date: Sat, 24 Dec 2022 09:27:18 +0000 Subject: [PATCH 148/257] Fix for exceptions thrown on journal events --- EDMarketConnector.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index ad043c93..47a7110a 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1547,10 +1547,10 @@ class AppWindow(object): monitor.state ) - if err: - self.status['text'] = err - if not config.get_int('hotkey_mute'): - hotkeymgr.play_bad() + 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 From e22fa7c23bf264da5fad37ba1f8ea40050be3c9f Mon Sep 17 00:00:00 2001 From: aussig Date: Sat, 24 Dec 2022 09:32:45 +0000 Subject: [PATCH 149/257] Store cmdr name at request time in CAPIData instead of passing into EDMCCAPIRequest and EDMCCAPIResponse --- PLUGINS.md | 24 +++++++++++------------- companion.py | 23 +++++++++-------------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index df6d011f..c9debd5b 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -970,22 +970,20 @@ def capi_fleetcarrier(data): | :-------- | :--------------: | :------------------------------------------------------------------------------------------------------- | | `data` | `CAPIData` | `/fleetcarrier` API response | -`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.** -In the `cmdr_data()` callback, the contents of `data` will always have at least the data returned by a CAPI -`/profile` query. 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. **But do not assume this -will always be the case**. +`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. -In the `capi_fleetcarrier()` callback, the contents of `data` will be the response from the CAPI `/fleetcarrier` query. 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. +#### Properties of CAPIData permitted for use by plugins -In all cases, `data` will include a `request_cmdr` entry, which will be 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. +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. **But do not assume this will always be the case**. | +| `source_host` | `str` | `SERVER_LIVE` \| `SERVER_BETA` \| `SERVER_LEGACY` the current calaxy 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 diff --git a/companion.py b/companion.py index f464e0d6..b7ccd093 100644 --- a/companion.py +++ b/companion.py @@ -68,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__() @@ -83,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 @@ -575,8 +577,7 @@ class EDMCCAPIRequest(EDMCCAPIReturn): self, capi_host: str, endpoint: str, query_time: int, tk_response_event: Optional[str] = None, - play_sound: bool = False, auto_update: bool = False, - cmdr: Optional[str] = None + play_sound: bool = False, auto_update: bool = False ): super().__init__( query_time=query_time, tk_response_event=tk_response_event, @@ -584,7 +585,6 @@ class EDMCCAPIRequest(EDMCCAPIReturn): ) self.capi_host: str = capi_host # The CAPI host to use. self.endpoint: str = endpoint # The CAPI query to perform. - self.cmdr: Optional[str] = cmdr # The CMDR name used for the request. class EDMCCAPIResponse(EDMCCAPIReturn): @@ -592,12 +592,10 @@ class EDMCCAPIResponse(EDMCCAPIReturn): def __init__( self, capi_data: CAPIData, - query_time: int, play_sound: bool = False, auto_update: bool = False, - cmdr: Optional[str] = None + query_time: int, play_sound: bool = False, auto_update: bool = False ): super().__init__(query_time=query_time, play_sound=play_sound, auto_update=auto_update) self.capi_data: CAPIData = capi_data # Frontier CAPI response, possibly augmented (station query) - self.capi_data['request_cmdr'] = cmdr # Inject the CMDR name used for the original request into the data class EDMCCAPIFailedRequest(EDMCCAPIReturn): @@ -821,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() @@ -997,8 +995,7 @@ class Session(object): capi_data=capi_data, query_time=query.query_time, play_sound=query.play_sound, - auto_update=query.auto_update, - cmdr=query.cmdr + auto_update=query.auto_update ) ) @@ -1046,8 +1043,7 @@ class Session(object): tk_response_event=tk_response_event, query_time=query_time, play_sound=play_sound, - auto_update=auto_update, - cmdr=monitor.cmdr + auto_update=auto_update ) ) @@ -1076,8 +1072,7 @@ class Session(object): tk_response_event=tk_response_event, query_time=query_time, play_sound=play_sound, - auto_update=auto_update, - cmdr=monitor.cmdr + auto_update=auto_update ) ) ###################################################################### From 5d1eb9e3b1f66eb56055881f3774db31bd696c6f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 24 Dec 2022 10:11:11 +0000 Subject: [PATCH 150/257] Fix "could be None" conditional for call to `plug.notify_journal_entry()` In testing the *first* hit on this does have `monitor.cmdr` set, but neither `monitor.system` or `monitor.station`. So: 1. Allow those to be `None` in the function signature, 2. Guard against only `monitor.cmdr` being falsey before the call. 3. Move the `if err:` to the same scope. --- EDMarketConnector.py | 10 +++++----- plug.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index b9c7bdf2..d6af828f 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1457,7 +1457,7 @@ class AppWindow(object): and config.get_int('output') & config.OUT_SHIP: monitor.export_ship() - if monitor.cmdr and monitor.system and monitor.station: + if monitor.cmdr: err = plug.notify_journal_entry( monitor.cmdr, monitor.is_beta, @@ -1467,10 +1467,10 @@ class AppWindow(object): monitor.state ) - if err: - self.status['text'] = err - if not config.get_int('hotkey_mute'): - hotkeymgr.play_bad() + 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 diff --git a/plug.py b/plug.py index 8e19a6cf..e0c69a44 100644 --- a/plug.py +++ b/plug.py @@ -286,7 +286,7 @@ def notify_prefs_changed(cmdr: str | None, 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]: From 81a8122c5971e922e951e10e3bd5780b034589d2 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 24 Dec 2022 10:15:41 +0000 Subject: [PATCH 151/257] Indent `if err:` check after plugin dashboard invocation Adding a mypy-make-happy conditional on the call above means `err` needs to be inside that as well. --- EDMarketConnector.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index d6af828f..5edae5a3 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1550,10 +1550,10 @@ class AppWindow(object): 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() + 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.""" From fc80d8ffd687e7bdf0eee6f20f73d7355d314c56 Mon Sep 17 00:00:00 2001 From: aussig Date: Sat, 24 Dec 2022 10:18:37 +0000 Subject: [PATCH 152/257] Revert "Fix for exceptions thrown on journal events" This reverts commit 754367618ff273b94ae459544a7c73b86a182499. --- EDMarketConnector.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 47a7110a..ad043c93 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1547,10 +1547,10 @@ class AppWindow(object): monitor.state ) - if err: - self.status['text'] = err - if not config.get_int('hotkey_mute'): - hotkeymgr.play_bad() + 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 From f6f122072bf500072ede4eafc5b2026d177eb43f Mon Sep 17 00:00:00 2001 From: aussig Date: Mon, 26 Dec 2022 11:20:37 +0000 Subject: [PATCH 153/257] Tweaks to plugins docs for fleetcarrier CAPI, including headings, typos and clarity on legacy galaxy --- PLUGINS.md | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index c9debd5b..e0e6f1fa 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -908,11 +908,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 CAPI 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,6 +941,8 @@ 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 | +#### 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 @@ -970,17 +972,16 @@ def capi_fleetcarrier(data): | :-------- | :--------------: | :------------------------------------------------------------------------------------------------------- | | `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 above. - -#### Properties of CAPIData permitted for use by plugins +`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. **But do not assume this will always be the case**. | -| `source_host` | `str` | `SERVER_LIVE` \| `SERVER_BETA` \| `SERVER_LEGACY` the current calaxy mode. | +| `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. @@ -989,12 +990,9 @@ 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): From 16055a311fdf195b9aebe796461b005998fa2df6 Mon Sep 17 00:00:00 2001 From: aussig Date: Mon, 26 Dec 2022 11:23:44 +0000 Subject: [PATCH 154/257] Typo in plugins docs --- PLUGINS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PLUGINS.md b/PLUGINS.md index e0e6f1fa..eb5cf57c 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -992,7 +992,7 @@ 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()`. Note that there is no legacy equivalent to `capi_fleetcarrier()`, so always use the `source_host` property to determine the user's galaxy. +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): From 20166f402fc223b4965a51e6959285bf7c3fcf1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Dec 2022 17:01:07 +0000 Subject: [PATCH 155/257] build(deps-dev): bump pre-commit from 2.20.0 to 2.21.0 Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.20.0 to 2.21.0. - [Release notes](https://github.com/pre-commit/pre-commit/releases) - [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md) - [Commits](https://github.com/pre-commit/pre-commit/compare/v2.20.0...v2.21.0) --- updated-dependencies: - dependency-name: pre-commit dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 4207743e..041a34e1 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -30,7 +30,7 @@ types-pkg-resources==0.1.3 autopep8==2.0.1 # Git pre-commit checking -pre-commit==2.20.0 +pre-commit==2.21.0 # HTML changelogs grip==4.6.1 From 95f6e0f7a0e07f6253a66320b7d3f6e47a69af0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Dec 2022 17:01:13 +0000 Subject: [PATCH 156/257] build(deps-dev): bump coverage[toml] from 7.0.0 to 7.0.1 Bumps [coverage[toml]](https://github.com/nedbat/coveragepy) from 7.0.0 to 7.0.1. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.0.0...7.0.1) --- updated-dependencies: - dependency-name: coverage[toml] dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 4207743e..23a0030b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -46,7 +46,7 @@ py2exe==0.13.0.0; sys_platform == 'win32' # Testing pytest==7.2.0 pytest-cov==4.0.0 # Pytest code coverage support -coverage[toml]==7.0.0 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs +coverage[toml]==7.0.1 # 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' From 18833c5e368a42893ec864f7737159087401f2aa Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 26 Dec 2022 19:48:38 +0000 Subject: [PATCH 157/257] plugins: Comment *why* the "load plugins that are packages" first is there It's *NOT* that it will actually load the plugin *as* a package, as the code explicitly only loads `load.py` still. --- plug.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plug.py b/plug.py index e0c69a44..92777acf 100644 --- a/plug.py +++ b/plug.py @@ -160,7 +160,10 @@ def load_plugins(master: tk.Tk) -> 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()) From 72c57900d289729e40cf2a94718052e13740374d Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 28 Dec 2022 12:11:52 +0000 Subject: [PATCH 158/257] updating submodules --- FDevIDs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FDevIDs b/FDevIDs index 726fb916..2aaf3cb0 160000 --- a/FDevIDs +++ b/FDevIDs @@ -1 +1 @@ -Subproject commit 726fb91654edb020491e57ce8c07041296645cd0 +Subproject commit 2aaf3cb023fc8c06e092efd0b81315c167f455f5 From 4a2401983da7909629b5e5c4b82846c85717f1b9 Mon Sep 17 00:00:00 2001 From: aussig Date: Thu, 29 Dec 2022 14:50:34 +0000 Subject: [PATCH 159/257] Add preference for enabling / disabling CAPI fleetcarrier endpoint --- EDMarketConnector.py | 2 +- prefs.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index eaba8797..cb704124 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1582,7 +1582,7 @@ class AppWindow(object): if not should_return: self.w.after(int(SERVER_RETRY * 1000), self.capi_request_data) - if entry['event'] in ('CarrierBuy', 'CarrierStats'): + if entry['event'] in ('CarrierBuy', 'CarrierStats') and config.get_int('capi_fleetcarrier') == 1: 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) diff --git a/prefs.py b/prefs.py index e5ab242b..b84e03e0 100644 --- a/prefs.py +++ b/prefs.py @@ -470,6 +470,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.IntVar(value=config.get_int('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() @@ -1244,6 +1263,8 @@ class PreferencesDialog(tk.Toplevel): else: config.set('journaldir', logdir) + config.set('capi_fleetcarrier', int(self.capi_fleetcarrier.get())) + if sys.platform in ('darwin', 'win32'): config.set('hotkey_code', self.hotkey_code) config.set('hotkey_mods', self.hotkey_mods) From 933520c5afc79951bd496796c48d2d933060d652 Mon Sep 17 00:00:00 2001 From: aussig Date: Fri, 30 Dec 2022 15:39:32 +0000 Subject: [PATCH 160/257] Switch to using a bool config value for fleetcarrier CAPI instead of int --- EDMarketConnector.py | 2 +- prefs.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index cb704124..2ce58201 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1582,7 +1582,7 @@ class AppWindow(object): if not should_return: self.w.after(int(SERVER_RETRY * 1000), self.capi_request_data) - if entry['event'] in ('CarrierBuy', 'CarrierStats') and config.get_int('capi_fleetcarrier') == 1: + 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) diff --git a/prefs.py b/prefs.py index b84e03e0..a356848b 100644 --- a/prefs.py +++ b/prefs.py @@ -471,7 +471,7 @@ class PreferencesDialog(tk.Toplevel): ).grid(column=2, pady=self.PADY, sticky=tk.EW, row=row.get()) # CAPI settings - self.capi_fleetcarrier = tk.IntVar(value=config.get_int('capi_fleetcarrier')) + 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() @@ -1263,7 +1263,7 @@ class PreferencesDialog(tk.Toplevel): else: config.set('journaldir', logdir) - config.set('capi_fleetcarrier', int(self.capi_fleetcarrier.get())) + config.set('capi_fleetcarrier', self.capi_fleetcarrier.get()) if sys.platform in ('darwin', 'win32'): config.set('hotkey_code', self.hotkey_code) From 0fe5e17b65fdd6152cb95d6a85d03532170823f2 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Dec 2022 16:25:25 +0000 Subject: [PATCH 161/257] CAPI: Fix `dump_capi_data()` for `/fleetcarrier` Still produces the system/station: `HIP 10792.Crimson Exchange.2022-12-30T16.22.39.json` But now also the FC: `FleetCarrier.X3F-N5Z.2022-12-30T16.24.01.json` --- companion.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/companion.py b/companion.py index b7ccd093..88bdd7e1 100644 --- a/companion.py +++ b/companion.py @@ -1125,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 = '' + 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 = '' + 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, From 3f91e57c7c6511a5f023c3de31ce4c68c77fdbfc Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Dec 2022 16:34:17 +0000 Subject: [PATCH 162/257] plugins/eddb: Fix `journal_entry()` and `new_data` types plug.py does `dict(entry)` before calling a plugin's `journal_entry()`, so `dict` is correct for `data`. Thus also use that for `new_data`'s type. --- plugins/eddb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/eddb.py b/plugins/eddb.py index 55ba4be3..59826a87 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -42,7 +42,7 @@ # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# import tkinter -from typing import TYPE_CHECKING, Any, Dict, Mapping, MutableMapping, Optional +from typing import TYPE_CHECKING, Any, Mapping, Optional import requests @@ -154,7 +154,7 @@ def prefs_changed(cmdr: str, is_beta: bool) -> None: def journal_entry( # noqa: CCR001 cmdr: str, is_beta: bool, system: str, station: str, - entry: MutableMapping[str, Any], + entry: dict[str, Any], state: Mapping[str, Any] ): """ @@ -169,7 +169,7 @@ def journal_entry( # noqa: CCR001 :return: None if no error, else an error string. """ should_return: bool - new_entry: Dict[str, Any] = {} + new_entry: dict[str, Any] = {} should_return, new_entry = killswitch.check_killswitch('plugins.eddb.journal', entry) if should_return: From 6b9ec285fda72a169aa7bbe34c7d300c2151811a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Dec 2022 16:43:58 +0000 Subject: [PATCH 163/257] plug.py: Use `x if x else y` not ` or `, & small type cleanup --- plug.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plug.py b/plug.py index d28ce4e6..5bc8c826 100644 --- a/plug.py +++ b/plug.py @@ -407,7 +407,7 @@ def notify_capidata( def notify_capi_fleetcarrierdata( data: companion.CAPIData -) -> Optional[str]: +) -> str | None: """ Send the latest CAPI Fleetcarrier data from the FD servers to each plugin. @@ -421,7 +421,7 @@ def notify_capi_fleetcarrierdata( try: # Pass a copy of the CAPIData in case the callee modifies it newerror = fc_callback(copy.deepcopy(data)) - error = error or newerror + error = error if error else newerror except Exception: logger.exception(f'Plugin "{plugin.name}" failed on receiving Fleetcarrier data') From 468a9effe5496b85b29d5bdef7bd102397a3d65d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Dec 2022 16:47:02 +0000 Subject: [PATCH 164/257] companion.py: Minor typing cleanup --- companion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/companion.py b/companion.py index 88bdd7e1..510510d5 100644 --- a/companion.py +++ b/companion.py @@ -1048,7 +1048,7 @@ class Session(object): ) def fleetcarrier( - self, query_time: int, tk_response_event: Optional[str] = None, + self, query_time: int, tk_response_event: str | None = None, play_sound: bool = False, auto_update: bool = False ) -> None: """ From ce4ae744342166ff2a220d9ba55f34707795471a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Dec 2022 18:10:36 +0000 Subject: [PATCH 165/257] update checks: Move setup of `self.updater` before menu entry Typing this as `update.Updater | None` and having the check `if self.updater is not None:` causes the menu entry to not even get added, because `import update` was coming later. I can't recall why that import/setup was later, but I might be about to find out again.... --- EDMarketConnector.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 2ce58201..9164a28c 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -592,11 +592,18 @@ 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 = None - self.menubar = tk.Menu() + # 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 + 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 @@ -649,8 +656,7 @@ class AppWindow(object): 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) - if self.updater is not None: - self.help_menu.add_command(command=lambda: self.updater.check_for_updates()) + self.help_menu.add_command(command=lambda: self.updater.check_for_updates()) self.help_menu.add_command(command=lambda: not self.HelpAbout.showing and self.HelpAbout(self.w)) @@ -766,16 +772,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) From 449e3e4ddc66b47a4ce450a5e3d622c7d1a964a9 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Dec 2022 18:13:57 +0000 Subject: [PATCH 166/257] update.py: Log when internal check finds no new version It just makes quick debugging easier. --- update.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/update.py b/update.py index bbd65ab2..272d217d 100644 --- a/update.py +++ b/update.py @@ -221,6 +221,9 @@ class Updater(object): status['text'] = newversion.title + ' is available' self.root.update_idletasks() + else: + logger.info("No new version available at this time") + def close(self) -> None: """ Handle the EDMarketConnector.AppWindow.onexit() request. From 80e2aee6bb3193b686f7f8e451b22c046e7dc8d3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Dec 2022 18:17:01 +0000 Subject: [PATCH 167/257] updates: Add comment about 'early' `import update` working after all Tested both under PyCharm debugging for 'internal', and py2exe-build .exe for 'external'. In both cases the 'Help' > 'Check for updates...' works. --- EDMarketConnector.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 9164a28c..fd5bcd5b 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -593,7 +593,9 @@ class AppWindow(object): sys.platform != 'win32' or isinstance(child, tk.Frame)) and 2 or 0) self.menubar = tk.Menu() - # Load updater after UI creation (for WinSparkle) + + # 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): From 0705d56bb49fee6fbfefaa705f68b426511278bb Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 31 Dec 2022 16:08:39 +0000 Subject: [PATCH 168/257] Properly name the main UI tk widgets Unfortunately we can't name the plugin ones, as that's entirely up to their `plugin_app()` code, and widget names can't be changed after creation. NB: Each `plugin_hr_X` frame is `grid()`'d to be *before* the plugin in question, despite being listed *after* in: >>> self.w.children['edmarketconnector'].children --- EDMarketConnector.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index fd5bcd5b..556660ce 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -523,15 +523,15 @@ 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: @@ -560,10 +560,14 @@ 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) if appitem: - tk.Frame(frame, highlightthickness=1).grid(columnspan=2, sticky=tk.EW) # separator + plugin_no += 1 + tk.Frame( + frame, highlightthickness=1, name=f"plugin_hr_{plugin_no}" + ).grid(columnspan=2, sticky=tk.EW) # separator 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) @@ -573,8 +577,20 @@ class AppWindow(object): appitem.grid(columnspan=2, sticky=tk.EW) # 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'), + 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) From ce1303e9e65035768b3d60265a1f9d8d1f705587 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 31 Dec 2022 16:16:52 +0000 Subject: [PATCH 169/257] UI: Make a frame to hold each plugin's UI NB: Currently breaks some core/internal plugin code, due to use of `parent.children` and the like. That will get addressed in subsequent commits. --- EDMarketConnector.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 556660ce..23136e97 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -562,7 +562,12 @@ class AppWindow(object): plugin_no = 0 for plugin in plug.PLUGINS: - appitem = plugin.get_app(frame) + # Per plugin frame + plugin_frame = tk.Frame( + frame, + name=f"plugin_{plugin_no + 1}" + ) + appitem = plugin.get_app(plugin_frame) if appitem: plugin_no += 1 tk.Frame( @@ -576,6 +581,9 @@ class AppWindow(object): else: appitem.grid(columnspan=2, sticky=tk.EW) + else: + plugin_frame.destroy() + # LANG: Update button in main window self.button = ttk.Button( frame, From f2de70bad6d5a56f255e37e0784332d388612452 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 31 Dec 2022 16:27:22 +0000 Subject: [PATCH 170/257] core plugins: Use `nametowidget()` to find system/station widgets As we're experimenting with per-plugin frames up a level `parent.children` would need to be `parent.parent.children`, but this way it will Just Work without knowledge of the hierarchy. --- plugins/eddb.py | 8 +++++--- plugins/edsm.py | 12 +++++++++--- plugins/inara.py | 8 +++++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/plugins/eddb.py b/plugins/eddb.py index 59826a87..a5d0593a 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -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 @@ -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 + # system label in main window + this.system_link = parent.nametowidget(f".{appname.lower()}.system") this.system = None this.system_address = None this.station = 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 diff --git a/plugins/edsm.py b/plugins/edsm.py index 635b3559..95d888d8 100644 --- a/plugins/edsm.py +++ b/plugins/edsm.py @@ -49,7 +49,7 @@ 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 @@ -250,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('<>', 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: diff --git a/plugins/inara.py b/plugins/inara.py index 15fdea5b..941ec8f2 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -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 @@ -218,8 +218,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('<>', update_location) this.system_link.bind_all('<>', update_ship) From 0fd835e9acdcecf2824ea4ff059347fadaf5b277 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 31 Dec 2022 16:49:29 +0000 Subject: [PATCH 171/257] core plugins: A little more 'children' fixup * eddn: Needs to find status text, although really there should be a helper function for this. * Removed commented out references to same in edsm and inara. --- plugins/eddn.py | 6 +++--- plugins/edsm.py | 1 - plugins/inara.py | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index 96c839ad..13bdf108 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -46,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 @@ -382,7 +382,7 @@ class EDDNSender: 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: """ @@ -2501,7 +2501,7 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]: # noqa: CCR001 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 diff --git a/plugins/edsm.py b/plugins/edsm.py index 95d888d8..9eb9167a 100644 --- a/plugins/edsm.py +++ b/plugins/edsm.py @@ -628,7 +628,6 @@ 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") diff --git a/plugins/inara.py b/plugins/inara.py index 941ec8f2..73ee482e 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -382,7 +382,6 @@ 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") From a842ce28c618fc1b99bb4bd9aa0a46bfd1c92350 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 31 Dec 2022 16:52:36 +0000 Subject: [PATCH 172/257] UI: Create a per-plugin frame in the main UI * This means all actual plugin UI will be children of this frame, rather than the main frame. --- EDMarketConnector.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 23136e97..13b4139f 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -536,7 +536,8 @@ class AppWindow(object): # 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 @@ -562,7 +563,11 @@ class AppWindow(object): plugin_no = 0 for plugin in plug.PLUGINS: - # Per plugin 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}" @@ -570,9 +575,11 @@ class AppWindow(object): appitem = plugin.get_app(plugin_frame) if appitem: plugin_no += 1 - tk.Frame( - frame, highlightthickness=1, name=f"plugin_hr_{plugin_no}" - ).grid(columnspan=2, sticky=tk.EW) # separator + plugin_sep.grid(columnspan=2, sticky=tk.EW) + ui_row = frame.grid_size()[1] + plugin_frame.grid( + row=ui_row, columnspan=2, sticky=tk.EW + ) 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) @@ -582,7 +589,9 @@ class AppWindow(object): 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( From 963b115e0e6d971a1e2e3c18bd20c895960aff0f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 31 Dec 2022 17:12:29 +0000 Subject: [PATCH 173/257] UI: Name the extra 'alternate' frames: titlebar and menubar These are used in the non-default themes, as the OS ones are hidden and replaced by them. They're created after the rest of the main UI, so come last in the 'children' list. --- EDMarketConnector.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 13b4139f..ffdb8ab9 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -718,11 +718,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('', self.drag_start) @@ -755,7 +759,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() From 991f69044cf9dbdaef3e63ee5328ebe9923b8ab0 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 31 Dec 2022 17:20:30 +0000 Subject: [PATCH 174/257] PLUGINS.md: Avoid an example implying plugins can set main status text The 'Error messages' section lays out how to get a message into the main UI status area, and it does *not* say to try setting it directly. --- PLUGINS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PLUGINS.md b/PLUGINS.md index eb5cf57c..cd0d47bc 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -1138,7 +1138,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 From 5fd4a68226f4a24b12d1849459e39680c7be9e70 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 1 Jan 2023 10:53:15 +0000 Subject: [PATCH 175/257] copyright: Bump end year to 2023 --- config/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/__init__.py b/config/__init__.py index ae2fad73..a2f05062 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -54,7 +54,7 @@ appcmdname = 'EDMC' # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() _static_appversion = '5.7.1-alpha0' _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 From 61ad75d52a44f3b26c4a93a61ea02e6900451ddd Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 2 Jan 2023 13:02:22 +0000 Subject: [PATCH 176/257] Configure per-plugin Frame the same as main Frame It was observed that some text in the EDMC-Canonn plugin was wrapping in this branch when the same text doesn't in `develop. So, tweaked the plugin_frame setup to match the main UI frame setup: * `tk.NSEW` not `tk.EW` - didn't fix the problem, but we should match this. * `.columnconfigure(1, weight=1)` - this actually fixed the problem. --- EDMarketConnector.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index ffdb8ab9..d901b448 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -578,8 +578,9 @@ class AppWindow(object): plugin_sep.grid(columnspan=2, sticky=tk.EW) ui_row = frame.grid_size()[1] plugin_frame.grid( - row=ui_row, columnspan=2, sticky=tk.EW + 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) From 7bfeb5ec621a965a17164fb753934b5268715f84 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 2 Jan 2023 14:05:07 +0000 Subject: [PATCH 177/257] Actually uncomment `plugin_frame.columnconfigure(1, weight=1)` It had been commented to test that it made a difference. --- EDMarketConnector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index d901b448..94d7ec07 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -580,7 +580,7 @@ class AppWindow(object): plugin_frame.grid( row=ui_row, columnspan=2, sticky=tk.NSEW ) - # plugin_frame.columnconfigure(1, weight=1) + 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) From dffb9c4e24b41a88e0605f5bc4488ee994e95837 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Jan 2023 17:01:01 +0000 Subject: [PATCH 178/257] build(deps): bump watchdog from 2.2.0 to 2.2.1 Bumps [watchdog](https://github.com/gorakhargosh/watchdog) from 2.2.0 to 2.2.1. - [Release notes](https://github.com/gorakhargosh/watchdog/releases) - [Changelog](https://github.com/gorakhargosh/watchdog/blob/master/changelog.rst) - [Commits](https://github.com/gorakhargosh/watchdog/compare/v2.2.0...v2.2.1) --- updated-dependencies: - dependency-name: watchdog dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8cc98823..5244e2f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ certifi==2022.12.7 requests==2.28.1 -watchdog==2.2.0 +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 From a4cd407b89540c43029e8dfe7381451d0785fde3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 11:39:47 +0000 Subject: [PATCH 179/257] Add Help > Troubleshooting / Report A Bug --- EDMarketConnector.py | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 94d7ec07..e5585e75 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -665,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) @@ -689,11 +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) @@ -926,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 @@ -944,10 +951,12 @@ 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' @@ -1757,6 +1766,15 @@ class AppWindow(object): """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') From 7d4118738be53fa2dd49c8b25ad58790ec63fdf3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 11:46:27 +0000 Subject: [PATCH 180/257] Add some missing LANG comments, as per script output --- EDMarketConnector.py | 2 +- plugins/edsm.py | 2 +- plugins/inara.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index e5585e75..180a6556 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -598,7 +598,7 @@ class AppWindow(object): self.button = ttk.Button( frame, name='update_button', - text=_('Update'), + text=_('Update'), # LANG: Main UI Update button width=28, default=tk.ACTIVE, state=tk.DISABLED diff --git a/plugins/edsm.py b/plugins/edsm.py index 9eb9167a..8975ff13 100644 --- a/plugins/edsm.py +++ b/plugins/edsm.py @@ -629,7 +629,7 @@ 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.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 '' diff --git a/plugins/inara.py b/plugins/inara.py index 73ee482e..ff87c881 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -383,7 +383,7 @@ 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.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 '' From fe38367e193c18aec029cfe3548cee0aa7eface2 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 11:48:18 +0000 Subject: [PATCH 181/257] Translations: Update en.template with latest script output Yes, we're just trusting it this time. --- L10n/en.template | 879 ++++++++++++++++++++++++----------------------- 1 file changed, 447 insertions(+), 432 deletions(-) diff --git a/L10n/en.template b/L10n/en.template index 6ed81d22..b0228e14 100644 --- a/L10n/en.template +++ b/L10n/en.template @@ -1,752 +1,767 @@ /* Language name */ "!Language" = "English"; -/* 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..." = "Sending data to 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" = "Error: Can't connect to 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" = "Send station data to the 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" = "Send system and scan data to the 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" = "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" = "Send flight log and Cmdr status to 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 credentials"; - -/* 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 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 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" = "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}" = "Error: 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" = "Error: Can't connect to 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" = "Send flight log and Cmdr status to 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 credentials"; - -/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; In files: inara.py:383; inara.py:386; */ -"Inara only accepts Live galaxy data" = "Inara only accepts Live galaxy data"; - -/* 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}" = "Error: 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='" = "Set the URL to use with coriolis.io ship loadouts. Note that this MUST end with '/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"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "Override Beta/Normal selection"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "Invalid Coriolis override mode!"; - -/* 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 Journal processing disabled. See Log."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "EDDN journal handler disabled. See Log."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "EDSM Handler disabled. See Log."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara disabled. See 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: No commander data returned"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "Override Beta/Normal Selection"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN Error: EDMC is too old for EDDN. Please update."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN Error: Validation Failed (EDMC Too Old?). See Log"; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "EDDN Error: Returned {STATUS} status code"; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "No 'Route' array in NavRoute.json contents"; - -/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */ -"Journal directory already locked" = "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." = "The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this."; - -/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */ -"Retry" = "Retry"; - -/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */ -"Ignore" = "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" = "Copy"; - -/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */ -"Update" = "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" = "Always on top"; - -/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */ -"Unknown" = "Unknown"; - -/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "Error: Check E:D journal file location"; - -/* 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" = "Ship"; - -/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */ -"Suit" = "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" = "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" = "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" = "Edit"; - -/* 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" = "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" = "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}" = "About {APP}"; - -/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */ -"Check for Updates..." = "Check for Updates..."; - -/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */ -"Save Raw Data..." = "Save Raw 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" = "Privacy Policy"; - -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */ -"Release Notes" = "Release Notes"; - -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */ -"Settings" = "Settings"; - -/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */ -"Exit" = "Exit"; - -/* 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..." = "Logging in..."; - -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */ -"Authentication successful" = "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!" = "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!" = "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!" = "Station doesn't have a market!"; - -/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "CAPI query aborted: Cmdr name unknown"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "CAPI query aborted: Game mode unknown"; - -/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; In files: EDMarketConnector.py:974; */ -"CAPI query aborted: GameVersion unknown" = "CAPI query aborted: GameVersion unknown"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "CAPI query aborted: Current system unknown"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "CAPI query aborted: In other-ship multi-crew"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "CAPI query aborted: CQC (Arena) detected"; - -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */ -"Fetching data..." = "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?!" = "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?!" = "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?!" = "What are you flying?!"; - -/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Frontier CAPI server error"; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI: Refreshing access token..."; - -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */ -"Last updated at %H:%M:%S" = "Last updated at %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" = "cooldown {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..." = "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." = "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."; - -/* 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 Without Python 3.x Support"; - -/* 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" = "Error: Frontier CAPI didn't respond"; -/* 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" = "Error: Frontier server is lagging"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "Docked but unknown station: EDO Settlement?"; -/* 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" = "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" = "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" = "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" = "Error: Couldn't check 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!" = "Error: customer_id doesn't match!"; -/* 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" = "Error: unable to get token"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "Frontier CAPI down for maintenance"; -/* 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 query failure"; -/* 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:1745; */ +"Update" = "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" = "Always on top"; + +/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */ +"Unknown" = "Unknown"; + +/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "Error: Check E:D journal file location"; + +/* 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:1484; */ +"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:1494; EDMarketConnector.py:1517; stats.py:405; */ +"Ship" = "Ship"; + +/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */ +"Suit" = "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" = "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:2261; */ +"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" = "Edit"; + +/* 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" = "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" = "Help"; + +/* EDMarketConnector.py: App menu entry on OSX; EDMarketConnector.py: Help > About App; In files: EDMarketConnector.py:928; EDMarketConnector.py:959; EDMarketConnector.py:1801; */ +"About {APP}" = "About {APP}"; + +/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */ +"Check for Updates..." = "Check for Updates..."; + +/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */ +"Save Raw Data..." = "Save Raw 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" = "Documentation"; + +/* EDMarketConnector.py: Help > Troubleshooting; In files: EDMarketConnector.py:934; EDMarketConnector.py:954; */ +"Troubleshooting" = "Troubleshooting"; + +/* EDMarketConnector.py: Help > Report A Bug; In files: EDMarketConnector.py:935; EDMarketConnector.py:955; */ +"Report A Bug" = "Report A Bug"; + +/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */ +"Privacy Policy" = "Privacy Policy"; + +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1835; */ +"Release Notes" = "Release Notes"; + +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2262; prefs.py:241; */ +"Settings" = "Settings"; + +/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */ +"Exit" = "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" = "Copy"; + +/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:977; */ +"Logging in..." = "Logging in..."; + +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:993; EDMarketConnector.py:1654; */ +"Authentication successful" = "Authentication successful"; + +/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1024; */ +"You're not docked at a station!" = "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:1032; */ +"Station doesn't have anything!" = "Station doesn't have anything!"; + +/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1037; */ +"Station doesn't have a market!" = "Station doesn't have a market!"; + +/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1075; EDMarketConnector.py:1161; */ +"CAPI query aborted: Cmdr name unknown" = "CAPI query aborted: Cmdr name unknown"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1081; */ +"CAPI query aborted: Game mode unknown" = "CAPI query aborted: Game mode unknown"; + +/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; In files: EDMarketConnector.py:1087; EDMarketConnector.py:1167; */ +"CAPI query aborted: GameVersion unknown" = "CAPI query aborted: GameVersion unknown"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1093; */ +"CAPI query aborted: Current system unknown" = "CAPI query aborted: Current system unknown"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1099; */ +"CAPI query aborted: In other-ship multi-crew" = "CAPI query aborted: In other-ship multi-crew"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1105; */ +"CAPI query aborted: CQC (Arena) detected" = "CAPI query aborted: CQC (Arena) detected"; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1126; EDMarketConnector.py:1176; */ +"Fetching data..." = "Fetching data..."; + +/* EDMarketConnector.py: No data was returned for the fleetcarrier from the Frontier CAPI; In files: EDMarketConnector.py:1216; */ +"CAPI: No fleetcarrier data returned" = "CAPI: No fleetcarrier data returned"; + +/* EDMarketConnector.py: We didn't have the fleetcarrier callsign when we should have; In files: EDMarketConnector.py:1220; */ +"CAPI: Fleetcarrier data incomplete" = "CAPI: Fleetcarrier data incomplete"; + +/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1239; */ +"CAPI: No commander data returned" = "CAPI: No commander data returned"; + +/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1243; stats.py:333; */ +"Who are you?!" = "Who are you?!"; + +/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1249; stats.py:341; */ +"Where are you?!" = "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:1256; stats.py:349; */ +"What are you flying?!" = "What are you flying?!"; + +/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1381; */ +"Frontier CAPI server error" = "Frontier CAPI server error"; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1387; */ +"CAPI: Refreshing access token..." = "CAPI: Refreshing access token..."; + +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1431; */ +"Last updated at %H:%M:%S" = "Last updated at %H:%M:%S"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1459; */ +"Fighter" = "Fighter"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1460; */ +"Gunner" = "Gunner"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1461; */ +"Helm" = "Helm"; + +/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1739; */ +"cooldown {SS}s" = "cooldown {SS}s"; + +/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1861; prefs.py:292; */ +"OK" = "OK"; + +/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1933; */ +"Shutting down..." = "Shutting down..."; + +/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2250:2256; */ +"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." = "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."; + +/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2260; 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:2271; */ +"EDMC: Plugins Without Python 3.x Support" = "EDMC: Plugins Without Python 3.x Support"; + +/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:208; */ +"Journal directory already locked" = "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." = "The new Journal Directory location is already locked.{CR}You can either attempt to resolve this and then Retry, or choose to Ignore this."; + +/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */ +"Retry" = "Retry"; + +/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */ +"Ignore" = "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" = "Default"; -/* 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='" = "Set the URL to use with coriolis.io ship loadouts. Note that this MUST end with '/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" = "Override Beta/Normal Selection"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "Invalid Coriolis override mode!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "EDDB Journal processing disabled. See 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" = "Error: Can't connect to EDDN"; + +/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN Error: EDMC is too old for EDDN. Please update."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN Error: Validation Failed (EDMC Too Old?). See Log"; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "EDDN Error: Returned {STATUS} status code"; + +/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */ +"Send station data to the Elite Dangerous Data Network" = "Send station data to the 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" = "Send system and scan data to the 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" = "Delay sending until docked"; + +/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "EDDN journal handler disabled. See Log."; + +/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */ +"Sending data to EDDN..." = "Sending data to EDDN..."; + +/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */ +"Send flight log and Cmdr status to EDSM" = "Send flight log and Cmdr status to 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 credentials"; + +/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */ +"Commander Name" = "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 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" = "None"; + +/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "EDSM Handler disabled. See Log."; + +/* edsm.py: EDSM - Only Live data; In files: edsm.py:632; */ +"EDSM only accepts Live galaxy data" = "EDSM only accepts Live galaxy data"; + +/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */ +"Error: EDSM {MSG}" = "Error: 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" = "Error: Can't connect to EDSM"; + +/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */ +"Send flight log and Cmdr status to Inara" = "Send flight log and Cmdr status to Inara"; + +/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */ +"Inara credentials" = "Inara credentials"; + +/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; inara.py: Inara - Only Live data; In files: inara.py:384; inara.py:386; */ +"Inara only accepts Live galaxy data" = "Inara only accepts Live galaxy data"; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "Inara disabled. See 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}" = "Error: 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" = "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" = "Market data in CSV format file"; -/* 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 Trade Dangerous format file"; -/* prefs.py: Settings > Output option; In files: prefs.py:373; */ +/* prefs.py: Settings > Output option; In files: prefs.py:360; */ "Ship loadout" = "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" = "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" = "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..." = "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..." = "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" = "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 journal file location"; -/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */ +/* prefs.py: Settings > Configuration - Label for CAPI section; In files: prefs.py:469; */ +"CAPI Settings" = "CAPI Settings"; + +/* prefs.py: Configuration - Enable or disable the Fleet Carrier CAPI calls; In files: prefs.py:475; */ +"Enable Fleetcarrier CAPI Queries" = "Enable Fleetcarrier CAPI Queries"; + +/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */ "Keyboard shortcut" = "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" = "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" = "Re-start {APP} to use shortcuts"; -/* 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} needs permission to use shortcuts"; -/* 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 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" = "Only when Elite: Dangerous is the active app"; -/* 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" = "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" = "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" = "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" = "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" = "Use alternate URL method"; -/* 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" = "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" = "Configuration"; -/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "Main UI privacy options"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "Hide private group name in UI"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "Hide multi-crew captain name"; -/* 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" = "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" = "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" = "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" = "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" = "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" = "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" = "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 means Default{CR}Restart Required for{CR}changes to take effect!"; -/* 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" = "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 means fully opaque.{CR}Window is updated in real time"; -/* 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" = "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" = "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" = "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" = "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" = "Tip: You can disable a plugin by{CR}adding '{EXT}' to its folder name"; -/* 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" = "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:" = "Plugins Without Python 3.x Support:"; -/* 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 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" = "Disabled 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" = "Loan"; -/* stats.py: Top rank; In files: stats.py:65; */ +/* stats.py: Top rank; In files: stats.py:63; */ "Elite" = "Elite"; -/* stats.py: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Elite I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Elite II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Elite III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Elite IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Elite V"; -/* 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:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "Mercenary"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "Exobiologist"; -/* 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: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "Mostly Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Rookie"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Soldier"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Gunslinger"; -/* stats.py: Mercenary rank; In files: stats.py:129; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ "Warrior" = "Warrior"; -/* stats.py: Mercenary rank; In files: stats.py:131; */ +/* stats.py: Mercenary rank; In files: stats.py:129; */ "Deadeye" = "Deadeye"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:135; */ +/* stats.py: Exobiologist rank; In files: stats.py:133; */ "Mostly Directionless" = "Mostly Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:136; */ +/* stats.py: Exobiologist rank; In files: stats.py:134; */ "Compiler" = "Compiler"; -/* stats.py: Exobiologist rank; In files: stats.py:137; */ +/* stats.py: Exobiologist rank; In files: stats.py:135; */ "Collector" = "Collector"; -/* stats.py: Exobiologist rank; In files: stats.py:138; */ +/* stats.py: Exobiologist rank; In files: stats.py:136; */ "Cataloguer" = "Cataloguer"; -/* stats.py: Exobiologist rank; In files: stats.py:139; */ +/* stats.py: Exobiologist rank; In files: stats.py:137; */ "Taxonomist" = "Taxonomist"; -/* stats.py: Exobiologist rank; In files: stats.py:140; */ +/* stats.py: Exobiologist rank; In files: stats.py:138; */ "Ecologist" = "Ecologist"; -/* stats.py: Exobiologist rank; In files: stats.py:141; */ +/* stats.py: Exobiologist rank; In files: stats.py:139; */ "Geneticist" = "Geneticist"; -/* 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: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "Status: Don't yet know your Commander name"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "Status: No CAPI data yet"; -/* 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" = "Value"; -/* stats.py: Status dialog title; In files: stats.py:422; */ +/* stats.py: Status dialog title; In files: stats.py:418; */ "Ships" = "Ships"; From c6ec7cc362dea136e07b528e62a6815b0c74044e Mon Sep 17 00:00:00 2001 From: aussig Date: Tue, 3 Jan 2023 15:07:52 +0000 Subject: [PATCH 182/257] Add some string localisations and improve lang comments. --- EDMarketConnector.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 180a6556..93b51132 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -969,7 +969,8 @@ class AppWindow(object): should_return, new_data = killswitch.check_killswitch('capi.auth', {}) if should_return: logger.warning('capi.auth has been disabled via killswitch. Returning.') - self.status['text'] = 'CAPI auth disabled by killswitch' + # LANG: CAPI auth aborted because of killswitch + self.status['text'] = _('CAPI auth disabled by killswitch') return if not self.status['text']: @@ -1062,7 +1063,8 @@ class AppWindow(object): should_return, new_data = killswitch.check_killswitch('capi.auth', {}) if should_return: logger.warning('capi.auth has been disabled via killswitch. Returning.') - self.status['text'] = 'CAPI auth disabled by killswitch' + # LANG: CAPI auth query aborted because of killswitch + self.status['text'] = _('CAPI auth disabled by killswitch') hotkeymgr.play_bad() return @@ -1151,19 +1153,20 @@ class AppWindow(object): should_return, new_data = killswitch.check_killswitch('capi.request.fleetcarrier', {}) if should_return: logger.warning('capi.fleetcarrier has been disabled via killswitch. Returning.') - self.status['text'] = 'CAPI fleetcarrier disabled by killswitch' + # 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 queries aborted because Cmdr name is 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 queries aborted because GameVersion unknown + # LANG: CAPI fleetcarrier query aborted because GameVersion unknown self.status['text'] = _('CAPI query aborted: GameVersion unknown') return From 4096fa14296015d4fe803767845f417fc0f5dc90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 17:00:58 +0000 Subject: [PATCH 183/257] build(deps-dev): bump coverage[toml] from 7.0.1 to 7.0.2 Bumps [coverage[toml]](https://github.com/nedbat/coveragepy) from 7.0.1 to 7.0.2. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.0.1...7.0.2) --- updated-dependencies: - dependency-name: coverage[toml] dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 5b2e24d9..597a3358 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -46,7 +46,7 @@ py2exe==0.13.0.0; sys_platform == 'win32' # Testing pytest==7.2.0 pytest-cov==4.0.0 # Pytest code coverage support -coverage[toml]==7.0.1 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs +coverage[toml]==7.0.2 # 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' From 5daabc57ef95ab317919fe68c79411fd408d787e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 4 Jan 2023 15:08:55 +0000 Subject: [PATCH 184/257] translations: Updated l10n/en.template via script --- L10n/en.template | 80 ++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/L10n/en.template b/L10n/en.template index b0228e14..96944a63 100644 --- a/L10n/en.template +++ b/L10n/en.template @@ -34,7 +34,7 @@ /* companion.py: Frontier CAPI data retrieval failed; In files: companion.py:856; */ "Frontier CAPI query failure" = "Frontier CAPI query failure"; -/* EDMarketConnector.py: Main UI Update button; EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:601; EDMarketConnector.py:919; EDMarketConnector.py:1745; */ +/* 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" = "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; */ @@ -49,10 +49,10 @@ /* 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:1484; */ +/* 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:1494; EDMarketConnector.py:1517; stats.py:405; */ +/* 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" = "Ship"; /* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */ @@ -64,7 +64,7 @@ /* 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:2261; */ +/* 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; */ @@ -79,7 +79,7 @@ /* 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:1801; */ +/* 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}" = "About {APP}"; /* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */ @@ -103,10 +103,10 @@ /* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */ "Privacy Policy" = "Privacy Policy"; -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1835; */ +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */ "Release Notes" = "Release Notes"; -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2262; prefs.py:241; */ +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */ "Settings" = "Settings"; /* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */ @@ -115,94 +115,100 @@ /* 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" = "Copy"; -/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:977; */ +/* EDMarketConnector.py: CAPI auth aborted because of killswitch; EDMarketConnector.py: CAPI auth query aborted because of killswitch; In files: EDMarketConnector.py:973; EDMarketConnector.py:1067; */ +"CAPI auth disabled by killswitch" = "CAPI auth disabled by killswitch"; + +/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */ "Logging in..." = "Logging in..."; -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:993; EDMarketConnector.py:1654; */ +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */ "Authentication successful" = "Authentication successful"; -/* EDMarketConnector.py: Player is not docked at a station, when we expect them to be; In files: EDMarketConnector.py:1024; */ +/* 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!" = "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:1032; */ +/* 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 doesn't have anything!"; -/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1037; */ +/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */ "Station doesn't have a market!" = "Station doesn't have a market!"; -/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1075; EDMarketConnector.py:1161; */ +/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ "CAPI query aborted: Cmdr name unknown" = "CAPI query aborted: Cmdr name unknown"; -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1081; */ +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ "CAPI query aborted: Game mode unknown" = "CAPI query aborted: Game mode unknown"; -/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; In files: EDMarketConnector.py:1087; EDMarketConnector.py:1167; */ +/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because GameVersion unknown; In files: EDMarketConnector.py:1089; EDMarketConnector.py:1170; */ "CAPI query aborted: GameVersion unknown" = "CAPI query aborted: GameVersion unknown"; -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1093; */ +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ "CAPI query aborted: Current system unknown" = "CAPI query aborted: Current system unknown"; -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1099; */ +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ "CAPI query aborted: In other-ship multi-crew" = "CAPI query aborted: In other-ship multi-crew"; -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1105; */ +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ "CAPI query aborted: CQC (Arena) detected" = "CAPI query aborted: CQC (Arena) detected"; -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1126; EDMarketConnector.py:1176; */ +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ "Fetching data..." = "Fetching data..."; -/* EDMarketConnector.py: No data was returned for the fleetcarrier from the Frontier CAPI; In files: EDMarketConnector.py:1216; */ +/* EDMarketConnector.py: CAPI fleetcarrier query aborted because of killswitch; In files: EDMarketConnector.py:1157; */ +"CAPI fleetcarrier disabled by killswitch" = "CAPI fleetcarrier disabled by killswitch"; + +/* EDMarketConnector.py: No data was returned for the fleetcarrier from the Frontier CAPI; In files: EDMarketConnector.py:1219; */ "CAPI: No fleetcarrier data returned" = "CAPI: No fleetcarrier data returned"; -/* EDMarketConnector.py: We didn't have the fleetcarrier callsign when we should have; In files: EDMarketConnector.py:1220; */ +/* EDMarketConnector.py: We didn't have the fleetcarrier callsign when we should have; In files: EDMarketConnector.py:1223; */ "CAPI: Fleetcarrier data incomplete" = "CAPI: Fleetcarrier data incomplete"; -/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1239; */ +/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */ "CAPI: No commander data returned" = "CAPI: No commander data returned"; -/* EDMarketConnector.py: We didn't have the commander name when we should have; stats.py: Unknown commander; In files: EDMarketConnector.py:1243; stats.py:333; */ +/* 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?!" = "Who are you?!"; -/* EDMarketConnector.py: We don't know where the commander is, when we should; stats.py: Unknown location; In files: EDMarketConnector.py:1249; stats.py:341; */ +/* 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?!" = "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:1256; stats.py:349; */ +/* 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?!" = "What are you flying?!"; -/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1381; */ +/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ "Frontier CAPI server error" = "Frontier CAPI server error"; -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1387; */ +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ "CAPI: Refreshing access token..." = "CAPI: Refreshing access token..."; -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1431; */ +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */ "Last updated at %H:%M:%S" = "Last updated at %H:%M:%S"; -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1459; */ +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */ "Fighter" = "Fighter"; -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1460; */ +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */ "Gunner" = "Gunner"; -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1461; */ +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */ "Helm" = "Helm"; -/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1739; */ +/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */ "cooldown {SS}s" = "cooldown {SS}s"; -/* EDMarketConnector.py: Generic 'OK' button label; prefs.py: 'OK' button on Settings/Preferences window; In files: EDMarketConnector.py:1861; prefs.py:292; */ +/* 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:1933; */ +/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1936; */ "Shutting down..." = "Shutting down..."; -/* EDMarketConnector.py: Popup-text about 'active' plugins without Python 3.x support; In files: EDMarketConnector.py:2250:2256; */ +/* 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." = "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."; -/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2260; prefs.py:986; */ +/* 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:2271; */ +/* 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 Without Python 3.x Support"; /* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:208; */ From 5e84205e322398e7e5036fc9f0305752b3bb207b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Jan 2023 17:01:34 +0000 Subject: [PATCH 185/257] build(deps-dev): bump coverage[toml] from 7.0.2 to 7.0.3 Bumps [coverage[toml]](https://github.com/nedbat/coveragepy) from 7.0.2 to 7.0.3. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.0.2...7.0.3) --- updated-dependencies: - dependency-name: coverage[toml] dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 597a3358..ab33ddc8 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -46,7 +46,7 @@ py2exe==0.13.0.0; sys_platform == 'win32' # Testing pytest==7.2.0 pytest-cov==4.0.0 # Pytest code coverage support -coverage[toml]==7.0.2 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs +coverage[toml]==7.0.3 # 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' From 881d6893317106a49c354874b8c1c4880cc9c0c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Jan 2023 17:01:28 +0000 Subject: [PATCH 186/257] build(deps-dev): bump coverage[toml] from 7.0.3 to 7.0.4 Bumps [coverage[toml]](https://github.com/nedbat/coveragepy) from 7.0.3 to 7.0.4. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.0.3...7.0.4) --- updated-dependencies: - dependency-name: coverage[toml] dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index ab33ddc8..38c4977f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -46,7 +46,7 @@ py2exe==0.13.0.0; sys_platform == 'win32' # Testing pytest==7.2.0 pytest-cov==4.0.0 # Pytest code coverage support -coverage[toml]==7.0.3 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs +coverage[toml]==7.0.4 # 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' From 596df0f987fbbbd0cdbba056b70737b2b5e4cb9d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 10 Jan 2023 11:49:58 +0000 Subject: [PATCH 187/257] CAPI 'Save Raw Data': Add '.' between system and station names in filename It's apparently *always* just mushed them together, but that's really crap. --- EDMarketConnector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 93b51132..13d1bd44 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1898,7 +1898,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.system}.{monitor.station}.{timestamp}' ) if not f: return From 6b38de10809fa81845c53da318958808ccdcb2bd Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 10 Jan 2023 14:04:41 +0000 Subject: [PATCH 188/257] .desktop: Add a file, and adjust icon filename to suit 1. `io.edcd.EDMarketConnector.desktop` based on the flathub one, but with reference to v1.5 of the spec (linked in a file comment). 2. As the Icon is specified using `io.edcd.EDMarketConnector`, not only `EDMarketConnector`, renamed the .png file and updated the single code reference to it. --- EDMarketConnector.py | 2 +- io.edcd.EDMarketConnector.desktop | 13 +++++++++++++ ...tConnector.png => io.edcd.EDMarketConnector.png | Bin 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 io.edcd.EDMarketConnector.desktop rename EDMarketConnector.png => io.edcd.EDMarketConnector.png (100%) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 13d1bd44..fe31304d 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -509,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( diff --git a/io.edcd.EDMarketConnector.desktop b/io.edcd.EDMarketConnector.desktop new file mode 100644 index 00000000..472c7add --- /dev/null +++ b/io.edcd.EDMarketConnector.desktop @@ -0,0 +1,13 @@ +#!/usr/bin/env xdg-open +[Desktop Entry] +Type=Application +# Ref: +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 diff --git a/EDMarketConnector.png b/io.edcd.EDMarketConnector.png similarity index 100% rename from EDMarketConnector.png rename to io.edcd.EDMarketConnector.png From b630445315b71f5c422a159d88af87cd2662bae0 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 10 Jan 2023 14:59:54 +0000 Subject: [PATCH 189/257] Linux: Add install/setup and startup script This *should* allow for easy setup to work on any XDG-compliant desktop environment. Just run `scripts/linux-setup.sh` and it will: 1. Determine the 'root' directory of the EDMarketConnector source you're using. 2. Check you have `${HOME}/bin` in PATH and it exists as a directory. 3. Copy `scripts/edmarketconnector.sh` to there, replacing the string `EDMC_PATH` with the 'root' directory. 4. Copy .png (icon) and .desktop files into ~/.local/share/... locations. Then the desktop environment should have a menu entry for "E:D Market Connector", which attempts to run `edmarketconnector`, which should now be the shell script present in ${HOME}/bin. --- scripts/edmarketconnector.sh | 8 ++++ scripts/linux-setup.sh | 74 ++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 scripts/edmarketconnector.sh create mode 100644 scripts/linux-setup.sh diff --git a/scripts/edmarketconnector.sh b/scripts/edmarketconnector.sh new file mode 100644 index 00000000..3505184a --- /dev/null +++ b/scripts/edmarketconnector.sh @@ -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 diff --git a/scripts/linux-setup.sh b/scripts/linux-setup.sh new file mode 100644 index 00000000..fb9ee393 --- /dev/null +++ b/scripts/linux-setup.sh @@ -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" +########################################################################### From bc610f618d59edab7d6705043f321794a795c6ce Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 11:24:30 +0000 Subject: [PATCH 190/257] sub-modules: Change coriolis-data to an https URL, not git@ Someone cloning shouldn't *need* a github account in order to get the sub-modules. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index b844f49e..cd89b465 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "coriolis-data"] path = coriolis-data - url = git@github.com:EDCD/coriolis-data.git + url = https://github.com/EDCD/coriolis-data.git [submodule "FDevIDs"] path = FDevIDs url = https://github.com/EDCD/FDevIDs.git From a67609696c7699ee529055d9bf11c16e22a69d23 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 11:36:54 +0000 Subject: [PATCH 191/257] windows-build: Properly name the build job --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 93091a7c..a64c5306 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: jobs: - test: + windows_build: name: Build EDMC runs-on: windows-2019 From c8e6285a136347e87d0b89bc71688b342be6b73f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 12:05:53 +0000 Subject: [PATCH 192/257] windows-build: Create a custom release .zip --- .github/workflows/windows-build.yml | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index a64c5306..232a51e7 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -7,7 +7,20 @@ on: workflow_dispatch: jobs: + variables: + outputs: + sem_ver: ${{ steps.var.outputs.sem_ver }} + 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\/', '')) + windows_build: + needs: [variables] name: Build EDMC runs-on: windows-2019 @@ -40,11 +53,20 @@ jobs: run: | python Build-exe-and-msi.py + - name: Make zip archive + uses: thedoctor0/zip-release@main + with: + type: 'zip' + filename: 'EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.zip' + exclusions: 'EDMarketConnector-release-*.zip .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data/* img/* pyproject.toml scripts/* tests/* wix/*' + - name: Upload build files 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 @@ -60,7 +82,7 @@ jobs: path: ./ - name: Hash files - run: sha256sum EDMarketConnector_win*.msi > ./hashes.sum + run: sha256sum EDMarketConnector_win*.msi EDMarketConnector-release*.zip > ./hashes.sum - name: Create Draft Release uses: "softprops/action-gh-release@v1" @@ -71,4 +93,5 @@ jobs: discussion_category_name: "Announcement" files: | ./EDMarketConnector_win*.msi + ./EDMarketConnector-release-*.zip ./hashes.sum From c48cfeca5dd7b2368850908600233d3dd4b4ff99 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 12:12:30 +0000 Subject: [PATCH 193/257] windows-build: Fix 'needs' reference to windows_build job --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 232a51e7..127fa243 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -71,7 +71,7 @@ jobs: release: name: Release new version runs-on: ubuntu-latest - needs: test + needs: windows_build if: "${{ github.event_name != 'workflow_dispatch' }}" steps: From 35b5a90409b03117d411ac1a06796810d8da6056 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 12:27:17 +0000 Subject: [PATCH 194/257] windows-build: Custom zip: Include top-level directory, and exclude more --- .github/workflows/windows-build.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 127fa243..6ed99fd1 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -57,8 +57,10 @@ jobs: uses: thedoctor0/zip-release@main with: type: 'zip' + directory: '..' + path: 'EDMarketConnector' filename: 'EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.zip' - exclusions: 'EDMarketConnector-release-*.zip .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data/* img/* pyproject.toml scripts/* tests/* wix/*' + exclusions: 'dist.win32/* dist.win32 __pycache__/* __pycache__ .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data/* coriolis-data/.??* coriolis-data img/* img out/* out out.zip pyproject.toml scripts/* scripts tests/* tests wix/* wix WinSparkle.*' - name: Upload build files uses: actions/upload-artifact@v3 @@ -66,7 +68,7 @@ jobs: name: Built files path: | EDMarketConnector_win*.msi - EDMarketConnector-release-*.zip + ../EDMarketConnector-release-*.zip release: name: Release new version From 2531e6de23cb8e58561ae8504e4ed8d2a0944bd8 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 12:38:08 +0000 Subject: [PATCH 195/257] windows-build: Can't use relative path for upload-artifact So, let's *hope* that zip-release still puts the .zip it creates in the main directory, despite being told to create it from the parent. --- .github/workflows/windows-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 6ed99fd1..480e54ca 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -60,7 +60,7 @@ jobs: directory: '..' path: 'EDMarketConnector' filename: 'EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.zip' - exclusions: 'dist.win32/* dist.win32 __pycache__/* __pycache__ .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data/* coriolis-data/.??* coriolis-data img/* img out/* out out.zip pyproject.toml scripts/* scripts tests/* tests wix/* wix WinSparkle.*' + exclusions: 'EDMarketConnector-release-*.zip dist.win32/* dist.win32 __pycache__/* __pycache__ .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data/* coriolis-data/.??* coriolis-data img/* img out/* out out.zip pyproject.toml scripts/* scripts tests/* tests wix/* wix WinSparkle.*' - name: Upload build files uses: actions/upload-artifact@v3 @@ -68,7 +68,7 @@ jobs: name: Built files path: | EDMarketConnector_win*.msi - ../EDMarketConnector-release-*.zip + EDMarketConnector-release-*.zip release: name: Release new version From 531c839d136c816320e6640a2b5fad6973b3f96e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 12:46:28 +0000 Subject: [PATCH 196/257] windows-build: Specify custom zip to be in the 'root' directory zip-release does indeed create this in `directory`, so we need to specify it should be *in* the 'root' directory that we're including *in* the zip file. --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 480e54ca..958e5bf8 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -59,7 +59,7 @@ jobs: type: 'zip' directory: '..' path: 'EDMarketConnector' - filename: 'EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.zip' + filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.zip' exclusions: 'EDMarketConnector-release-*.zip dist.win32/* dist.win32 __pycache__/* __pycache__ .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data/* coriolis-data/.??* coriolis-data img/* img out/* out out.zip pyproject.toml scripts/* scripts tests/* tests wix/* wix WinSparkle.*' - name: Upload build files From 0c0c14166deeeca411e2af51745036cbfab80635 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 12:58:05 +0000 Subject: [PATCH 197/257] windows-build: custom zip exclusions need 'root' prefix Also, comment out exactly what we're doing in the zip-release configuration, and why. --- .github/workflows/windows-build.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 958e5bf8..148e8048 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -57,10 +57,18 @@ jobs: 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' - exclusions: 'EDMarketConnector-release-*.zip dist.win32/* dist.win32 __pycache__/* __pycache__ .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data/* coriolis-data/.??* coriolis-data img/* img out/* out out.zip pyproject.toml scripts/* scripts tests/* tests wix/* wix WinSparkle.*' + # 4. And all the exclusions need to be prefixed with the 'root' + # directory. + exclusions: 'EDMarketConnector/EDMarketConnector-release-*.zip EDMarketConnector/dist.win32/* EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/* EDMarketConnector/__pycache__ 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/coriolis-data/.??* EDMarketConnector/coriolis-data EDMarketConnector/img/* EDMarketConnector/img EDMarketConnector/out/* EDMarketConnector/out EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/* EDMarketConnector/scripts EDMarketConnector/tests/* EDMarketConnector/tests EDMarketConnector/wix/* EDMarketConnector/wix EDMarketConnector/WinSparkle.*' - name: Upload build files uses: actions/upload-artifact@v3 From 804b450c82b4b6caa359f9d9c4594fecb25f0c5d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 13:19:04 +0000 Subject: [PATCH 198/257] windows-build: Custom zip: Reduce exclusions It *seems* we don't need to specify both a directory and its contents. Also, hopefully this will fix the: Creating zip archive... Command Line Error: Unknown switch: - which the last run got. That was where the 'root' directory prefix was added to all exclusions. Maybe the commandline got too long ? --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 148e8048..f2eda9fd 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -68,7 +68,7 @@ jobs: filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.zip' # 4. And all the exclusions need to be prefixed with the 'root' # directory. - exclusions: 'EDMarketConnector/EDMarketConnector-release-*.zip EDMarketConnector/dist.win32/* EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/* EDMarketConnector/__pycache__ 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/coriolis-data/.??* EDMarketConnector/coriolis-data EDMarketConnector/img/* EDMarketConnector/img EDMarketConnector/out/* EDMarketConnector/out EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/* EDMarketConnector/scripts EDMarketConnector/tests/* EDMarketConnector/tests EDMarketConnector/wix/* EDMarketConnector/wix EDMarketConnector/WinSparkle.*' + exclusions: 'EDMarketConnector/EDMarketConnector-release-*.zip EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/ 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/out/ EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/ EDMarketConnector/WinSparkle.*' - name: Upload build files uses: actions/upload-artifact@v3 From 5713a2e11cb6caaae596c3cfb54f323ff9cee733 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jan 2023 17:01:28 +0000 Subject: [PATCH 199/257] build(deps-dev): bump coverage[toml] from 7.0.4 to 7.0.5 Bumps [coverage[toml]](https://github.com/nedbat/coveragepy) from 7.0.4 to 7.0.5. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/7.0.4...7.0.5) --- updated-dependencies: - dependency-name: coverage[toml] dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 38c4977f..6a0ace7f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -46,7 +46,7 @@ py2exe==0.13.0.0; sys_platform == 'win32' # Testing pytest==7.2.0 pytest-cov==4.0.0 # Pytest code coverage support -coverage[toml]==7.0.4 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs +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' From 64b1a4afd6c2ca258364dfd946ae0ec643689c0b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Wed, 11 Jan 2023 18:10:18 +0000 Subject: [PATCH 200/257] windows-build/custom zip: Add comment about the "too long args" issue --- .github/workflows/windows-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index f2eda9fd..70cca876 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -68,6 +68,8 @@ jobs: 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-*.zip EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/ 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/out/ EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/ EDMarketConnector/WinSparkle.*' - name: Upload build files From 6d6f3b057fde87add79a006b32e554dcf0657fdd Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 12:02:42 +0000 Subject: [PATCH 201/257] typing: Use ` | None`, not `Optional[...]` --- monitor.py | 58 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/monitor.py b/monitor.py index 126e04c7..bcac1351 100644 --- a/monitor.py +++ b/monitor.py @@ -14,7 +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 TYPE_CHECKING, Any, BinaryIO, MutableMapping from typing import OrderedDict as OrderedDictT from typing import Tuple @@ -91,11 +91,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 +112,27 @@ 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.planet: str | None = None + self.system: str | None = None + self.station: str | None = None + self.station_marketid: int | None = None + self.stationtype: str | None = None + self.coordinates: Tuple[float, float, float] | None = None + self.systemaddress: int | None = None + self.systempopulation: int | 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 @@ -274,7 +274,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. @@ -455,7 +455,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 @@ -1918,7 +1918,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 +1955,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. @@ -2051,7 +2051,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. @@ -2250,7 +2250,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 +2276,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 +2348,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 From 6bd0b042b1e01cd918a1d14f15637a12254d0f93 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 12:05:45 +0000 Subject: [PATCH 202/257] monitor.py: typing: Don't use List or Dict --- monitor.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/monitor.py b/monitor.py index bcac1351..bd5d2d65 100644 --- a/monitor.py +++ b/monitor.py @@ -144,7 +144,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 @@ -1955,7 +1955,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below return item.capitalize() - def get_entry(self) -> MutableMapping[str, Any | None]: + def get_entry(self) -> MutableMapping[str, Any] | None: """ Pull the next Journal event from the event_queue. @@ -2051,7 +2051,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below return False - def ship(self, timestamped=True) -> MutableMapping[str, Any | None]: + def ship(self, timestamped=True) -> MutableMapping[str, Any] | None: """ Produce a subset of data for the current ship. @@ -2188,7 +2188,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 +2209,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 +2250,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below return slots - def _parse_navroute_file(self) -> dict[str, Any | None]: + 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 +2276,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below return data - def _parse_fcmaterials_file(self) -> dict[str, Any | None]: + 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 +2348,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self._last_navroute_journal_timestamp = None return True - def __fcmaterials_retry(self) -> Dict[str, Any | None]: + def __fcmaterials_retry(self) -> dict[str, Any] | None: """Retry reading FCMaterials files.""" if self._fcmaterials_retries_remaining == 0: return None From 86b0aa45504ced2efa44af93056eceed8a0a1988 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 15:08:47 +0000 Subject: [PATCH 203/257] monitor: Track all System and Body state in monitor.state * Minor grammar edit only in PLUGINS.md (I was checking if it explicitly stated what data is expected in the synthetic 'StartUp' event, it doesn't). * First changes to move some monitor properties into the monitor.state dictionary. This is for system or body data. * Re-factored the generation of 'StartUp' event into `EDLogs.synthesize_startup_event()`. It's done in two places, so was anti-DRY. * In general any bulk setting of system & body data is now done in the same order for comparison clarity. * A little of the location tracking has been duplicated from plugins/eddn.py. This is with a view to switching *it* to using the state version. --- PLUGINS.md | 2 +- monitor.py | 181 ++++++++++++++++++++++++++---------------------- plugins/eddn.py | 9 +++ 3 files changed, 108 insertions(+), 84 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index cd0d47bc..0378ef96 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -771,7 +771,7 @@ ___ 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 diff --git a/monitor.py b/monitor.py index bd5d2d65..57beb124 100644 --- a/monitor.py +++ b/monitor.py @@ -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, MutableMapping -from typing import OrderedDict as OrderedDictT -from typing import Tuple +from typing import TYPE_CHECKING, Any, BinaryIO, MutableMapping, Tuple if TYPE_CHECKING: import tkinter @@ -118,14 +116,14 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode: str | None = None self.group: str | None = None self.cmdr: str | None = None - self.planet: str | None = None self.system: str | None = None + self.systemaddress: int | None = None + self.coordinates: Tuple[float, float, float] | None = None + self.systempopulation: int | None = None + self.planet: str | None = None self.station: str | None = None self.station_marketid: int | None = None self.stationtype: str | None = None - self.coordinates: Tuple[float, float, float] | None = None - self.systemaddress: int | None = None - self.systempopulation: int | None = None self.started: int | None = None # Timestamp of the LoadGame event self._navroute_retries_remaining = 0 @@ -195,7 +193,9 @@ 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, 'Body': None, + 'BodyID': None, 'BodyType': None, 'NavRoute': None, @@ -306,19 +306,19 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode = None self.group = None self.cmdr = None - self.planet = None self.system = None + self.state['SystemAddress'] = self.systemaddress = None + self.coordinates = None + self.planet = self.state['Body'] = None + self.state['BodyID'] = None + self.state['BodyType'] = None self.station = None self.station_marketid = None self.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()') @@ -416,24 +416,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below if self.live: if self.game_was_running: # 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=(', ', ':'))) @@ -534,6 +517,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.system, + 'StarPos': self.coordinates, + 'SystemAddress': self.systemaddress, + 'Population': self.systempopulation, + } + + if self.planet: + entry['Body'] = self.planet + entry['BodyID'] = self.state['BodyID'] + entry['BodyType'] = self.state['BodyType'] + + if self.station: + entry['Docked'] = True + entry['MarketID'] = self.station_marketid + entry['StationName'] = self.station + entry['StationType'] = self.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 +581,15 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.cmdr = None self.mode = None self.group = None - self.planet = None self.system = None + self.state['SystemAddress'] = self.systemaddress = None + self.state['StarPos'] = self.coordinates = None + self.state['Body'] = self.planet = None + self.state['BodyID'] = None self.station = None self.station_marketid = None self.stationtype = None self.stationservices = None - self.coordinates = None - self.systemaddress = None self.started = None self.__init_state() @@ -599,34 +618,34 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode = entry.get('GameMode') self.group = entry.get('Group') - self.planet = None self.system = None + self.state['SystemAddress'] = self.systemaddress = None + self.state['StarPos'] = self.coordinates = None + self.status['Body'] = self.planet = None + self.status['BodyID'] = None + self.status['BodyType'] = None self.station = None self.station_marketid = None self.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 @@ -808,6 +827,18 @@ 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': self.state['IsDocked'] = True self.station = entry.get('StationName') # May be None @@ -828,6 +859,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below if event_type in ('location', 'carrierjump'): self.planet = entry.get('Body') if entry.get('BodyType') == 'Planet' else None self.state['Body'] = entry.get('Body') + self.state['BodyID'] = entry.get('BodyID') self.state['BodyType'] = entry.get('BodyType') if event_type == 'location': @@ -838,13 +870,14 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'fsdjump': self.planet = None self.state['Body'] = None + self.state['BodyID'] = None self.state['BodyType'] = None 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.state['SystemAddress'] = self.systemaddress = entry.get('SystemAddress') self.systempopulation = entry.get('Population') @@ -872,11 +905,16 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'approachbody': self.planet = entry['Body'] self.state['Body'] = entry['Body'] + self.state['BodyID'] = entry.get('BodyID') self.state['BodyType'] = 'Planet' # Best guess. Journal says always planet. elif event_type in ('leavebody', 'supercruiseentry'): + # FIXME: In the plugins/eddn.py version of this tracking we + # explicitly do NOT clear this information for `supercruiseentry', + # but it is also doing some Status.jon checking. self.planet = None self.state['Body'] = None + self.state['BodyID'] = None self.state['BodyType'] = None elif event_type in ('rank', 'promotion'): @@ -1562,14 +1600,15 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'joinacrew': self.state['Captain'] = entry['Captain'] self.state['Role'] = 'Idle' - self.planet = None + self.state['Body'] = self.planet = None + self.state['BodyID'] = 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['SystemAddress'] = self.systemaddress = None self.state['OnFoot'] = False self.state['Body'] = None @@ -1581,17 +1620,17 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'quitacrew': self.state['Captain'] = None self.state['Role'] = None - self.planet = None + self.state['Body'] = self.planet = None + self.state['BodyID'] = None + self.state['BodyType'] = 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['SystemAddress'] = self.systemaddress = None - self.state['Body'] = None - self.state['BodyType'] = None # TODO: on_foot: Will we get an event after this to know ? elif event_type == 'friends': @@ -1979,31 +2018,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below if not self.live and entry['event'] not in (None, 'Fileheader'): # 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=(', ', ':'))) diff --git a/plugins/eddn.py b/plugins/eddn.py index 13bdf108..45773cd2 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -2208,6 +2208,14 @@ def journal_entry( # noqa: C901, CCR001 entry ) + # TODO - uncomment this, i.e. use monitor.py tracking, not also here + # 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.coordinates = state['StarPos'] + # this.systemaddress = state['SystemAddress'] + # Track location if event_name == 'supercruiseexit': # For any orbital station we have no way of determining the body @@ -2360,6 +2368,7 @@ def journal_entry( # noqa: C901, CCR001 # add planet to Docked event for planetary stations if known if event_name == 'docked' and this.body_name: + # FIXME - Is this correct if using monitor.py tracking ? entry['Body'] = this.body_name entry['BodyType'] = 'Planet' From 9ccd0c3b7d623350c86ca8594bd2eb661a3b1a0e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 15:15:02 +0000 Subject: [PATCH 204/257] monitor: Remove EDLogs.systemaddress in favour of .state version This was literally only used within this file. --- monitor.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/monitor.py b/monitor.py index 57beb124..ff872db3 100644 --- a/monitor.py +++ b/monitor.py @@ -117,7 +117,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.group: str | None = None self.cmdr: str | None = None self.system: str | None = None - self.systemaddress: int | None = None self.coordinates: Tuple[float, float, float] | None = None self.systempopulation: int | None = None self.planet: str | None = None @@ -307,7 +306,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.group = None self.cmdr = None self.system = None - self.state['SystemAddress'] = self.systemaddress = None + self.state['SystemAddress'] = None self.coordinates = None self.planet = self.state['Body'] = None self.state['BodyID'] = None @@ -532,7 +531,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'event': 'StartUp', 'StarSystem': self.system, 'StarPos': self.coordinates, - 'SystemAddress': self.systemaddress, + 'SystemAddress': self.state['SystemAddress'], 'Population': self.systempopulation, } @@ -582,7 +581,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode = None self.group = None self.system = None - self.state['SystemAddress'] = self.systemaddress = None + self.state['SystemAddress'] = None self.state['StarPos'] = self.coordinates = None self.state['Body'] = self.planet = None self.state['BodyID'] = None @@ -619,7 +618,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.group = entry.get('Group') self.system = None - self.state['SystemAddress'] = self.systemaddress = None + self.state['SystemAddress'] = None self.state['StarPos'] = self.coordinates = None self.status['Body'] = self.planet = None self.status['BodyID'] = None @@ -877,7 +876,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # Plugins need this as well, so copy in state self.state['StarPos'] = self.coordinates = tuple(entry['StarPos']) # type: ignore - self.state['SystemAddress'] = self.systemaddress = entry.get('SystemAddress') + self.state['SystemAddress'] = entry.get('SystemAddress') self.systempopulation = entry.get('Population') @@ -1608,7 +1607,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.stationtype = None self.stationservices = None self.coordinates = None - self.state['SystemAddress'] = self.systemaddress = None + self.state['SystemAddress'] = None self.state['OnFoot'] = False self.state['Body'] = None @@ -1629,7 +1628,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.stationtype = None self.stationservices = None self.coordinates = None - self.state['SystemAddress'] = self.systemaddress = None + self.state['SystemAddress'] = None # TODO: on_foot: Will we get an event after this to know ? From 0177fc4d699ec966f16358c09231ea8fafb7641f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 15:28:48 +0000 Subject: [PATCH 205/257] monitor: Remove .planet in favour of state['Body'] This had mostly been done already, now it's complete. *If* any plugin is, still, using `monitor.planet` then they get to keep the broken pieces because it's not included in PLUGINS.md#Available-imports. --- monitor.py | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/monitor.py b/monitor.py index ff872db3..bab1d244 100644 --- a/monitor.py +++ b/monitor.py @@ -119,7 +119,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.system: str | None = None self.coordinates: Tuple[float, float, float] | None = None self.systempopulation: int | None = None - self.planet: str | None = None self.station: str | None = None self.station_marketid: int | None = None self.stationtype: str | None = None @@ -308,7 +307,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.system = None self.state['SystemAddress'] = None self.coordinates = None - self.planet = self.state['Body'] = None + self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None self.station = None @@ -535,8 +534,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'Population': self.systempopulation, } - if self.planet: - entry['Body'] = self.planet + if self.state['Body']: + entry['Body'] = self.state['Body'] entry['BodyID'] = self.state['BodyID'] entry['BodyType'] = self.state['BodyType'] @@ -583,7 +582,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.system = None self.state['SystemAddress'] = None self.state['StarPos'] = self.coordinates = None - self.state['Body'] = self.planet = None + self.state['Body'] = None self.state['BodyID'] = None self.station = None self.station_marketid = None @@ -620,7 +619,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.system = None self.state['SystemAddress'] = None self.state['StarPos'] = self.coordinates = None - self.status['Body'] = self.planet = None + self.status['Body'] = None self.status['BodyID'] = None self.status['BodyType'] = None self.station = None @@ -856,7 +855,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • InSRV: bool # • OnFoot: bool 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') @@ -867,7 +867,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['IsDocked'] = True elif event_type == 'fsdjump': - self.planet = None self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None @@ -902,7 +901,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['Dropship'] = None elif event_type == 'approachbody': - self.planet = entry['Body'] self.state['Body'] = entry['Body'] self.state['BodyID'] = entry.get('BodyID') self.state['BodyType'] = 'Planet' # Best guess. Journal says always planet. @@ -911,7 +909,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # FIXME: In the plugins/eddn.py version of this tracking we # explicitly do NOT clear this information for `supercruiseentry', # but it is also doing some Status.jon checking. - self.planet = None self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None @@ -1599,7 +1596,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'joinacrew': self.state['Captain'] = entry['Captain'] self.state['Role'] = 'Idle' - self.state['Body'] = self.planet = None + self.state['Body'] = None self.state['BodyID'] = None self.system = None self.station = None @@ -1619,7 +1616,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'quitacrew': self.state['Captain'] = None self.state['Role'] = None - self.state['Body'] = self.planet = None + self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None self.system = None @@ -1714,11 +1711,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: From e3254aec3104d831af0996aa28f0b54ad7835dc2 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 15:34:11 +0000 Subject: [PATCH 206/257] monitor: Minor cleanup on 'Location'->'Docked' handling * All my recent Location events *have* the 'Docked' flag. * If any don't, then just use a default on .get() to set it False. --- monitor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/monitor.py b/monitor.py index bab1d244..541cd03b 100644 --- a/monitor.py +++ b/monitor.py @@ -863,8 +863,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below if event_type == 'location': logger.trace_if('journal.locations', '"Location" event') - if entry.get('Docked'): - self.state['IsDocked'] = True + self.state['IsDocked'] = entry.get('Docked', False) elif event_type == 'fsdjump': self.state['Body'] = None From 232e91ebfcf3fada650aa8c582a4d1d4f02abac3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 16:34:56 +0000 Subject: [PATCH 207/257] monitor/Body: Tweak & comment, and remove defunct tracking from eddn.py * Typod '.status' instead of 'state'. * Bring in some sanity-checks and comments from eddn.py to monitor.py. * Have a 'pass' elif for 'supercruiseentry' so as to comment why we do NOT use this to blank out body state. * Bring in the 'if we exit to main menu, blank body state' from eddn.py. * Remove checks from eddn.py that are now in monitor.py. * Have a disctinct 'docked' event check in eddn.py for triggering the "Now we're docked, so the Delay sending until docked is satisfied" sending of messages. --- monitor.py | 41 +++++++++++++++++++++++++++++--------- plugins/eddn.py | 53 ++++++++++--------------------------------------- 2 files changed, 42 insertions(+), 52 deletions(-) diff --git a/monitor.py b/monitor.py index 541cd03b..d416b100 100644 --- a/monitor.py +++ b/monitor.py @@ -619,9 +619,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.system = None self.state['SystemAddress'] = None self.state['StarPos'] = self.coordinates = None - self.status['Body'] = None - self.status['BodyID'] = None - self.status['BodyType'] = None + self.state['Body'] = None + self.state['BodyID'] = None + self.state['BodyType'] = None self.station = None self.station_marketid = None self.stationtype = None @@ -874,7 +874,14 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # Plugins need this as well, so copy in state self.state['StarPos'] = self.coordinates = tuple(entry['StarPos']) # type: ignore - self.state['SystemAddress'] = entry.get('SystemAddress') + 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. + self.state['SystemAddress'] = entry.get('SystemAddress', None) self.systempopulation = entry.get('Population') @@ -902,16 +909,32 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'approachbody': self.state['Body'] = entry['Body'] self.state['BodyID'] = entry.get('BodyID') - self.state['BodyType'] = 'Planet' # Best guess. Journal says always planet. + # 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 + self.state['BodyType'] = 'Planet' - elif event_type in ('leavebody', 'supercruiseentry'): - # FIXME: In the plugins/eddn.py version of this tracking we - # explicitly do NOT clear this information for `supercruiseentry', - # but it is also doing some Status.jon checking. + 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': + # NB: Do **NOT** clear Body state, because we won't get a fresh + # ApproachBody if we don't leave Orbital Cruise but land + # again. + pass + + 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') diff --git a/plugins/eddn.py b/plugins/eddn.py index 45773cd2..f1a5c162 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -1279,6 +1279,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: @@ -2208,40 +2210,14 @@ def journal_entry( # noqa: C901, CCR001 entry ) - # TODO - uncomment this, i.e. use monitor.py tracking, not also here # 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.coordinates = state['StarPos'] - # this.systemaddress = state['SystemAddress'] - - # 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 - - 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 + this.body_name = state['Body'] + this.body_id = state['BodyID'] + this.coordinates = state['StarPos'] + this.systemaddress = state['SystemAddress'] + if event_name in ('location', 'fsdjump', 'docked', 'carrierjump'): if 'StarPos' in entry: this.coordinates = tuple(entry['StarPos']) @@ -2251,18 +2227,9 @@ def journal_entry( # noqa: C901, CCR001 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') + 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 == 'leavebody': # NB: **NOT** SupercruiseEntry, because we won't get a fresh From e6abc137cebd15f94638a822e5ab8a0255b3014b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 18:49:27 +0000 Subject: [PATCH 208/257] monitor/tracking: Shift .coordinates to state['StarPos'] * Some additional commenting for future clarity. * Remove the old eddn.py tracking. --- monitor.py | 79 +++++++++++++++++++++++++++++-------------------- plugins/eddn.py | 10 ------- 2 files changed, 47 insertions(+), 42 deletions(-) diff --git a/monitor.py b/monitor.py index d416b100..f34c41da 100644 --- a/monitor.py +++ b/monitor.py @@ -117,7 +117,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.group: str | None = None self.cmdr: str | None = None self.system: str | None = None - self.coordinates: Tuple[float, float, float] | None = None self.systempopulation: int | None = None self.station: str | None = None self.station_marketid: int | None = None @@ -306,7 +305,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.cmdr = None self.system = None self.state['SystemAddress'] = None - self.coordinates = None + self.state['StarPos'] = None self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None @@ -529,7 +528,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'timestamp': strftime('%Y-%m-%dT%H:%M:%SZ', gmtime()), 'event': 'StartUp', 'StarSystem': self.system, - 'StarPos': self.coordinates, + 'StarPos': self.state['StarPos'], 'SystemAddress': self.state['SystemAddress'], 'Population': self.systempopulation, } @@ -581,7 +580,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.group = None self.system = None self.state['SystemAddress'] = None - self.state['StarPos'] = self.coordinates = None + self.state['StarPos'] = None self.state['Body'] = None self.state['BodyID'] = None self.station = None @@ -618,7 +617,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.group = entry.get('Group') self.system = None self.state['SystemAddress'] = None - self.state['StarPos'] = self.coordinates = None + self.state['StarPos'] = None self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None @@ -839,21 +838,18 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'docked': 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.station = entry.get('StationName') # It may be None + self.station_marketid = entry.get('MarketID') # It may be None + self.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 + ############################################################### + # Track: Body + ############################################################### if event_type in ('location', 'carrierjump'): # We're not guaranteeing this is a planet, rather than a # station. @@ -861,21 +857,32 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyID'] = entry.get('BodyID') self.state['BodyType'] = entry.get('BodyType') - if event_type == 'location': - logger.trace_if('journal.locations', '"Location" event') - self.state['IsDocked'] = entry.get('Docked', False) - elif event_type == 'fsdjump': 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.state['StarPos'] = tuple(entry['StarPos']) # type: ignore + + else: + logger.warning(f"'{event_type}' event without 'StarPos' !!!:\n{entry}\n") if 'SystemAddress' not in entry: - logger.warning(f'"location" event without SystemAddress !!!:\n{entry}\n') + logger.warning(f"{event_type} 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 @@ -890,8 +897,12 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below else: self.system = entry['StarSystem'] + ############################################################### - self.station = entry.get('StationName') # May be None + ############################################################### + # Track: Current station, if applicable + ############################################################### + self.station = 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 @@ -901,10 +912,15 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 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' + ############################################################### + ############################################################### + # 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.state['Body'] = entry['Body'] @@ -1618,36 +1634,35 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'joinacrew': self.state['Captain'] = entry['Captain'] self.state['Role'] = 'Idle' + self.state['StarPos'] = None + self.system = None + self.state['SystemAddress'] = None + self.state['StarPos'] = None self.state['Body'] = None self.state['BodyID'] = None - self.system = None + self.state['BodyType'] = None self.station = None self.station_marketid = None self.stationtype = None self.stationservices = None - self.coordinates = None - self.state['SystemAddress'] = None self.state['OnFoot'] = False - self.state['Body'] = None - self.state['BodyType'] = None - elif event_type == 'changecrewrole': self.state['Role'] = entry['Role'] elif event_type == 'quitacrew': self.state['Captain'] = None self.state['Role'] = None + self.system = None + self.state['SystemAddress'] = None + self.state['StarPos'] = None self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None - self.system = None self.station = None self.station_marketid = None self.stationtype = None self.stationservices = None - self.coordinates = None - self.state['SystemAddress'] = None # TODO: on_foot: Will we get an event after this to know ? diff --git a/plugins/eddn.py b/plugins/eddn.py index f1a5c162..dac4e303 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -2217,16 +2217,6 @@ def journal_entry( # noqa: C901, CCR001 this.coordinates = state['StarPos'] this.systemaddress = state['SystemAddress'] - if event_name in ('location', 'fsdjump', 'docked', 'carrierjump'): - 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') - 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) From 6f3967fb7fa13fa48bc457114c7e2e8ad24cdd3a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 3 Jan 2023 18:55:42 +0000 Subject: [PATCH 209/257] eddn/tracking: Tweak commenting about coordinates * `entry_augment_system_data()` will now always be passed starpos based on state['StarPos']. * Removed TODO about deprecating in-plugin tracking. --- plugins/eddn.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index dac4e303..5366f73e 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -1123,11 +1123,10 @@ class EDDN: entry['SystemAddress'] = this.systemaddress 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) From 386ea1636e7943c4e1bbec9f28102a5d5bc20424 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 11:26:35 +0000 Subject: [PATCH 210/257] eddn: For 'docked' only set entry Body(Type) if latter is 'Planet' We explicitly must not set this for other BodyType, e.g. 'Station'. --- plugins/eddn.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index 5366f73e..0a20bdfc 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -2323,10 +2323,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: - # FIXME - Is this correct if using monitor.py tracking ? - 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 From edc23081b15023237a11eff302a6be84514bdc7f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 11:29:46 +0000 Subject: [PATCH 211/257] monitor: Extend 'approachbody' comment to call out use in plugins/eddn.py We're setting `self.state['BodyType']` specifically so plugins/eddn.py's 'docked' handling can use it as a check. --- monitor.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/monitor.py b/monitor.py index f34c41da..61e03759 100644 --- a/monitor.py +++ b/monitor.py @@ -927,6 +927,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 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 == 'leavebody': From 427a238dee5ddf957b0fc8b683e67e98e03c2235 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 11:34:58 +0000 Subject: [PATCH 212/257] eddn: Remove un-necessary 'leavebody' state clearing This is now handled in monitor.py, and *this* code explicitly sets the 'this' values to those in `state` as passed in. --- plugins/eddn.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index 0a20bdfc..f76274a8 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -2220,14 +2220,6 @@ def journal_entry( # noqa: C901, CCR001 # 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 == '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 - elif event_name == 'music': if entry['MusicTrack'] == 'MainMenu': this.body_name = None From fafe9a5f7b940a4dc90c0ac38caabf2a895a237a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 11:37:13 +0000 Subject: [PATCH 213/257] eddn: Remove un-necessary 'music'/'MainMenu' body tracking clearance monitor.py does this for `state` passed in, which *this* code then uses to set `this` values. --- plugins/eddn.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index f76274a8..cd29d215 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -2222,8 +2222,6 @@ def journal_entry( # noqa: C901, CCR001 elif event_name == 'music': if entry['MusicTrack'] == 'MainMenu': - this.body_name = None - this.body_id = None this.status_body_name = None # Events with their own EDDN schema From b1308e4f28f4cc126b496e199d65a68aef7988ac Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 12:18:13 +0000 Subject: [PATCH 214/257] PLUGINS.md: Document addition of Bodt(ID|Type) and the caveats about use --- PLUGINS.md | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index 0378ef96..279f6b5b 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -653,8 +653,9 @@ Content of `state` (updated to the current journal entry): | `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 | +| `Body`[3] | `Optional[str]` | Name of the body we're currently on / in the SOI of | +| `BodyID`[3] | `Optional[int]` | ID of the body we're currently on / in the SOI of | +| `BodyType`[3] | `Optional[str]` | The type of body that `Body` refers to | [1] - Contents of `NavRoute` not changed if a `NavRouteClear` event is seen, but plugins will see the `NavRouteClear` event. @@ -676,6 +677,28 @@ 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] - 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,6 +788,12 @@ 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: +`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. + ___ ##### Synthetic Events From d533919790c3909db40802a77162c44fa02f1a61 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 12:18:41 +0000 Subject: [PATCH 215/257] monitor: Add some documentation about the player location tracking caveats --- monitor.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/monitor.py b/monitor.py index 61e03759..97d6bca5 100644 --- a/monitor.py +++ b/monitor.py @@ -837,6 +837,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyID'] = None elif event_type == 'docked': + ############################################################### + # Track: Station + ############################################################### self.state['IsDocked'] = True self.station = entry.get('StationName') # It may be None self.station_marketid = entry.get('MarketID') # It may be None @@ -845,8 +848,51 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # 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'): + """ + 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. + """ ############################################################### # Track: Body ############################################################### From dab69367e2f627fe42ec689e03b08a2721cb8017 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 12:23:09 +0000 Subject: [PATCH 216/257] monitor: Cite the Status.json body workaround for Body data caveat --- monitor.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/monitor.py b/monitor.py index 97d6bca5..d7eefe88 100644 --- a/monitor.py +++ b/monitor.py @@ -892,6 +892,10 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 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 From fa1c072d9e8a84cef8db5c0683b0327524a62917 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 15:05:29 +0000 Subject: [PATCH 217/257] monitor: Change .system to state['SystemName'] 1. EDDB plugin needs to track the system name, but we're moving all of that into monitor.py. 2. monitor.py was tracking this in monitor.system, but it needs to be in monitor.state['SystemName'] in order for plugins to access it. So, move monitor.system to monitor.state['SystemName'] and update all uses. --- EDMC.py | 11 ++++++----- EDMarketConnector.py | 43 +++++++++++++++++++++++++++---------------- monitor.py | 17 ++++++++--------- plugins/eddb.py | 2 ++ 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/EDMC.py b/EDMC.py index 2a7d7cd4..b3cce61d 100755 --- a/EDMC.py +++ b/EDMC.py @@ -326,7 +326,7 @@ sys.path: {sys.path}''' raise companion.CmdrError() elif ( - data['lastSystem']['name'] != monitor.system or + data['lastSystem']['name'] != monitor.state['SystemName'] 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'] @@ -431,10 +431,11 @@ sys.path: {sys.path}''' 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.system and \ - deep_get(new_data, 'lastStarport', 'name') == monitor.station: - + if ( + new_data['commander'].get('docked') + and deep_get(new_data, 'lastSystem', 'name') == monitor.state['SystemName'] + and deep_get(new_data, 'lastStarport', 'name') == monitor.station + ): data = new_data if args.s: diff --git a/EDMarketConnector.py b/EDMarketConnector.py index fe31304d..8ac7e938 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1089,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') @@ -1272,9 +1272,10 @@ 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: @@ -1526,7 +1527,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', @@ -1589,7 +1590,7 @@ class AppWindow(object): err = plug.notify_journal_entry( monitor.cmdr, monitor.is_beta, - monitor.system, + monitor.state['SystemName'], monitor.station, entry, monitor.state @@ -1728,11 +1729,16 @@ class AppWindow(object): 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 | 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.station + ) def cooldown(self) -> None: """Display and update the cooldown timer for 'Update' button.""" @@ -1746,12 +1752,14 @@ 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 + ) if sys.platform == 'win32': def ontop_changed(self, event=None) -> None: @@ -1761,9 +1769,12 @@ class AppWindow(object): 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.station}" if monitor.station + else monitor.state['SystemName'] + ) def help_general(self, event=None) -> None: """Open Wiki Help page in browser.""" @@ -1898,7 +1909,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.station}.{timestamp}" ) if not f: return diff --git a/monitor.py b/monitor.py index d7eefe88..a1a9ff63 100644 --- a/monitor.py +++ b/monitor.py @@ -116,7 +116,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode: str | None = None self.group: str | None = None self.cmdr: str | None = None - self.system: str | None = None self.systempopulation: int | None = None self.station: str | None = None self.station_marketid: int | None = None @@ -191,6 +190,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below '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, 'Body': None, 'BodyID': None, 'BodyType': None, @@ -303,7 +303,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode = None self.group = None self.cmdr = None - self.system = None self.state['SystemAddress'] = None self.state['StarPos'] = None self.state['Body'] = None @@ -527,7 +526,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below entry: dict[str, Any] = { 'timestamp': strftime('%Y-%m-%dT%H:%M:%SZ', gmtime()), 'event': 'StartUp', - 'StarSystem': self.system, + 'StarSystem': self.state['SystemName'], 'StarPos': self.state['StarPos'], 'SystemAddress': self.state['SystemAddress'], 'Population': self.systempopulation, @@ -578,7 +577,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.cmdr = None self.mode = None self.group = None - self.system = None + self.state['SystemName'] = None self.state['SystemAddress'] = None self.state['StarPos'] = None self.state['Body'] = None @@ -615,7 +614,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode = entry.get('GameMode') self.group = entry.get('Group') - self.system = None + self.state['SystemName'] = None self.state['SystemAddress'] = None self.state['StarPos'] = None self.state['Body'] = None @@ -943,10 +942,10 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.systempopulation = entry.get('Population') if entry['StarSystem'] == 'ProvingGround': - self.system = 'CQC' + self.state['SystemName'] = 'CQC' else: - self.system = entry['StarSystem'] + self.state['SystemName'] = entry['StarSystem'] ############################################################### ############################################################### @@ -1687,7 +1686,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['Captain'] = entry['Captain'] self.state['Role'] = 'Idle' self.state['StarPos'] = None - self.system = None + self.state['SystemName'] = None self.state['SystemAddress'] = None self.state['StarPos'] = None self.state['Body'] = None @@ -1705,7 +1704,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'quitacrew': self.state['Captain'] = None self.state['Role'] = None - self.system = None + self.state['SystemName'] = None self.state['SystemAddress'] = None self.state['StarPos'] = None self.state['Body'] = None diff --git a/plugins/eddb.py b/plugins/eddb.py index a5d0593a..2dd2d787 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -184,6 +184,8 @@ def journal_entry( # noqa: CCR001 return this.on_foot = state['OnFoot'] + this.system_address = state['SystemAddress'] + # 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'): From 86e81adb3d96ba365aaa55f9cab3f38d9327618e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 15:17:39 +0000 Subject: [PATCH 218/257] EDDB: Rename this.system to this.system_name --- plugins/eddb.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/plugins/eddb.py b/plugins/eddb.py index 2dd2d787..1c53ae5b 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -42,7 +42,7 @@ # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# # ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# import tkinter -from typing import TYPE_CHECKING, Any, Mapping, Optional +from typing import TYPE_CHECKING, Any, Mapping import requests @@ -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: str | None = None + self.station_marketid: int | None = None self.on_foot = False @@ -133,7 +133,7 @@ def plugin_app(parent: 'Tk'): """ # system label in main window this.system_link = parent.nametowidget(f".{appname.lower()}.system") - this.system = None + this.system_name = None this.system_address = None this.station = None this.station_marketid = None # Frontier MarketID @@ -185,12 +185,13 @@ def journal_entry( # noqa: CCR001 this.on_foot = state['OnFoot'] this.system_address = state['SystemAddress'] + this.system_name = state['SystemName'] # 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_name = entry.get('StarSystem') or this.system_name # We need pop == 0 to set the value so as to clear 'x' in systems with # no stations. @@ -217,7 +218,7 @@ def journal_entry( # noqa: CCR001 # Only actually change URLs if we are current provider. 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() @@ -238,7 +239,7 @@ def journal_entry( # noqa: CCR001 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. @@ -251,15 +252,15 @@ 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'] # 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() From dbad45cf3b1d7eab6d7880ac46ed0bd4a2842dfe Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 15:20:21 +0000 Subject: [PATCH 219/257] EDDB: Use only state['SystemName'] for this.system_name tracking --- plugins/eddb.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugins/eddb.py b/plugins/eddb.py index 1c53ae5b..51291c37 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -187,12 +187,6 @@ def journal_entry( # noqa: CCR001 this.system_address = state['SystemAddress'] this.system_name = state['SystemName'] - # 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_name = entry.get('StarSystem') or this.system_name - # We need pop == 0 to set the value so as to clear 'x' in systems with # no stations. pop = entry.get('Population') From df5eb5b27045eb9cfdb5e530ed54c5178edc55d6 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 15:37:07 +0000 Subject: [PATCH 220/257] monitor/tracking: Switch .systempopulation to state['SystemPopulation'] 1. EDDB plugin tracked this for keeping the Station link text up to date. * So moved it to monitor.state['SystemPopulation']. * PLUGINS.md updated to cite this. * PLUGINS.md also updated to note state entries that are set to None if remote multi-crew is detected. --- PLUGINS.md | 26 +++++++++++++++++++------- monitor.py | 16 +++++++++++----- plugins/eddb.py | 7 +------ 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index 279f6b5b..8d30a140 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -607,11 +607,11 @@ 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 | +| `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 | @@ -639,7 +639,7 @@ Content of `state` (updated to the current journal entry): | `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 | +| `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. | @@ -653,9 +653,13 @@ Content of `state` (updated to the current journal entry): | `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`[3] | `Optional[str]` | Name of the body we're currently on / in the SOI of | -| `BodyID`[3] | `Optional[int]` | ID of the body we're currently on / in the SOI of | -| `BodyType`[3] | `Optional[str]` | The type of body that `Body` refers to | +| `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 | [1] - Contents of `NavRoute` not changed if a `NavRouteClear` event is seen, but plugins will see the `NavRouteClear` event. @@ -677,7 +681,10 @@ 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] - There are some caveats with the Body data. Firstly the name and ID +[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. @@ -789,6 +796,11 @@ 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 diff --git a/monitor.py b/monitor.py index a1a9ff63..3df19170 100644 --- a/monitor.py +++ b/monitor.py @@ -116,7 +116,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode: str | None = None self.group: str | None = None self.cmdr: str | None = None - self.systempopulation: int | None = None self.station: str | None = None self.station_marketid: int | None = None self.stationtype: str | None = None @@ -191,6 +190,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'StarPos': None, # Best effort current system's galaxy position. 'SystemAddress': None, 'SystemName': None, + 'SystemPopulation': None, 'Body': None, 'BodyID': None, 'BodyType': None, @@ -304,6 +304,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.group = None self.cmdr = 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 @@ -529,7 +531,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'StarSystem': self.state['SystemName'], 'StarPos': self.state['StarPos'], 'SystemAddress': self.state['SystemAddress'], - 'Population': self.systempopulation, + 'Population': self.state['SystemPopulation'], } if self.state['Body']: @@ -577,8 +579,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.cmdr = None self.mode = None self.group = None - self.state['SystemName'] = 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 @@ -614,8 +617,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode = entry.get('GameMode') self.group = entry.get('Group') - self.state['SystemName'] = 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 @@ -939,7 +943,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # Yes, explicitly state `None` here, so it's crystal clear. self.state['SystemAddress'] = entry.get('SystemAddress', None) - self.systempopulation = entry.get('Population') + self.state['SystemPopulation'] = entry.get('Population') if entry['StarSystem'] == 'ProvingGround': self.state['SystemName'] = 'CQC' @@ -1688,6 +1692,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 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 @@ -1706,6 +1711,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['Role'] = 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 diff --git a/plugins/eddb.py b/plugins/eddb.py index 51291c37..41a32fd7 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -186,12 +186,7 @@ def journal_entry( # noqa: CCR001 this.on_foot = state['OnFoot'] this.system_address = state['SystemAddress'] this.system_name = state['SystemName'] - - # 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.system_population = state['SystemPopulation'] this.station = entry.get('StationName') or this.station # on_foot station detection From dde0cf876c02ba061318eff2f9c9e7cc4c0efc95 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 16:14:19 +0000 Subject: [PATCH 221/257] monitor/tracking: Move .station to state['StationName'] 1. EDDB tracks this. * So move monitor.station to monitor.state['StationName']. * PLUGINS.md updated to cite this. --- EDMC.py | 12 +++++---- EDMarketConnector.py | 23 ++++++++--------- PLUGINS.md | 3 +++ monitor.py | 59 +++++++++++++++++++++++++++----------------- plugins/eddb.py | 30 +++++++++------------- plugins/eddn.py | 2 +- 6 files changed, 71 insertions(+), 58 deletions(-) diff --git a/EDMC.py b/EDMC.py index b3cce61d..f56f7ead 100755 --- a/EDMC.py +++ b/EDMC.py @@ -326,10 +326,12 @@ sys.path: {sys.path}''' raise companion.CmdrError() elif ( - data['lastSystem']['name'] != monitor.state['SystemName'] 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() @@ -434,7 +436,7 @@ sys.path: {sys.path}''' if ( new_data['commander'].get('docked') and deep_get(new_data, 'lastSystem', 'name') == monitor.state['SystemName'] - and deep_get(new_data, 'lastStarport', 'name') == monitor.station + and deep_get(new_data, 'lastStarport', 'name') == monitor.state['StationName'] ): data = new_data diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 8ac7e938..57f56982 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1278,18 +1278,19 @@ class AppWindow(object): 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 @@ -1591,7 +1592,7 @@ class AppWindow(object): monitor.cmdr, monitor.is_beta, monitor.state['SystemName'], - monitor.station, + monitor.state['StationName'], entry, monitor.state ) @@ -1607,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'): @@ -1737,7 +1738,7 @@ class AppWindow(object): """Despatch a station URL to the configured handler.""" return plug.invoke( config.get_str('station_provider'), 'eddb', 'station_url', - monitor.state['SystemName'], monitor.station + monitor.state['SystemName'], monitor.state['StationName'] ) def cooldown(self) -> None: @@ -1772,7 +1773,7 @@ class AppWindow(object): if monitor.state['SystemName']: self.w.clipboard_clear() self.w.clipboard_append( - f"{monitor.state['SystemName']},{monitor.station}" if monitor.station + f"{monitor.state['SystemName']},{monitor.state['StationName']}" if monitor.state['StationName'] else monitor.state['SystemName'] ) @@ -1909,7 +1910,7 @@ class AppWindow(object): defaultextension=default_extension, filetypes=[('JSON', '.json'), ('All Files', '*')], initialdir=config.get_str('outdir'), - initialfile=f"{monitor.state['SystemName']}.{monitor.station}.{timestamp}" + initialfile=f"{monitor.state['SystemName']}.{monitor.state['StationName']}.{timestamp}" ) if not f: return diff --git a/PLUGINS.md b/PLUGINS.md index 8d30a140..36beef9d 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -660,6 +660,7 @@ Content of `state` (updated to the current journal entry): | `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` | `Optional[str]` | Name 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. @@ -806,6 +807,8 @@ 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` added to the `state` dictionary. + ___ ##### Synthetic Events diff --git a/monitor.py b/monitor.py index 3df19170..19b57983 100644 --- a/monitor.py +++ b/monitor.py @@ -116,7 +116,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode: str | None = None self.group: str | None = None self.cmdr: str | None = None - self.station: str | None = None self.station_marketid: int | None = None self.stationtype: str | None = None self.started: int | None = None # Timestamp of the LoadGame event @@ -194,6 +193,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'Body': None, 'BodyID': None, 'BodyType': None, + 'StationName': None, 'NavRoute': None, } @@ -310,7 +310,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None - self.station = None + self.state['StationName'] = None self.station_marketid = None self.stationtype = None self.stationservices = None @@ -585,7 +585,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['StarPos'] = None self.state['Body'] = None self.state['BodyID'] = None - self.station = None + self.state['StationName'] = None self.station_marketid = None self.stationtype = None self.stationservices = None @@ -624,7 +624,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None - self.station = None + self.state['StationName'] = None self.station_marketid = None self.stationtype = None self.stationservices = None @@ -757,7 +757,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below modules.pop(from_slot, None) elif event_type == 'undocked': - self.station = None + self.state['StationName'] = None self.station_marketid = None self.stationtype = None self.stationservices = None @@ -779,9 +779,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • StationName (if at a station) # • StationType # • MarketID - self.station = None + self.state['StationName'] = None if entry.get('OnStation'): - self.station = entry.get('StationName', '') + self.state['StationName'] = entry.get('StationName', '') self.state['OnFoot'] = False self.state['Taxi'] = entry['Taxi'] @@ -809,10 +809,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): @@ -844,7 +844,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # Track: Station ############################################################### self.state['IsDocked'] = True - self.station = entry.get('StationName') # It may be None + self.state['StationName'] = entry.get('StationName') # It may be None self.station_marketid = entry.get('MarketID') # It may be None self.stationtype = entry.get('StationType') # It may be None self.stationservices = entry.get('StationServices') # None under E:D < 2.4 @@ -955,16 +955,23 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below ############################################################### # Track: Current station, if applicable ############################################################### - self.station = 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.station = entry.get('Body') + if event_type == 'fsdjump': + self.state['StationName'] = None + self.station_marketid = None + self.stationtype = None + self.stationservices = None - 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' + 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.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' ############################################################### ############################################################### @@ -996,7 +1003,15 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # NB: Do **NOT** clear Body state, because we won't get a fresh # ApproachBody if we don't leave Orbital Cruise but land # again. - pass + + ############################################################### + # Track: Current station, if applicable + ############################################################### + self.state['StationName'] = None + self.station_marketid = None + self.stationtype = None + self.stationservices = None + ############################################################### elif event_type == 'music': if entry['MusicTrack'] == 'MainMenu': @@ -1697,7 +1712,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None - self.station = None + self.state['StationName'] = None self.station_marketid = None self.stationtype = None self.stationservices = None @@ -1716,7 +1731,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['Body'] = None self.state['BodyID'] = None self.state['BodyType'] = None - self.station = None + self.state['StationName'] = None self.station_marketid = None self.stationtype = None self.stationservices = None diff --git a/plugins/eddb.py b/plugins/eddb.py index 41a32fd7..dc6c7b63 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -73,7 +73,7 @@ class This: self.system_address: str | None = None self.system_population: int | None = None self.station_link: tkinter.Widget - self.station: str | None = None + self.station_name: str | None = None self.station_marketid: int | None = None self.on_foot = False @@ -135,7 +135,7 @@ def plugin_app(parent: 'Tk'): 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 # station label in main window this.station_link = parent.nametowidget(f".{appname.lower()}.station") @@ -154,7 +154,7 @@ 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: dict[str, Any], state: Mapping[str, Any] @@ -187,22 +187,16 @@ def journal_entry( # noqa: CCR001 this.system_address = state['SystemAddress'] this.system_name = state['SystemName'] this.system_population = state['SystemPopulation'] - - 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_name = state['StationName'] 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. @@ -214,15 +208,13 @@ def journal_entry( # noqa: CCR001 # 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 not this.station_name: 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() @@ -244,8 +236,8 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> str | None: 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': @@ -255,8 +247,8 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> str | None: 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 diff --git a/plugins/eddn.py b/plugins/eddn.py index cd29d215..ab7d2fa3 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -2449,7 +2449,7 @@ 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']: From 2a8dd14e24aaec8c73d5cbb5f3ef12beaf59d868 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 16:28:26 +0000 Subject: [PATCH 222/257] tracking/stationname; Minor fixups * Missed a some `self.station` in monitor.py * Fixed EDDB system *and* station link setting. Brainfart had mixed them together in last commit. --- monitor.py | 4 ++-- plugins/eddb.py | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/monitor.py b/monitor.py index 19b57983..ab7ce21e 100644 --- a/monitor.py +++ b/monitor.py @@ -539,10 +539,10 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below entry['BodyID'] = self.state['BodyID'] entry['BodyType'] = self.state['BodyType'] - if self.station: + if self.state['StationName']: entry['Docked'] = True entry['MarketID'] = self.station_marketid - entry['StationName'] = self.station + entry['StationName'] = self.state['StationName'] entry['StationType'] = self.stationtype else: diff --git a/plugins/eddb.py b/plugins/eddb.py index dc6c7b63..d7a0f431 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -199,16 +199,17 @@ def journal_entry( # Undocked event. this.station_marketid = None - # Only actually change URLs if we are current provider. - if config.get_str('system_provider') == 'eddb': + # 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': - if not this.station_name: + if this.station_name: + this.station_link['text'] = this.station_name + + else: if this.system_population is not None and this.system_population > 0: this.station_link['text'] = this.STATION_UNDOCKED From 31e8d0372d5dfc2a58b6cedf1c3b8c6e7cf9f343 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 16:55:04 +0000 Subject: [PATCH 223/257] monitor/tracking: Move .station_marketid to state['MarketID'] 1. plugins/eddb.py uses this for MarketID-based station URLs. * So do the 'rename'. * Remove EDDB tracking in favour of this. * Update PLUGINS.md --- EDMarketConnector.py | 4 +- PLUGINS.md | 113 ++++++++++++++++++++++--------------------- monitor.py | 25 +++++----- plugins/eddb.py | 11 +---- 4 files changed, 73 insertions(+), 80 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 57f56982..f413b05d 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1295,9 +1295,9 @@ class AppWindow(object): 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']: diff --git a/PLUGINS.md b/PLUGINS.md index 36beef9d..d8236650 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -606,61 +606,62 @@ 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`[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` | `Optional[str]` | Name of the station we're docked at, if applicable | +| 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 | [1] - Contents of `NavRoute` not changed if a `NavRouteClear` event is seen, but plugins will see the `NavRouteClear` event. @@ -807,7 +808,7 @@ 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` added to the `state` dictionary. +`StationName` and `MarketID` added to the `state` dictionary. ___ diff --git a/monitor.py b/monitor.py index ab7ce21e..d225c98c 100644 --- a/monitor.py +++ b/monitor.py @@ -116,7 +116,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode: str | None = None self.group: str | None = None self.cmdr: str | None = None - self.station_marketid: int | None = None self.stationtype: str | None = None self.started: int | None = None # Timestamp of the LoadGame event @@ -311,7 +310,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyID'] = None self.state['BodyType'] = None self.state['StationName'] = None - self.station_marketid = None + self.state['MarketID'] = None self.stationtype = None self.stationservices = None self.is_beta = False @@ -541,7 +540,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below if self.state['StationName']: entry['Docked'] = True - entry['MarketID'] = self.station_marketid + entry['MarketID'] = self.state['MarketID'] entry['StationName'] = self.state['StationName'] entry['StationType'] = self.stationtype @@ -586,7 +585,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['Body'] = None self.state['BodyID'] = None self.state['StationName'] = None - self.station_marketid = None + self.state['MarketID'] = None self.stationtype = None self.stationservices = None self.started = None @@ -625,7 +624,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyID'] = None self.state['BodyType'] = None self.state['StationName'] = None - self.station_marketid = None + self.state['MarketID'] = None self.stationtype = None self.stationservices = None self.started = timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ')) @@ -758,7 +757,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'undocked': self.state['StationName'] = None - self.station_marketid = None + self.state['MarketID'] = None self.stationtype = None self.stationservices = None self.state['IsDocked'] = False @@ -780,8 +779,10 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • StationType # • MarketID self.state['StationName'] = None + self.state['MarketID'] = None if entry.get('OnStation'): self.state['StationName'] = entry.get('StationName', '') + self.state['MarketID'] = entry.get('MarketID', '') self.state['OnFoot'] = False self.state['Taxi'] = entry['Taxi'] @@ -845,7 +846,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below ############################################################### self.state['IsDocked'] = True self.state['StationName'] = entry.get('StationName') # It may be None - self.station_marketid = entry.get('MarketID') # It may be None + self.state['MarketID'] = entry.get('MarketID') # It may be None self.stationtype = entry.get('StationType') # It may be None self.stationservices = entry.get('StationServices') # None under E:D < 2.4 @@ -957,7 +958,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below ############################################################### if event_type == 'fsdjump': self.state['StationName'] = None - self.station_marketid = None + self.state['MarketID'] = None self.stationtype = None self.stationservices = None @@ -969,7 +970,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below if entry.get('BodyType') and entry['BodyType'] == 'Station': self.state['StationName'] = entry.get('Body') - self.station_marketid = entry.get('MarketID') # May be None + self.state['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' ############################################################### @@ -1008,7 +1009,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # Track: Current station, if applicable ############################################################### self.state['StationName'] = None - self.station_marketid = None + self.state['MarketID'] = None self.stationtype = None self.stationservices = None ############################################################### @@ -1713,7 +1714,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyID'] = None self.state['BodyType'] = None self.state['StationName'] = None - self.station_marketid = None + self.state['MarketID'] = None self.stationtype = None self.stationservices = None self.state['OnFoot'] = False @@ -1732,7 +1733,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyID'] = None self.state['BodyType'] = None self.state['StationName'] = None - self.station_marketid = None + self.state['MarketID'] = None self.stationtype = None self.stationservices = None diff --git a/plugins/eddb.py b/plugins/eddb.py index d7a0f431..5638ddb4 100644 --- a/plugins/eddb.py +++ b/plugins/eddb.py @@ -188,16 +188,7 @@ def journal_entry( this.system_name = state['SystemName'] this.system_population = state['SystemPopulation'] this.station_name = state['StationName'] - - 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_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_marketid = None + this.station_marketid = state['MarketID'] # Only change URL text if we are current provider. if config.get_str('station_provider') == 'eddb': From ef1642181ad8254fc70c5fb69b455e712103f3db Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 17:00:31 +0000 Subject: [PATCH 224/257] monitor/tracking: Move .stationtype to state['StationType'] * Nothing outside of monitor.py uses this, but it's of the same nature as StationName and MarketID, so do this for consistency. For now we'll leave monitor.stationservices as-is. --- PLUGINS.md | 3 ++- monitor.py | 23 +++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index d8236650..5cabd8b6 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -662,6 +662,7 @@ Content of `state` (updated to the current journal entry): | `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. @@ -808,7 +809,7 @@ 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` and `MarketID` added to the `state` dictionary. +`StationName`, `MarketID`, and `StationType` added to the `state` dictionary. ___ diff --git a/monitor.py b/monitor.py index d225c98c..c65aef5c 100644 --- a/monitor.py +++ b/monitor.py @@ -116,7 +116,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.mode: str | None = None self.group: str | None = None self.cmdr: str | None = None - self.stationtype: str | None = None self.started: int | None = None # Timestamp of the LoadGame event self._navroute_retries_remaining = 0 @@ -311,7 +310,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyType'] = None self.state['StationName'] = None self.state['MarketID'] = None - self.stationtype = None + self.state['StationType'] = None self.stationservices = None self.is_beta = False self.state['OnFoot'] = False @@ -542,7 +541,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below entry['Docked'] = True entry['MarketID'] = self.state['MarketID'] entry['StationName'] = self.state['StationName'] - entry['StationType'] = self.stationtype + entry['StationType'] = self.state['StationType'] else: entry['Docked'] = False @@ -586,7 +585,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyID'] = None self.state['StationName'] = None self.state['MarketID'] = None - self.stationtype = None + self.state['StationType'] = None self.stationservices = None self.started = None self.__init_state() @@ -625,7 +624,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyType'] = None self.state['StationName'] = None self.state['MarketID'] = None - self.stationtype = None + self.state['StationType'] = None self.stationservices = 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 @@ -758,7 +757,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'undocked': self.state['StationName'] = None self.state['MarketID'] = None - self.stationtype = None + self.state['StationType'] = None self.stationservices = None self.state['IsDocked'] = False @@ -847,7 +846,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['IsDocked'] = True self.state['StationName'] = entry.get('StationName') # It may be None self.state['MarketID'] = entry.get('MarketID') # It may be None - self.stationtype = entry.get('StationType') # 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 it's @@ -959,7 +958,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below if event_type == 'fsdjump': self.state['StationName'] = None self.state['MarketID'] = None - self.stationtype = None + self.state['StationType'] = None self.stationservices = None else: @@ -971,7 +970,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['StationName'] = entry.get('Body') self.state['MarketID'] = entry.get('MarketID') # May be None - self.stationtype = entry.get('StationType') # May be None + self.state['StationType'] = entry.get('StationType') # May be None self.stationservices = entry.get('StationServices') # None in Odyssey for on-foot 'Location' ############################################################### @@ -1010,7 +1009,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below ############################################################### self.state['StationName'] = None self.state['MarketID'] = None - self.stationtype = None + self.state['StationType'] = None self.stationservices = None ############################################################### @@ -1715,7 +1714,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyType'] = None self.state['StationName'] = None self.state['MarketID'] = None - self.stationtype = None + self.state['StationType'] = None self.stationservices = None self.state['OnFoot'] = False @@ -1734,7 +1733,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyType'] = None self.state['StationName'] = None self.state['MarketID'] = None - self.stationtype = None + self.state['StationType'] = None self.stationservices = None # TODO: on_foot: Will we get an event after this to know ? From c396a253f8dc4ae8b5688a9bfefacbf7f14ca3f1 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 17:07:47 +0000 Subject: [PATCH 225/257] plugins/edsm: Use state[...] values for system/station * Also renamed system -> system_name and station -> station_name --- plugins/edsm.py | 61 +++++++++++++++---------------------------------- 1 file changed, 19 insertions(+), 42 deletions(-) diff --git a/plugins/edsm.py b/plugins/edsm.py index 8975ff13..d68a3491 100644 --- a/plugins/edsm.py +++ b/plugins/edsm.py @@ -94,11 +94,11 @@ class This: 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 = None - self.system: tk.Tk | 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: str | None = None + self.station_name: str | None = None self.station_marketid: int | None = None # Frontier MarketID self.on_foot = False @@ -186,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: @@ -525,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 @@ -538,38 +543,10 @@ 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 @@ -578,7 +555,7 @@ entry: {entry!r}''' if this.station_link: this.station_link['text'] = to_set - this.station_link['url'] = station_url(str(this.system), str(this.station)) + 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 @@ -685,25 +662,25 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]: # noqa: CCR001 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': if this.system_link: - 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') == 'EDSM': if this.station_link: - 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'] = STATION_UNDOCKED From 7b62fa1125c2e43012508f3634c7cea439c394f6 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 9 Jan 2023 17:19:49 +0000 Subject: [PATCH 226/257] plugins/inara: Use state[...] values for system/station * Also renamed system -> system_name & station -> station_name --- plugins/inara.py | 97 +++++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 58 deletions(-) diff --git a/plugins/inara.py b/plugins/inara.py index ff87c881..326b963b 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -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 @@ -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) @@ -371,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 ( @@ -387,15 +416,6 @@ def journal_entry( # noqa: C901, CCR001 return '' - 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 '' - should_return, new_entry = killswitch.check_killswitch( f'plugins.inara.journal.event.{entry["event"]}', new_entry, logger ) @@ -405,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': @@ -431,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" @@ -443,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: @@ -1158,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: @@ -1377,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() @@ -1407,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() From 4edebf981f3242361e8f87e9b1ccfff1b60594df Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 11:39:35 +0000 Subject: [PATCH 227/257] windows-build/archives: Create .tar.gz as well * Move the definition of archive excludes to a global variable. * Add another step to create a tar(.gz) archive as well. * Add .tar.gz to the `Built files` handling. --- .github/workflows/windows-build.yml | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 70cca876..cbee180f 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -10,6 +10,7 @@ jobs: 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 @@ -18,6 +19,11 @@ jobs: with: script: | core.setOutput('sem_ver', '${{ github.ref_name }}'.replaceAll('Release\/', '')) + # If this value gets too long it can cause issues with Windows + # command-line length and zip/tar will fail + # And all the exclusions need to be prefixed with the 'root' + # directory. + core.setOutput('archive_exclusions', 'EDMarketConnector/EDMarketConnector-release-*.* EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/ 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/out/ EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/ EDMarketConnector/WinSparkle.*') windows_build: needs: [variables] @@ -70,15 +76,25 @@ jobs: # 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-*.zip EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/ 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/out/ EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/ EDMarketConnector/WinSparkle.*' + exclusions: ${{ needs.variables.outputs.archive_exclusions }} + + - name: Make tar archive + uses: thedoctor0/zip-release@main + with: + # See the 'zip' version above for commentary on these values + type: 'tar' + path: 'EDMarketConnector' + filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz' + exclusions: ${{ needs.variables.outputs.archive_exclusions }} - name: Upload build files uses: actions/upload-artifact@v3 with: name: Built files path: | - EDMarketConnector_win*.msi + EDMarketConnector_win_*.msi EDMarketConnector-release-*.zip + EDMarketConnector-release-*.tar.gz release: name: Release new version @@ -94,7 +110,7 @@ jobs: path: ./ - name: Hash files - run: sha256sum EDMarketConnector_win*.msi EDMarketConnector-release*.zip > ./hashes.sum + run: sha256sum EDMarketConnector_win_*.msi EDMarketConnector-release-*.{zip,tar.gz} > ./hashes.sum - name: Create Draft Release uses: "softprops/action-gh-release@v1" @@ -104,6 +120,7 @@ jobs: prerelease: true discussion_category_name: "Announcement" files: | - ./EDMarketConnector_win*.msi + ./EDMarketConnector_win_*.msi ./EDMarketConnector-release-*.zip + ./EDMarketConnector-release-*.tar.gz ./hashes.sum From 43d10ab29a7ae55b52f90aa484070531d319b748 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 11:53:17 +0000 Subject: [PATCH 228/257] windows-build/archives: Can't multiple setOutput, use env instead * As the archive exclusions is static, we can just set it in workflow env. --- .github/workflows/windows-build.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index cbee180f..e55a8d5f 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -1,3 +1,4 @@ +# vim: tabstop=2 shiftwidth=2 name: Build EDMC for Windows on: @@ -6,6 +7,13 @@ on: - "Release/*" workflow_dispatch: +env: + # If this value gets too long it can cause issues with Windows + # command-line length and zip/tar will fail + # And all the exclusions need to be prefixed with the 'root' + # directory. + ARCHIVE_EXCLUSIONS: 'EDMarketConnector/EDMarketConnector-release-*.* EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/ 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/out/ EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/ EDMarketConnector/WinSparkle.*' + jobs: variables: outputs: @@ -19,11 +27,6 @@ jobs: with: script: | core.setOutput('sem_ver', '${{ github.ref_name }}'.replaceAll('Release\/', '')) - # If this value gets too long it can cause issues with Windows - # command-line length and zip/tar will fail - # And all the exclusions need to be prefixed with the 'root' - # directory. - core.setOutput('archive_exclusions', 'EDMarketConnector/EDMarketConnector-release-*.* EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/ 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/out/ EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/ EDMarketConnector/WinSparkle.*') windows_build: needs: [variables] @@ -76,7 +79,7 @@ jobs: # directory. # NB: If this gets too long it can cause zip 'Command Line Error', # presumably due to a Windows CL length limit. - exclusions: ${{ needs.variables.outputs.archive_exclusions }} + exclusions: ${{ env.ARCHIVE_EXCLUSIONS }} - name: Make tar archive uses: thedoctor0/zip-release@main @@ -85,7 +88,7 @@ jobs: type: 'tar' path: 'EDMarketConnector' filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz' - exclusions: ${{ needs.variables.outputs.archive_exclusions }} + exclusions: ${{ env.ARCHIVE_EXCLUSIONS }} - name: Upload build files uses: actions/upload-artifact@v3 From 709847990267fea34e1fff8cd8c75061495785df Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 12:03:51 +0000 Subject: [PATCH 229/257] windows-build/tar: Different specification of exclusions --- .github/workflows/windows-build.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index e55a8d5f..0fcada1f 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -7,13 +7,6 @@ on: - "Release/*" workflow_dispatch: -env: - # If this value gets too long it can cause issues with Windows - # command-line length and zip/tar will fail - # And all the exclusions need to be prefixed with the 'root' - # directory. - ARCHIVE_EXCLUSIONS: 'EDMarketConnector/EDMarketConnector-release-*.* EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/ 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/out/ EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/ EDMarketConnector/WinSparkle.*' - jobs: variables: outputs: @@ -79,7 +72,7 @@ jobs: # directory. # NB: If this gets too long it can cause zip 'Command Line Error', # presumably due to a Windows CL length limit. - exclusions: ${{ env.ARCHIVE_EXCLUSIONS }} + exclusions: 'EDMarketConnector/EDMarketConnector-release-*.* EDMarketConnector/dist.win32 EDMarketConnector/__pycache__/ 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/out/ EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/ EDMarketConnector/WinSparkle.*' - name: Make tar archive uses: thedoctor0/zip-release@main @@ -88,7 +81,8 @@ jobs: type: 'tar' path: 'EDMarketConnector' filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz' - exclusions: ${{ env.ARCHIVE_EXCLUSIONS }} + # For 'tar' we can only specify filenames, not any directory location + exclusions: 'EDMarketConnector-release-*.* dist.win32 __pycache__ .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data img out out.zip pyproject.toml scripts tests wix WinSparkle.*' - name: Upload build files uses: actions/upload-artifact@v3 From 15ee894142658927924f4feed9bf0b6efaae99e9 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 12:14:00 +0000 Subject: [PATCH 230/257] windows-build/archives: Re-order to very early, add `directory` to tar * I'd missed copying the `directory` line from zip to tar step. * There's no reason we can't perform these steps *before* the build, or even the python setup, so move them up there. That has the near side-effect of not needing to exclude so much stuff. --- .github/workflows/windows-build.yml | 59 +++++++++++++++-------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 0fcada1f..d5a40656 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -35,6 +35,36 @@ jobs: with: submodules: true + - name: Make tar archive + uses: thedoctor0/zip-release@main + with: + # See the 'zip' version for commentary on these values + type: 'tar' + directory: '..' + path: 'EDMarketConnector' + filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz' + # For 'tar' we can only specify filenames, not any directory location + exclusions: 'EDMarketConnector-release-*.* .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data img pyproject.toml scripts tests wix' + + - 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' @@ -55,35 +85,6 @@ jobs: run: | python Build-exe-and-msi.py - - 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/dist.win32 EDMarketConnector/__pycache__/ 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/out/ EDMarketConnector/out.zip EDMarketConnector/pyproject.toml EDMarketConnector/scripts/ EDMarketConnector/tests/ EDMarketConnector/wix/ EDMarketConnector/WinSparkle.*' - - - name: Make tar archive - uses: thedoctor0/zip-release@main - with: - # See the 'zip' version above for commentary on these values - type: 'tar' - path: 'EDMarketConnector' - filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz' - # For 'tar' we can only specify filenames, not any directory location - exclusions: 'EDMarketConnector-release-*.* dist.win32 __pycache__ .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data img out out.zip pyproject.toml scripts tests wix WinSparkle.*' - - name: Upload build files uses: actions/upload-artifact@v3 with: From 3e05f919494c910e279b5e269a271f35b5d99e3d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 12:18:09 +0000 Subject: [PATCH 231/257] windows-build/tar: Now we have `directory` we *do* need exclusion paths * Maybe I was wrong about not needing the prefix path on tar exclusions, because that was when I'd not copied `directory`. --- .github/workflows/windows-build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index d5a40656..19d836af 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -44,7 +44,8 @@ jobs: path: 'EDMarketConnector' filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz' # For 'tar' we can only specify filenames, not any directory location - exclusions: 'EDMarketConnector-release-*.* .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data img pyproject.toml scripts tests wix' + # exclusions: 'EDMarketConnector-release-*.* .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data img pyproject.toml scripts tests wix' + 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/' - name: Make zip archive uses: thedoctor0/zip-release@main From 042c8d4ff243433ecbd0529c243a0570f1c7291a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 12:34:44 +0000 Subject: [PATCH 232/257] windows-build/tar: Move to running under ubuntu * On windows specifying only filenames to exclusions causes things like `tar: .editorconfig: Cannot stat: No such file or directory` But putting `EDMarketConnector/` prefix on such means they don't work. * Testing with 'git bash' GNU tar 1.34: `tar -c -v -z -f edmc-test.tar.gz --exclude=.editorconfig --exclude=.git\* EDMarketConnector` works, with empty output from: `tar tfvz edmc-test.tar.gz | grep editorconfig` --- .github/workflows/windows-build.yml | 36 ++++++++++++++++++----------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 19d836af..ce6a9175 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -21,16 +21,6 @@ jobs: script: | core.setOutput('sem_ver', '${{ github.ref_name }}'.replaceAll('Release\/', '')) - windows_build: - needs: [variables] - name: Build EDMC - runs-on: windows-2019 - - defaults: - run: - shell: powershell - - steps: - uses: actions/checkout@v3 with: submodules: true @@ -44,8 +34,29 @@ jobs: path: 'EDMarketConnector' filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz' # For 'tar' we can only specify filenames, not any directory location - # exclusions: 'EDMarketConnector-release-*.* .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data img pyproject.toml scripts tests wix' - 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/' + exclusions: 'EDMarketConnector-release-*.* .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data img pyproject.toml scripts tests wix' + # 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/' + + - 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 + + defaults: + run: + shell: powershell + + steps: + - uses: actions/checkout@v3 + with: + submodules: true - name: Make zip archive uses: thedoctor0/zip-release@main @@ -93,7 +104,6 @@ jobs: path: | EDMarketConnector_win_*.msi EDMarketConnector-release-*.zip - EDMarketConnector-release-*.tar.gz release: name: Release new version From 048be66f54a46a5a661703612e5da12505fff2fe Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 12:54:19 +0000 Subject: [PATCH 233/257] windows-build/tar: Just run a tar command ourselves directly thedoctor0/zip-release has a bug where only the first word in `exclusions` has `--exclude=` pre-pended to it, the other words being treated as input filenames/globs/paths. So, let's do this manually. --- .github/workflows/windows-build.yml | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index ce6a9175..c074d170 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -26,16 +26,27 @@ jobs: submodules: true - name: Make tar archive - uses: thedoctor0/zip-release@main with: - # See the 'zip' version for commentary on these values - type: 'tar' - directory: '..' - path: 'EDMarketConnector' - filename: 'EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz' - # For 'tar' we can only specify filenames, not any directory location - exclusions: 'EDMarketConnector-release-*.* .editorconfig .flake8 .git* .mypy.ini .pre-commit-config.yaml Build-exe-and-msi.py *.manifest coriolis-data img pyproject.toml scripts tests wix' - # 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/' + script: | + # For 'tar' we can only specify filename/glob exclusions, not any + # directory location + tar -C .. -c -v -z \ + -f EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz \ + --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 - name: Upload build files uses: actions/upload-artifact@v3 From d52f161dc94c6fff8f080460394383594f1ec01c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 12:58:10 +0000 Subject: [PATCH 234/257] windows-build/tar: `run`, not `script`. --- .github/workflows/windows-build.yml | 41 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index c074d170..a7a8a5da 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -26,27 +26,26 @@ jobs: submodules: true - name: Make tar archive - with: - script: | - # For 'tar' we can only specify filename/glob exclusions, not any - # directory location - tar -C .. -c -v -z \ - -f EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz \ - --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 + run: | + # For 'tar' we can only specify filename/glob exclusions, not any + # directory location + tar -C .. -c -v -z \ + -f EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz \ + --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 - name: Upload build files uses: actions/upload-artifact@v3 From a00c6f789a381572b6f53cb537774fcba12f7bd1 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 13:03:06 +0000 Subject: [PATCH 235/257] windows-build/tar: Adjust argument ordering `-C ..` applies to anything that happens after it, so needs to be after the `-f `. --- .github/workflows/windows-build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index a7a8a5da..20b48c30 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -29,8 +29,9 @@ jobs: run: | # For 'tar' we can only specify filename/glob exclusions, not any # directory location - tar -C .. -c -v -z \ - -f EDMarketConnector/EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz \ + tar -c -v -z \ + -f EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz \ + -C .. \ --exclude=EDMarketConnector-release-*.* \ --exclude=.editorconfig \ --exclude=.flake8 \ From bcfcc8c71c78f24fdbe28c6caaf537ebe3dc0246 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 13:06:53 +0000 Subject: [PATCH 236/257] windows-build/tar: tar needs to be in job *after* `variables` At least we had `-f EDMarketConnector-release-.tar.gz ` which implies the `needs.variables.outputs.sem_ver` variable wasn't yet set. --- .github/workflows/windows-build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 20b48c30..ef1108ad 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -21,6 +21,9 @@ jobs: script: | core.setOutput('sem_ver', '${{ github.ref_name }}'.replaceAll('Release\/', '')) + linux_build: + runs-on: "ubuntu-latest" + steps: - uses: actions/checkout@v3 with: submodules: true From 2678d7d63f70b3e28cb86f7dbcdeb9a3e114aa08 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 13:10:43 +0000 Subject: [PATCH 237/257] windows-build/tar: New job needs to depend on `variables` --- .github/workflows/windows-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index ef1108ad..0cf0695a 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -22,6 +22,8 @@ jobs: 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 From 48a80411b4c44f5b6365929f853a6035673bec3e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 13:47:41 +0000 Subject: [PATCH 238/257] windows-build/tar: Make archive at .. and then mv into 'root' * Because the archive is a new file in the root it causes: `tar: EDMarketConnector: file changed as we read it` Verified on Linux/Debian, and also verified that this fix works. --- .github/workflows/windows-build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 0cf0695a..3f306884 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -35,7 +35,7 @@ jobs: # 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 \ + -f ../EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz \ -C .. \ --exclude=EDMarketConnector-release-*.* \ --exclude=.editorconfig \ @@ -52,6 +52,7 @@ jobs: --exclude=tests \ --exclude=wix \ EDMarketConnector + mv ../EDMarketConnector-release-${{ needs.variables.outputs.sem_ver }}.tar.gz . - name: Upload build files uses: actions/upload-artifact@v3 @@ -124,7 +125,7 @@ jobs: release: name: Release new version runs-on: ubuntu-latest - needs: windows_build + needs: [ windows_build, linux_build ] if: "${{ github.event_name != 'workflow_dispatch' }}" steps: From 3d41be76515528fe5eda2f01aeeb0b9c974206b5 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 14:50:44 +0000 Subject: [PATCH 239/257] monitor: log INFO when for-plugins `StartUp` event synthesized This is actually to do with a reported issue around the ctypes code in `EDLogs.gamerunning()` causing: ```python exception ignored on calling ctypes callback function: .callback at 0x0000020E9C9D0EA0> Traceback (most recent call last): File "monitor.pyc", line 2041, in callback File "monitor.pyc", line 2034, in WindowTitle ctypes.ArgumentError: argument 1: OverflowError: int too long to convert ``` Although I can't personally get this to trigger at all under 64-bit python, either in PyCharm *or* with the 5.7.1-alpha1 64-bit pre-release. `game_running()` is only used in a few places, and the key things it malfunctioning might cause are lack of the synthetic `ShutDown` (already has an INFO logging) and `StartUp` events. --- monitor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/monitor.py b/monitor.py index 126e04c7..049e75da 100644 --- a/monitor.py +++ b/monitor.py @@ -415,6 +415,7 @@ 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())), From 085159f8cb012f2f94956429dab2fb1e93025cb7 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 12 Jan 2023 15:03:43 +0000 Subject: [PATCH 240/257] When it's a StartUp event say *that*, not Startup This check in EDMarketConnector.py is explicitly for StartUp (and Loadgame), not Startup, so have the logging say that. --- EDMarketConnector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index fe31304d..0c1df7b8 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1567,7 +1567,7 @@ 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: From b39d669ce7bcca4da248af2884af8cc6464cfc6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 17:02:49 +0000 Subject: [PATCH 241/257] build(deps): bump requests from 2.28.1 to 2.28.2 Bumps [requests](https://github.com/psf/requests) from 2.28.1 to 2.28.2. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.28.1...v2.28.2) --- updated-dependencies: - dependency-name: requests dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5244e2f0..44d3f92d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ certifi==2022.12.7 -requests==2.28.1 +requests==2.28.2 watchdog==2.2.1 # Commented out because this doesn't package well with py2exe infi.systray==0.1.12; sys_platform == 'win32' From 60b14999bec2265234e15ae2b9fba7ddf2c99d84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 17:03:03 +0000 Subject: [PATCH 242/257] build(deps-dev): bump setuptools from 65.6.3 to 65.7.0 Bumps [setuptools](https://github.com/pypa/setuptools) from 65.6.3 to 65.7.0. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v65.6.3...v65.7.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 6a0ace7f..cc41469c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -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==65.7.0 # Static analysis tools flake8==6.0.0 From b5bb9657d87f475cba16f51c5da0c9526d31230f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 15 Jan 2023 21:54:02 +0000 Subject: [PATCH 243/257] eddn: Move `tracking_ui_update()` nearer top of `journal_entry()` With the tracking now being in monitor.py this needs to be ASAP after the local copies of the tracking have been updated. Below the possible `this.status_body_name` blanking, in case that's hit. --- plugins/eddn.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index ab7d2fa3..ace4f27f 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -2224,6 +2224,8 @@ def journal_entry( # noqa: C901, CCR001 if entry['MusicTrack'] == 'MainMenu': 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']: @@ -2409,8 +2411,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 From 93acfd058212da045530bf0db01867394fc66542 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 17:01:02 +0000 Subject: [PATCH 244/257] build(deps-dev): bump setuptools from 65.7.0 to 66.0.0 Bumps [setuptools](https://github.com/pypa/setuptools) from 65.7.0 to 66.0.0. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v65.7.0...v66.0.0) --- updated-dependencies: - dependency-name: setuptools dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index cc41469c..b608ae1f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -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.7.0 +setuptools==66.0.0 # Static analysis tools flake8==6.0.0 From 357bdb92fbc159d39ed03af847ddb0971f48f97b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 17:01:08 +0000 Subject: [PATCH 245/257] build(deps-dev): bump pytest from 7.2.0 to 7.2.1 Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.2.0 to 7.2.1. - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.2.0...7.2.1) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index cc41469c..add78710 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -44,7 +44,7 @@ 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]==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 From 46fd129d3e6a0677b36340c794a5883931573cf1 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 16 Jan 2023 18:10:57 +0000 Subject: [PATCH 246/257] eddn: Expand the tracking UI for all system, body & station location data * Also renamed This.systemaddress to this.system_address, which impacted misc. other lines of code. --- plugins/eddn.py | 115 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 97 insertions(+), 18 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index ace4f27f..07209758 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -82,10 +82,14 @@ 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.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 @@ -117,9 +121,14 @@ 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_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() @@ -1116,11 +1125,11 @@ 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 version @@ -1159,7 +1168,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 ?' @@ -1201,7 +1210,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 ?' @@ -1263,7 +1272,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 ?' @@ -1357,7 +1366,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 ?' @@ -1652,7 +1661,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 ?' @@ -1702,7 +1711,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 ?' @@ -1758,7 +1767,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 ?' @@ -1816,11 +1825,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 @@ -1964,23 +1973,69 @@ 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="S:Name:") + 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="S:Address:") + 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 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 @@ -1992,6 +2047,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 @@ -2004,6 +2067,18 @@ def tracking_ui_update() -> 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() @@ -2214,7 +2289,11 @@ def journal_entry( # noqa: C901, CCR001 this.body_name = state['Body'] this.body_id = state['BodyID'] this.coordinates = state['StarPos'] - this.systemaddress = state['SystemAddress'] + 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'] if event_name == 'docked': # Trigger a send/retry of pending EDDN messages @@ -2339,7 +2418,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?" @@ -2356,7 +2435,7 @@ def journal_entry( # noqa: C901, CCR001 # Gazelle[TD] reported seeing a lagged Scan event with incorrect # augmented StarPos: - 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?" From 2f2ee885c8a4fae17403ca2ee1cd65e25c1d2386 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 16 Jan 2023 19:30:02 +0000 Subject: [PATCH 247/257] monitor/tracking: *Do* clear supercruisentry/body state if Station type --- monitor.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/monitor.py b/monitor.py index c65aef5c..bd82fe8e 100644 --- a/monitor.py +++ b/monitor.py @@ -1000,9 +1000,13 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['BodyType'] = None elif event_type == 'supercruiseentry': - # NB: Do **NOT** clear Body state, because we won't get a fresh - # ApproachBody if we don't leave Orbital Cruise but land - # again. + # 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 From dbb471f2c281a1f1e49ae5fa0743d409362e8e52 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Mon, 16 Jan 2023 19:32:44 +0000 Subject: [PATCH 248/257] eddn/tracking: Add BodyType to tracking UI This helps demonstrate that a 'spurious' Station BodyName/ID is actually OK, because BodyType makes it clear. --- plugins/eddn.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/eddn.py b/plugins/eddn.py index 07209758..4577aba5 100644 --- a/plugins/eddn.py +++ b/plugins/eddn.py @@ -87,6 +87,7 @@ class This: 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 @@ -125,6 +126,7 @@ class This: 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 @@ -1978,13 +1980,13 @@ def plugin_app(parent: tk.Tk) -> Optional[tk.Frame]: # System ####################################################################### # SystemName - system_name_label = tk.Label(this.ui, text="S:Name:") + 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="S:Address:") + 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) @@ -2006,6 +2008,12 @@ def plugin_app(parent: tk.Tk) -> Optional[tk.Frame]: 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) @@ -2063,6 +2071,10 @@ 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 @@ -2288,6 +2300,7 @@ def journal_entry( # noqa: C901, CCR001 # 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'] From 5bd14ddd788288eba3a7f132d70ad78bbf0437dd Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 13 Jan 2023 14:04:01 +0000 Subject: [PATCH 249/257] monitor: Don't synthesize StartUp if current event is ShutDown --- monitor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index 0b3a5a67..1770195c 100644 --- a/monitor.py +++ b/monitor.py @@ -2120,7 +2120,7 @@ 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 entry = self.synthesize_startup_event() From 63b14f5caebdfa4ef64e3e7eaaaaf3941ba098d5 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 17 Jan 2023 16:00:50 +0000 Subject: [PATCH 250/257] Translations: Latest imported from OneSky --- L10n/cs.strings | 722 ++++++++++++++++---------------- L10n/de.strings | 864 ++++++++++++++++++++------------------- L10n/es.strings | 748 +++++++++++++++++----------------- L10n/fi.strings | 668 +++++++++++++++--------------- L10n/fr.strings | 568 +++++++++++++------------- L10n/hu.strings | 546 ++++++++++++------------- L10n/it.strings | 688 +++++++++++++++---------------- L10n/ja.strings | 882 ++++++++++++++++++++------------------- L10n/ko.strings | 790 +++++++++++++++++------------------ L10n/lv.strings | 516 +++++++++++------------ L10n/nl.strings | 564 ++++++++++++------------- L10n/pl.strings | 846 +++++++++++++++++++------------------- L10n/pt-BR.strings | 884 +++++++++++++++++++++------------------- L10n/pt-PT.strings | 882 ++++++++++++++++++++------------------- L10n/ru.strings | 882 ++++++++++++++++++++------------------- L10n/sl.strings | 460 ++++++++++----------- L10n/sr-Latn-BA.strings | 852 +++++++++++++++++++------------------- L10n/sr-Latn.strings | 882 ++++++++++++++++++++------------------- L10n/sv-SE.strings | 560 ++++++++++++------------- L10n/uk.strings | 634 ++++++++++++++-------------- L10n/zh-Hans.strings | 846 +++++++++++++++++++------------------- 21 files changed, 7708 insertions(+), 7576 deletions(-) diff --git a/L10n/cs.strings b/L10n/cs.strings index cbb40363..90519f65 100644 --- a/L10n/cs.strings +++ b/L10n/cs.strings @@ -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ě"; diff --git a/L10n/de.strings b/L10n/de.strings index a1350b05..4ba8793d 100644 --- a/L10n/de.strings +++ b/L10n/de.strings @@ -1,719 +1,749 @@ /* Language name */ "!Language" = "Deutsch"; -/* 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..." = "Daten werden an das EDDN gesendet..."; - -/* 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" = "Fehler: Keine Verbindung zum 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" = "Schicke Stationsdaten an das Elite Dangerous Data Netzwerk"; - -/* 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" = "Sende System- und Scandaten zum 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" = "Senden verzögern bis angedockt"; - -/* 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" = "Sende Fluglog und CMDR-Status an 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 Anmeldedaten"; - -/* 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" = "Kdt."; - -/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */ -"Commander Name" = "Kommandantenname"; - -/* 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 Schlüssel"; - -/* 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" = "Keine Zuweisung"; - -/* 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}" = "Fehler: 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" = "Fehler: Kann keine Verbindung zu EDSM aufbauen"; - -/* 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" = "Sende Fluglog und CMDR-Status an 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-Anmeldedaten"; - -/* 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}" = "Fehler: 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='" = "Setze die zu nutzende URL für coriolis.io Schiffsausrüstungen. Beachte, dass sie auf '/import?data=' enden muss."; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "Normale URL"; - -/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */ -"Reset" = "Zurücksetzen"; - -/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */ -"Beta URL" = "Beta-URL"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "Beta/Standard-Auswahl überschreiben"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "Ungültiger Coriolis-Überschreibungsmodus!"; - -/* 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 Journal-Verarbeitung deaktiviert. Siehe Log."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "EDDN Journal-Handler deaktiviert. Siehe Log."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "EDSM-Handler deaktiviert. Siehe Log."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara deaktiviert. Siehe 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: Keine Kommandanten-Daten erhalten"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "Beta/Normal-Auswahl überschreiben"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN-Fehler: EDMC ist zu alt für EDDN. Bitte aktualisieren."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN-Fehler: Validierung fehlgeschlagen (EDMC zu alt?). Siehe Log"; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "EDDN-Fehler: {STATUS} Statuscode zurückgegeben"; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "Kein 'Route'-Array in NavRoute.json enthalten"; - -/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */ -"Journal directory already locked" = "Journal-Ordner bereits gesperrt"; - -/* 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." = "Der neue Journal-Ordnerpfad ist bereits gesperrt.{CR}Du kannst entweder versuchen, das zu beheben und es nochmal zu probieren, oder diese Meldung ignorieren."; - -/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */ -"Retry" = "Wiederholen"; - -/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */ -"Ignore" = "Ignorieren"; - -/* 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" = "Kopieren"; - -/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */ -"Update" = "Aktualisieren"; - -/* 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" = "Immer im Vordergrund"; - -/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */ -"Unknown" = "Unbekannt"; - -/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "Fehler: Prüfe E:D Journal Dateispeicherort"; - -/* 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" = "Rolle"; - -/* 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" = "Schiff"; - -/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */ -"Suit" = "Anzug"; - -/* 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" = "Datei"; - -/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */ -"Edit" = "Bearbeiten"; - -/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */ -"View" = "Ansicht"; - -/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */ -"Window" = "Fenster"; - -/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */ -"Help" = "Hilfe"; - -/* 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}" = "Über {APP}"; - -/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */ -"Check for Updates..." = "Auf Aktualisierungen überprüfen..."; - -/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */ -"Save Raw Data..." = "Speichere Originaldaten..."; - -/* 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" = "Datenschutzrichtlinie"; - -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */ -"Release Notes" = "Anmerkungen"; - -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */ -"Settings" = "Einstellungen"; - -/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */ -"Exit" = "Beenden"; - -/* 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..." = "Anmelden..."; - -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */ -"Authentication successful" = "Authentifizierung erfolgreich"; - -/* 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 bist an keiner Station angedockt!"; - -/* 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!" = "Diese Station hat nichts!"; - -/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */ -"Station doesn't have a market!" = "Diese Station hat keinen Markt!"; - -/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "CAPI Anfrage abgebrochen: Kdt. Name unbekannt"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "CAPI Anfrage abgebrochen: Spielmodus unbekannt"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "CAPI Anfrage abgebrochen: Aktuelles System unbekannt"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "CAPI Anfrage abgebrochen: In anderem Schiff in Multicrew"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "CAPI Anfrage abgebrochen: CQC (Arena) erkannt"; - -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */ -"Fetching data..." = "Daten werden abgerufen..."; - -/* 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?!" = "Wer bist du?!"; - -/* 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?!" = "Wo bist du?!"; - -/* 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?!" = "Was fliegst du?!"; - -/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Frontier CAPI Server-Fehler"; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI: Erneuere Access-Token..."; - -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */ -"Last updated at %H:%M:%S" = "Zuletzt aktualisiert um %H:%M:%S"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */ -"Fighter" = "Fighter"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */ -"Gunner" = "Kanonier"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */ -"Helm" = "Steuer"; - -/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */ -"cooldown {SS}s" = "Wartezeit {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..." = "Programm schließt..."; - -/* 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." = "Eins oder mehr deiner aktivierten Plugins hat noch keinen Support für Python 3.x. Du kannst dir die Liste im '{PLUGINS}'-Tab unter '{FILE}' > '{SETTINGS}' ansehen. Du solltest prüfen, ob es für diese Updates gibt und ansonsten dem Entwickler Bescheid geben, dass sie ihren Code für Python 3.x aktualisieren müssen.\n\nDu kannst ein Plugin deaktivieren, indem du dessen Ordner ein '{DISABLED}' am Ende des Namens anhängst."; - -/* 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 ohne Python 3.x Support"; - -/* 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" = "Fehler: Frontier CAPI antwortet nicht"; -/* 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" = "Fehler: Frontier-Server ist überlastet"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "Angedockt aber unbekannte Station: EDO-Siedlung?"; -/* 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" = "Fehler: Ungültige Anmeldedaten"; -/* 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" = "Fehler: Falscher Kdt."; -/* 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" = "Fehler"; -/* 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" = "Fehler: Konnte das Token customer_id nicht prüfen"; -/* 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!" = "Fehler: customer_id stimmt nicht überein!"; -/* 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" = "Fehler: konnte Token nicht erhalten"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "Frontier CAPI offline wegen Wartung"; -/* 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 Anfrage gescheitert"; -/* 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" = "Aktualisieren"; + +/* 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" = "Immer im Vordergrund"; + +/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */ +"Unknown" = "Unbekannt"; + +/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "Fehler: Prüfe E:D Journal Dateispeicherort"; + +/* 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" = "Kdt."; + +/* 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" = "Rolle"; + +/* 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" = "Schiff"; + +/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */ +"Suit" = "Anzug"; + +/* 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" = "Datei"; + +/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */ +"Edit" = "Bearbeiten"; + +/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */ +"View" = "Ansicht"; + +/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */ +"Window" = "Fenster"; + +/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */ +"Help" = "Hilfe"; + +/* 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}" = "Über {APP}"; + +/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */ +"Check for Updates..." = "Auf Aktualisierungen überprüfen..."; + +/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */ +"Save Raw Data..." = "Speichere Originaldaten..."; + +/* 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 > Troubleshooting; In files: EDMarketConnector.py:934; EDMarketConnector.py:954; */ +"Troubleshooting" = "Problembehandlung"; + +/* EDMarketConnector.py: Help > Report A Bug; In files: EDMarketConnector.py:935; EDMarketConnector.py:955; */ +"Report A Bug" = "Fehler melden"; + +/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */ +"Privacy Policy" = "Datenschutzrichtlinie"; + +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */ +"Release Notes" = "Anmerkungen"; + +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */ +"Settings" = "Einstellungen"; + +/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */ +"Exit" = "Beenden"; + +/* 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" = "Kopieren"; + +/* EDMarketConnector.py: CAPI auth aborted because of killswitch; EDMarketConnector.py: CAPI auth query aborted because of killswitch; In files: EDMarketConnector.py:973; EDMarketConnector.py:1067; */ +"CAPI auth disabled by killswitch" = "CAPI auth durch Killswitch deaktiviert"; + +/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */ +"Logging in..." = "Anmelden..."; + +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */ +"Authentication successful" = "Authentifizierung erfolgreich"; + +/* 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 bist an keiner Station angedockt!"; + +/* 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!" = "Diese Station hat nichts!"; + +/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */ +"Station doesn't have a market!" = "Diese Station hat keinen Markt!"; + +/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "CAPI Anfrage abgebrochen: Kdt. Name unbekannt"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "CAPI Anfrage abgebrochen: Spielmodus unbekannt"; + +/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because GameVersion unknown; In files: EDMarketConnector.py:1089; EDMarketConnector.py:1170; */ +"CAPI query aborted: GameVersion unknown" = "CAPI-Anfrage abgebrochen: GameVersion unbekannt"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "CAPI Anfrage abgebrochen: Aktuelles System unbekannt"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "CAPI Anfrage abgebrochen: In anderem Schiff in Multicrew"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "CAPI Anfrage abgebrochen: CQC (Arena) erkannt"; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ +"Fetching data..." = "Daten werden abgerufen..."; + +/* EDMarketConnector.py: CAPI fleetcarrier query aborted because of killswitch; In files: EDMarketConnector.py:1157; */ +"CAPI fleetcarrier disabled by killswitch" = "CAPI Fleet Carrier durch Killswitch deaktiviert"; + +/* EDMarketConnector.py: No data was returned for the fleetcarrier from the Frontier CAPI; In files: EDMarketConnector.py:1219; */ +"CAPI: No fleetcarrier data returned" = "CAPI: Keine Fleet Carrier-Daten erhalten"; + +/* EDMarketConnector.py: We didn't have the fleetcarrier callsign when we should have; In files: EDMarketConnector.py:1223; */ +"CAPI: Fleetcarrier data incomplete" = "CAPI: Fleet Carrier-Daten unvollständig"; + +/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */ +"CAPI: No commander data returned" = "CAPI: Keine Kommandanten-Daten erhalten"; + +/* 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?!" = "Wer bist du?!"; + +/* 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?!" = "Wo bist du?!"; + +/* 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?!" = "Was fliegst du?!"; + +/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Frontier CAPI Server-Fehler"; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ +"CAPI: Refreshing access token..." = "CAPI: Erneuere Access-Token..."; + +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */ +"Last updated at %H:%M:%S" = "Zuletzt aktualisiert um %H:%M:%S"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */ +"Fighter" = "Fighter"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */ +"Gunner" = "Kanonier"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */ +"Helm" = "Steuer"; + +/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */ +"cooldown {SS}s" = "Wartezeit {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..." = "Programm schließt..."; + +/* 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." = "Eins oder mehr deiner aktivierten Plugins hat noch keinen Support für Python 3.x. Du kannst dir die Liste im '{PLUGINS}'-Tab unter '{FILE}' > '{SETTINGS}' ansehen. Du solltest prüfen, ob es für diese Updates gibt und ansonsten dem Entwickler Bescheid geben, dass sie ihren Code für Python 3.x aktualisieren müssen.\n\nDu kannst ein Plugin deaktivieren, indem du dessen Ordner ein '{DISABLED}' am Ende des Namens anhängst."; + +/* 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 ohne Python 3.x Support"; + +/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:208; */ +"Journal directory already locked" = "Journal-Ordner bereits gesperrt"; + +/* 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." = "Der neue Journal-Ordnerpfad ist bereits gesperrt.{CR}Du kannst entweder versuchen, das zu beheben und es nochmal zu probieren, oder diese Meldung ignorieren."; + +/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */ +"Retry" = "Wiederholen"; + +/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */ +"Ignore" = "Ignorieren"; + +/* 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; */ +/* 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='" = "Setze die zu nutzende URL für coriolis.io Schiffsausrüstungen. Beachte, dass sie auf '/import?data=' enden muss."; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "Normale URL"; + +/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */ +"Reset" = "Zurücksetzen"; + +/* 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" = "Beta/Normal-Auswahl überschreiben"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "Ungültiger Coriolis-Überschreibungsmodus!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "EDDB Journal-Verarbeitung deaktiviert. Siehe 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" = "Fehler: Keine Verbindung zum EDDN"; + +/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN-Fehler: EDMC ist zu alt für EDDN. Bitte aktualisieren."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN-Fehler: Validierung fehlgeschlagen (EDMC zu alt?). Siehe Log"; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "EDDN-Fehler: {STATUS} Statuscode zurückgegeben"; + +/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */ +"Send station data to the Elite Dangerous Data Network" = "Schicke Stationsdaten an das Elite Dangerous Data Netzwerk"; + +/* 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" = "Sende System- und Scandaten zum 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" = "Senden verzögern bis angedockt"; + +/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "EDDN Journal-Handler deaktiviert. Siehe Log."; + +/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */ +"Sending data to EDDN..." = "Daten werden an das EDDN gesendet..."; + +/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */ +"Send flight log and Cmdr status to EDSM" = "Sende Fluglog und CMDR-Status an 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 Anmeldedaten"; + +/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */ +"Commander Name" = "Kommandantenname"; + +/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */ +"API Key" = "API Schlüssel"; + +/* 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" = "Keine Zuweisung"; + +/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "EDSM-Handler deaktiviert. Siehe Log."; + +/* edsm.py: EDSM - Only Live data; In files: edsm.py:632; */ +"EDSM only accepts Live galaxy data" = "EDSM akzeptiert ausschließlich Live-Galaxiedaten"; + +/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */ +"Error: EDSM {MSG}" = "Fehler: 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" = "Fehler: Kann keine Verbindung zu EDSM aufbauen"; + +/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */ +"Send flight log and Cmdr status to Inara" = "Sende Fluglog und CMDR-Status an Inara"; + +/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */ +"Inara credentials" = "Inara-Anmeldedaten"; + +/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; inara.py: Inara - Only Live data; In files: inara.py:384; inara.py:386; */ +"Inara only accepts Live galaxy data" = "Inara akzeptiert ausschließlich Live-Galaxiedaten"; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "Inara deaktiviert. Siehe 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}" = "Fehler: Inara {MSG}"; + +/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */ "Preferences" = "Einstellungen"; -/* 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" = "Bitte wähle zu speichernde Daten aus"; -/* 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" = "Marktdaten als CSV Datei"; -/* 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" = "Marktdaten als Trade-Dangerous Datei"; -/* prefs.py: Settings > Output option; In files: prefs.py:373; */ +/* prefs.py: Settings > Output option; In files: prefs.py:360; */ "Ship loadout" = "Schiffsausstattung"; -/* 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 beim Andocken aktualisieren"; -/* 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" = "Speicherort"; -/* 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..." = "Ordner..."; -/* 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..." = "Durchsuchen..."; -/* 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" = "Ausgabe"; -/* 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 Dateispeicherort"; -/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */ +/* prefs.py: Settings > Configuration - Label for CAPI section; In files: prefs.py:469; */ +"CAPI Settings" = "CAPI-Einstellungen"; + +/* prefs.py: Configuration - Enable or disable the Fleet Carrier CAPI calls; In files: prefs.py:475; */ +"Enable Fleetcarrier CAPI Queries" = "Fleet Carrier CAPI-Anfragen aktivieren"; + +/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */ "Keyboard shortcut" = "Makro"; -/* 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" = "Starte {APP} neu, um den Tastenkürzel nutzen zu können"; -/* 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} benötigt für Tastenkürzel Systemrechte (Bedienungshilfen)"; -/* 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" = "Öffne Systemeinstellungen"; -/* 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" = "Nur wenn Elite: Dangerous geöffnet ist"; -/* 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" = "Ton abspielen"; -/* 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" = "Während das Spiel läuft nicht auf Updates überprüfen"; -/* 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" = "Favorisierte Webseiten"; -/* 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" = "Werft"; -/* 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" = "Alternative URL-Methode benutzen"; -/* 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" = "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" = "Konfiguration"; -/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "Haupt-UI-Datenschutzoptionen"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "Private Gruppe-Name im UI verstecken"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "Multi-Crew Kapitänsnamen verstecken"; -/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */ +/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */ "Privacy" = "Datenschutz"; -/* 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" = "Normaler 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" = "Hervorgehobener 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" = "Sprache"; -/* 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" = "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" = "Dunkel"; -/* 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: 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" = "UI-Skalierung in Prozent"; -/* 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 bedeutet Standardwert{CR}Neustart erforderlich, um{CR}Änderungen zu übernehmen!"; -/* 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" = "Durchsichtigkeit Hauptfenster"; -/* 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 bedeutet komplett undurchsichtig.{CR}Fenster wird in Echtzeit aktualisiert"; -/* 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" = "In die Taskleiste minimieren"; -/* 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" = "Aussehen"; -/* 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-Ordner"; -/* 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" = "Öffnen"; -/* 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: Du kannst ein Plugin deaktivieren, indem{CR}du '{EXT}' zu seinem Ordnernamen hinzufügst"; -/* 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" = "Aktivierte 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:" = "Plugins ohne Python 3.x Support"; -/* 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" = "Informationen zum Migrieren von 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" = "Deaktivierte Plugins"; -/* stats.py: Cmdr stats; In files: stats.py:60; */ +/* stats.py: Cmdr stats; In files: stats.py:58; */ "Balance" = "Kontostand"; -/* stats.py: Cmdr stats; In files: stats.py:61; */ +/* stats.py: Cmdr stats; In files: stats.py:59; */ "Loan" = "Kredit"; -/* stats.py: Top rank; In files: stats.py:65; */ +/* stats.py: Top rank; In files: stats.py:63; */ "Elite" = "Elite"; -/* stats.py: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Elite I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Elite II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Elite III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Elite IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Elite V"; -/* stats.py: Ranking; In files: stats.py:76; */ +/* stats.py: Ranking; In files: stats.py:74; */ "Combat" = "Kampfrang"; -/* stats.py: Ranking; In files: stats.py:77; */ +/* stats.py: Ranking; In files: stats.py:75; */ "Trade" = "Handelsrang"; -/* stats.py: Ranking; In files: stats.py:78; */ +/* stats.py: Ranking; In files: stats.py:76; */ "Explorer" = "Erkunderrang"; -/* stats.py: Ranking; In files: stats.py:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "Söldner"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "Exobiologe"; -/* stats.py: Ranking; In files: stats.py:81; */ +/* stats.py: Ranking; In files: stats.py:79; */ "CQC" = "CQC-Rang"; -/* stats.py: Ranking; In files: stats.py:82; */ +/* stats.py: Ranking; In files: stats.py:80; */ "Federation" = "Föderation"; -/* stats.py: Ranking; In files: stats.py:83; */ +/* stats.py: Ranking; In files: stats.py:81; */ "Empire" = "Imperium"; -/* stats.py: Ranking; In files: stats.py:84; */ +/* stats.py: Ranking; In files: stats.py:82; */ "Powerplay" = "Machtspiele"; -/* stats.py: Combat rank; In files: stats.py:93; */ +/* stats.py: Combat rank; In files: stats.py:91; */ "Harmless" = "Harmlos"; -/* stats.py: Combat rank; In files: stats.py:94; */ +/* stats.py: Combat rank; In files: stats.py:92; */ "Mostly Harmless" = "Zumeist Harmlos"; -/* stats.py: Combat rank; In files: stats.py:95; */ +/* stats.py: Combat rank; In files: stats.py:93; */ "Novice" = "Neuling"; -/* stats.py: Combat rank; In files: stats.py:96; */ +/* stats.py: Combat rank; In files: stats.py:94; */ "Competent" = "Kompetent"; -/* stats.py: Combat rank; In files: stats.py:97; */ +/* stats.py: Combat rank; In files: stats.py:95; */ "Expert" = "Experte"; -/* 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" = "Meister"; -/* stats.py: Combat rank; In files: stats.py:99; */ +/* stats.py: Combat rank; In files: stats.py:97; */ "Dangerous" = "Gefährlich"; -/* stats.py: Combat rank; In files: stats.py:100; */ +/* stats.py: Combat rank; In files: stats.py:98; */ "Deadly" = "Tödlich"; -/* stats.py: Trade rank; In files: stats.py:103; */ +/* stats.py: Trade rank; In files: stats.py:101; */ "Penniless" = "Bettelarm"; -/* stats.py: Trade rank; In files: stats.py:104; */ +/* stats.py: Trade rank; In files: stats.py:102; */ "Mostly Penniless" = "Sehr Arm"; -/* stats.py: Trade rank; In files: stats.py:105; */ +/* stats.py: Trade rank; In files: stats.py:103; */ "Peddler" = "Krämer"; -/* stats.py: Trade rank; In files: stats.py:106; */ +/* stats.py: Trade rank; In files: stats.py:104; */ "Dealer" = "Kleinhändler"; -/* stats.py: Trade rank; In files: stats.py:107; */ +/* stats.py: Trade rank; In files: stats.py:105; */ "Merchant" = "Kaufmann"; -/* stats.py: Trade rank; In files: stats.py:108; */ +/* stats.py: Trade rank; In files: stats.py:106; */ "Broker" = "Großhändler"; -/* stats.py: Trade rank; In files: stats.py:109; */ +/* stats.py: Trade rank; In files: stats.py:107; */ "Entrepreneur" = "Unternehmer"; -/* 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" = "Total planlos"; -/* stats.py: Explorer rank; In files: stats.py:114; */ +/* stats.py: Explorer rank; In files: stats.py:112; */ "Mostly Aimless" = "Fast Planlos"; -/* stats.py: Explorer rank; In files: stats.py:115; */ +/* stats.py: Explorer rank; In files: stats.py:113; */ "Scout" = "Späher"; -/* stats.py: Explorer rank; In files: stats.py:116; */ +/* stats.py: Explorer rank; In files: stats.py:114; */ "Surveyor" = "Landkundiger"; -/* stats.py: Explorer rank; In files: stats.py:117; */ +/* stats.py: Explorer rank; In files: stats.py:115; */ "Trailblazer" = "Wegebner"; -/* stats.py: Explorer rank; In files: stats.py:118; */ +/* stats.py: Explorer rank; In files: stats.py:116; */ "Pathfinder" = "Pistensucher"; -/* stats.py: Explorer rank; In files: stats.py:119; */ +/* stats.py: Explorer rank; In files: stats.py:117; */ "Ranger" = "Aufseher"; -/* stats.py: Explorer rank; In files: stats.py:120; */ +/* stats.py: Explorer rank; In files: stats.py:118; */ "Pioneer" = "Pionier"; -/* stats.py: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Wehrlos"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "Fast Wehrlos"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Anfänger"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Soldat"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Revolverheld"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ +"Warrior" = "Krieger"; + +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Ziellos"; -/* stats.py: CQC rank; In files: stats.py:144; */ +/* stats.py: CQC rank; In files: stats.py:142; */ "Helpless" = "Hilflos"; -/* stats.py: CQC rank; In files: stats.py:145; */ +/* stats.py: CQC rank; In files: stats.py:143; */ "Mostly Helpless" = "Zumeist Hilflos"; -/* stats.py: CQC rank; In files: stats.py:146; */ +/* stats.py: CQC rank; In files: stats.py:144; */ "Amateur" = "Anfänger"; -/* stats.py: CQC rank; In files: stats.py:147; */ +/* stats.py: CQC rank; In files: stats.py:145; */ "Semi Professional" = "Halbprofi"; -/* stats.py: CQC rank; In files: stats.py:148; */ +/* stats.py: CQC rank; In files: stats.py:146; */ "Professional" = "Profi"; -/* stats.py: CQC rank; In files: stats.py:149; */ +/* stats.py: CQC rank; In files: stats.py:147; */ "Champion" = "Sieger"; -/* stats.py: CQC rank; In files: stats.py:150; */ +/* stats.py: CQC rank; In files: stats.py:148; */ "Hero" = "Held"; -/* 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" = "Rekrut"; -/* stats.py: Federation rank; In files: stats.py:158; */ +/* stats.py: Federation rank; In files: stats.py:156; */ "Cadet" = "Kadett"; -/* stats.py: Federation rank; In files: stats.py:159; */ +/* stats.py: Federation rank; In files: stats.py:157; */ "Midshipman" = "Fähnrich"; -/* stats.py: Federation rank; In files: stats.py:160; */ +/* stats.py: Federation rank; In files: stats.py:158; */ "Petty Officer" = "Maat"; -/* stats.py: Federation rank; In files: stats.py:161; */ +/* stats.py: Federation rank; In files: stats.py:159; */ "Chief Petty Officer" = "Obermaat"; -/* stats.py: Federation rank; In files: stats.py:162; */ +/* stats.py: Federation rank; In files: stats.py:160; */ "Warrant Officer" = "Feldwebel"; -/* stats.py: Federation rank; In files: stats.py:163; */ +/* stats.py: Federation rank; In files: stats.py:161; */ "Ensign" = "Leutnant"; -/* stats.py: Federation rank; In files: stats.py:164; */ +/* stats.py: Federation rank; In files: stats.py:162; */ "Lieutenant" = "Kapitänleutnant"; -/* stats.py: Federation rank; In files: stats.py:165; */ +/* stats.py: Federation rank; In files: stats.py:163; */ "Lieutenant Commander" = "Korvettenleutnant"; -/* stats.py: Federation rank; In files: stats.py:166; */ +/* stats.py: Federation rank; In files: stats.py:164; */ "Post Commander" = "Fregattenkapitän"; -/* stats.py: Federation rank; In files: stats.py:167; */ +/* stats.py: Federation rank; In files: stats.py:165; */ "Post Captain" = "Kapitän"; -/* stats.py: Federation rank; In files: stats.py:168; */ +/* stats.py: Federation rank; In files: stats.py:166; */ "Rear Admiral" = "Konteradmiral"; -/* stats.py: Federation rank; In files: stats.py:169; */ +/* stats.py: Federation rank; In files: stats.py:167; */ "Vice Admiral" = "Vizeadmiral"; -/* 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" = "Fremder"; -/* stats.py: Empire rank; In files: stats.py:177; */ +/* stats.py: Empire rank; In files: stats.py:175; */ "Serf" = "Leibeigener"; -/* stats.py: Empire rank; In files: stats.py:179; */ +/* stats.py: Empire rank; In files: stats.py:177; */ "Squire" = "Knappe"; -/* stats.py: Empire rank; In files: stats.py:180; */ +/* stats.py: Empire rank; In files: stats.py:178; */ "Knight" = "Ritter"; -/* stats.py: Empire rank; In files: stats.py:181; */ +/* stats.py: Empire rank; In files: stats.py:179; */ "Lord" = "Fürst"; -/* 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" = "Graf"; -/* 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" = "Marquise"; -/* stats.py: Empire rank; In files: stats.py:187; */ +/* stats.py: Empire rank; In files: stats.py:185; */ "Duke" = "Herzog"; -/* stats.py: Empire rank; In files: stats.py:188; */ +/* stats.py: Empire rank; In files: stats.py:186; */ "Prince" = "Prinz"; -/* stats.py: Empire rank; In files: stats.py:189; */ +/* stats.py: Empire rank; In files: stats.py:187; */ "King" = "König"; -/* stats.py: Power rank; In files: stats.py:195; */ +/* stats.py: Power rank; In files: stats.py:193; */ "Rating 1" = "Wertung 1"; -/* stats.py: Power rank; In files: stats.py:196; */ +/* stats.py: Power rank; In files: stats.py:194; */ "Rating 2" = "Wertung 2"; -/* stats.py: Power rank; In files: stats.py:197; */ +/* stats.py: Power rank; In files: stats.py:195; */ "Rating 3" = "Wertung 3"; -/* stats.py: Power rank; In files: stats.py:198; */ +/* stats.py: Power rank; In files: stats.py:196; */ "Rating 4" = "Wertung 4"; -/* stats.py: Power rank; In files: stats.py:199; */ +/* stats.py: Power rank; In files: stats.py:197; */ "Rating 5" = "Wertung 5"; -/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "Status: Dein Kommandanten-Name ist noch nicht bekannt"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "Status: Noch keine CAPI-Daten"; -/* 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" = "Wert"; -/* stats.py: Status dialog title; In files: stats.py:422; */ +/* stats.py: Status dialog title; In files: stats.py:418; */ "Ships" = "Schiffe"; diff --git a/L10n/es.strings b/L10n/es.strings index 3d1e5143..abced1a9 100644 --- a/L10n/es.strings +++ b/L10n/es.strings @@ -1,638 +1,638 @@ /* Language name */ "!Language" = "Español"; -/* 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..." = "Enviando datos 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" = "Error: No se puede conectar 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" = "Enviar datos de la estación 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" = "Enviar datos de sistema y escáner a 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" = "Retrasar envío hasta el atraque"; - -/* 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" = "Enviar Registro de Vuelo y estado del CMDT 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" = "Credenciales de 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" = "Cmdt"; - -/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */ -"Commander Name" = "Nombre de Comandante"; - -/* 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" = "Llave 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" = "Ninguna"; - -/* 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}" = "Error: 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" = "Error: No se puede conectar 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" = "Enviar Registro de Vuelo y estado del CMDT 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" = "Credenciales de 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}" = "Error: 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='" = "Configura la URL para usar con equipamiento de naves en coriolis.io. Nota, debe acabar en '/import?data='"; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "URL Normal"; - -/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */ -"Reset" = "Reiniciar"; - -/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */ -"Beta URL" = "URL Beta"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "¡Modo sobrescritura de Coriolis Inválido!"; - -/* eddb.py: Journal Processing disabled due to an active killswitch; In files: load.py:99; eddb.py:100; */ -"EDDB Journal processing disabled. See Log." = "Procesamiento de Journal para EDDB desactivado. Ver Log."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "Manejo de Journal para EDDN desactivado. Ver Log."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "Manejo de Journal para EDSM desactivado. Ver Log."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara desactivado. Ver 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: No se devolvió datos de comandante"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "Sobrescribir Selección Beta/Normal"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "Error EDDN: EDMC es demasiado antiguo para EDDN. Actualiza por favor."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Error EDDN: Validación Fallida (¿EDMC Demasiado Antiguo?). Revisa el Log"; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "Error EDDN: Devolvió código de estado {STATUS}"; - -/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */ -"Journal directory already locked" = "El Directorio Journal ya está bloqueado"; - -/* 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 localización Directorio Journal ya está bloqueada.{CR}Puedes intentar resolverlo y pulsar Reintentar, o elegir Ignorar esto."; - -/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */ -"Retry" = "Reintentar"; - -/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */ -"Ignore" = "Ignorar"; - -/* 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" = "Copiar"; - -/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */ -"Update" = "Actualizar"; - -/* 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" = "Siempre visible"; - -/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */ -"Unknown" = "Desconocido"; - -/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "Error: Comprueba la localización del fichero journal de E:D"; - -/* 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" = "Nave"; - -/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */ -"Suit" = "Traje"; - -/* 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" = "Estación"; - -/* 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" = "Archivo"; - -/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */ -"Edit" = "Editar"; - -/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */ -"View" = "Visualización"; - -/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */ -"Window" = "Ventana"; - -/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */ -"Help" = "Ayuda"; - -/* 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}" = "Acerca de {APP}"; - -/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */ -"Check for Updates..." = "Buscar Actualizaciones..."; - -/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */ -"Save Raw Data..." = "Guardar Datos Sin Procesar..."; - -/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */ -"Status" = "Estado"; - -/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */ -"Privacy Policy" = "Política de Privacidad"; - -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */ -"Release Notes" = "Notas de la versión"; - -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */ -"Settings" = "Configuración"; - -/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */ -"Exit" = "Salir"; - -/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */ -"Documentation" = "Documentación"; - -/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */ -"Logging in..." = "Identificándose..."; - -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */ -"Authentication successful" = "Autenticación correcta"; - -/* 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!" = "¡No estás atracado en una estación!"; - -/* 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 estación no tiene nada!"; - -/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */ -"Station doesn't have a market!" = "¡La estación no tiene mercado!"; - -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */ -"Fetching data..." = "Recopilando datos..."; - -/* 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én eres?"; - -/* 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?!" = "¿Dónde estás?"; - -/* 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?!" = "¿Qué estás volando?"; - -/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Error de servidor CAPI de Frontier"; - -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */ -"Last updated at %H:%M:%S" = "Última actualización: %H:%M:%S"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */ -"Fighter" = "Caza"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */ -"Gunner" = "Artillero"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */ -"Helm" = "Timón"; - -/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */ -"cooldown {SS}s" = "Espere {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" = "Aceptar"; - -/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1693; */ -"Shutting down..." = "Apagando..."; - -/* 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 más de tus plugins habilitados aún no tienen soporte para Python 3.x. Por favor, consulta la lista en la pestaña '{PLUGINS}' de '{FILE}' > '{SETTINGS}'. Deberías comprobar si hay una versión actualizada disponible, si no, avisa al desarrollador de que necesita actualizar el código para Python 3.x.\n\nPuedes deshabilitar un plugin cambiando el nombre de su carpeta para que tenga '{DISABLED}' al final del nombre."; - -/* 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 Sin Soporte para 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" = "Error: El CAPI de Frontier no respondió"; -/* 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" = "Error: El servidor de Frontier está retrasado"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "Atracado pero estación desconocida: ¿Asentamiento EDO?"; -/* 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" = "Error: Credenciales Inválidas"; -/* 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" = "Error: Cmdt Incorrecto"; -/* 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" = "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" = "Error: No se pudo comprobar el 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!" = "Error: ¡customer_id no coincide!"; -/* 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" = "Error: no se pudo conseguir el 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" = "Fallo de consulta del CAPI de Frontier"; -/* 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" = "Actualizar"; + +/* 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" = "Siempre visible"; + +/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */ +"Unknown" = "Desconocido"; + +/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "Error: Comprueba la localización del fichero journal de E:D"; + +/* 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" = "Cmdt"; + +/* 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" = "Nave"; + +/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */ +"Suit" = "Traje"; + +/* 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" = "Estación"; + +/* 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" = "Archivo"; + +/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */ +"Edit" = "Editar"; + +/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */ +"View" = "Visualización"; + +/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */ +"Window" = "Ventana"; + +/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */ +"Help" = "Ayuda"; + +/* 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}" = "Acerca de {APP}"; + +/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */ +"Check for Updates..." = "Buscar Actualizaciones..."; + +/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */ +"Save Raw Data..." = "Guardar Datos Sin Procesar..."; + +/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */ +"Status" = "Estado"; + +/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */ +"Documentation" = "Documentación"; + +/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */ +"Privacy Policy" = "Política de Privacidad"; + +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */ +"Release Notes" = "Notas de la versión"; + +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */ +"Settings" = "Configuración"; + +/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */ +"Exit" = "Salir"; + +/* 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" = "Copiar"; + +/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */ +"Logging in..." = "Identificándose..."; + +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */ +"Authentication successful" = "Autenticación correcta"; + +/* 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!" = "¡No estás atracado en una estación!"; + +/* 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 estación no tiene nada!"; + +/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */ +"Station doesn't have a market!" = "¡La estación no tiene mercado!"; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ +"Fetching data..." = "Recopilando datos..."; + +/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */ +"CAPI: No commander data returned" = "CAPI: No se devolvió datos de comandante"; + +/* 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én eres?"; + +/* 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?!" = "¿Dónde estás?"; + +/* 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?!" = "¿Qué estás volando?"; + +/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Error de servidor CAPI de Frontier"; + +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */ +"Last updated at %H:%M:%S" = "Última actualización: %H:%M:%S"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */ +"Fighter" = "Caza"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */ +"Gunner" = "Artillero"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */ +"Helm" = "Timón"; + +/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */ +"cooldown {SS}s" = "Espere {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" = "Aceptar"; + +/* EDMarketConnector.py: The application is shutting down; In files: EDMarketConnector.py:1936; */ +"Shutting down..." = "Apagando..."; + +/* 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 más de tus plugins habilitados aún no tienen soporte para Python 3.x. Por favor, consulta la lista en la pestaña '{PLUGINS}' de '{FILE}' > '{SETTINGS}'. Deberías comprobar si hay una versión actualizada disponible, si no, avisa al desarrollador de que necesita actualizar el código para Python 3.x.\n\nPuedes deshabilitar un plugin cambiando el nombre de su carpeta para que tenga '{DISABLED}' al final del nombre."; + +/* 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 Sin Soporte para 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" = "El Directorio Journal ya está bloqueado"; + +/* 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 localización Directorio Journal ya está bloqueada.{CR}Puedes intentar resolverlo y pulsar Reintentar, o elegir Ignorar esto."; + +/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */ +"Retry" = "Reintentar"; + +/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */ +"Ignore" = "Ignorar"; + +/* 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" = "Por defecto"; -/* 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='" = "Configura la URL para usar con equipamiento de naves en coriolis.io. Nota, debe acabar en '/import?data='"; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "URL Normal"; + +/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */ +"Reset" = "Reiniciar"; + +/* 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" = "Sobrescribir Selección Beta/Normal"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "¡Modo sobrescritura de Coriolis Inválido!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "Procesamiento de Journal para EDDB desactivado. Ver 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" = "Error: No se puede conectar a EDDN"; + +/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "Error EDDN: EDMC es demasiado antiguo para EDDN. Actualiza por favor."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Error EDDN: Validación Fallida (¿EDMC Demasiado Antiguo?). Revisa el Log"; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "Error EDDN: Devolvió código de estado {STATUS}"; + +/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */ +"Send station data to the Elite Dangerous Data Network" = "Enviar datos de la estación 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" = "Enviar datos de sistema y escáner a 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" = "Retrasar envío hasta el atraque"; + +/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "Manejo de Journal para EDDN desactivado. Ver Log."; + +/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */ +"Sending data to EDDN..." = "Enviando datos 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" = "Enviar Registro de Vuelo y estado del CMDT 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" = "Credenciales de Elite Dangerous Star Map"; + +/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */ +"Commander Name" = "Nombre de Comandante"; + +/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */ +"API Key" = "Llave 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" = "Ninguna"; + +/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "Manejo de Journal para EDSM desactivado. Ver Log."; + +/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */ +"Error: EDSM {MSG}" = "Error: 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" = "Error: No se puede conectar a EDSM"; + +/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */ +"Send flight log and Cmdr status to Inara" = "Enviar Registro de Vuelo y estado del CMDT a Inara"; + +/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */ +"Inara credentials" = "Credenciales de Inara"; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "Inara desactivado. Ver 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}" = "Error: Inara {MSG}"; + +/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */ "Preferences" = "Preferencias"; -/* 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" = "Seleccione qué datos quiere guardar"; -/* 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" = "Datos de mercado en 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" = "Datos de mercado en 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" = "Equipamiento de la 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" = "Actualizar automáticamente al atracar"; -/* 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" = "Localización de archivos"; -/* 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..." = "Cambiar..."; -/* 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..." = "Examinar..."; -/* 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" = "Salida"; -/* 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" = "Localización del archivo de Journal de 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" = "Tecla de acceso directo"; -/* 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" = "Tecla de acceso directo"; -/* 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" = "Reinicie {APP} para usar los accesos directos de teclado"; -/* 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} necesita permisos para usar teclas de acceso directo"; -/* 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" = "Abrir Preferencias del 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 cuando Elite: Dangerous es la aplicación activa"; -/* 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" = "Reproducir sonido"; -/* 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" = "Desactivar Comprobación Automática de Actualizaciones de la Aplicación mientras juega"; -/* 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" = "Sitios Web preferidos"; -/* 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" = "Astillero"; -/* 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" = "Usar método 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" = "Nivel de registro"; -/* 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" = "Configuración"; -/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */ +/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */ "Privacy" = "Privacidad"; -/* 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" = "Texto 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" = "Texto resaltado"; -/* 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" = "Idioma"; -/* 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" = "Oscuro"; -/* 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" = "Transparente"; -/* 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" = "Porcentaje escala 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 Por Defecto{CR}Se requiere reiniciar{CR}para que los cambios surtan efecto!"; -/* 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" = "Transparencia de la ventana principal"; -/* 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 significa completamente opaco.{CR}La ventana se actualiza en tiempo real."; -/* 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" = "Minimizar a la bandeja de 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" = "Apariencia"; -/* 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" = "Carpeta de 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" = "Abrir"; -/* 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" = "Puedes desactivar un plugin añadiendo{CR}'{EXT}' al nombre de su carpeta"; -/* 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 Activados"; -/* 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:" = "Plugins sin soporte para 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" = "Información sobre migración de 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 Desactivados"; -/* 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" = "Préstamo"; -/* 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" = "Combate"; -/* stats.py: Ranking; In files: stats.py:77; */ +/* stats.py: Ranking; In files: stats.py:75; */ "Trade" = "Comercio"; -/* stats.py: Ranking; In files: stats.py:78; */ +/* stats.py: Ranking; In files: stats.py:76; */ "Explorer" = "Exploración"; -/* 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" = "Federación"; -/* stats.py: Ranking; In files: stats.py:83; */ +/* stats.py: Ranking; In files: stats.py:81; */ "Empire" = "Imperio"; -/* 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" = "Inofensivo"; -/* stats.py: Combat rank; In files: stats.py:94; */ +/* stats.py: Combat rank; In files: stats.py:92; */ "Mostly Harmless" = "Casi inofensivo"; -/* stats.py: Combat rank; In files: stats.py:95; */ +/* stats.py: Combat rank; In files: stats.py:93; */ "Novice" = "Novato"; -/* stats.py: Combat rank; In files: stats.py:96; */ +/* stats.py: Combat rank; In files: stats.py:94; */ "Competent" = "Competente"; -/* stats.py: Combat rank; In files: stats.py:97; */ +/* stats.py: Combat rank; In files: stats.py:95; */ "Expert" = "Experto"; -/* 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" = "Maestro"; -/* stats.py: Combat rank; In files: stats.py:99; */ +/* stats.py: Combat rank; In files: stats.py:97; */ "Dangerous" = "Peligroso"; -/* stats.py: Combat rank; In files: stats.py:100; */ +/* stats.py: Combat rank; In files: stats.py:98; */ "Deadly" = "Letal"; -/* stats.py: Trade rank; In files: stats.py:103; */ +/* stats.py: Trade rank; In files: stats.py:101; */ "Penniless" = "Pobre"; -/* stats.py: Trade rank; In files: stats.py:104; */ +/* stats.py: Trade rank; In files: stats.py:102; */ "Mostly Penniless" = "Casi pobre"; -/* stats.py: Trade rank; In files: stats.py:105; */ +/* stats.py: Trade rank; In files: stats.py:103; */ "Peddler" = "Buhonero"; -/* stats.py: Trade rank; In files: stats.py:106; */ +/* stats.py: Trade rank; In files: stats.py:104; */ "Dealer" = "Distribuidor"; -/* stats.py: Trade rank; In files: stats.py:107; */ +/* stats.py: Trade rank; In files: stats.py:105; */ "Merchant" = "Mercader"; -/* 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" = "Empresario"; -/* stats.py: Trade rank; In files: stats.py:110; */ +/* stats.py: Trade rank; In files: stats.py:108; */ "Tycoon" = "Magnate"; -/* stats.py: Explorer rank; In files: stats.py:113; */ +/* stats.py: Explorer rank; In files: stats.py:111; */ "Aimless" = "Perdido"; -/* stats.py: Explorer rank; In files: stats.py:114; */ +/* stats.py: Explorer rank; In files: stats.py:112; */ "Mostly Aimless" = "Casi perdido"; -/* stats.py: Explorer rank; In files: stats.py:115; */ +/* stats.py: Explorer rank; In files: stats.py:113; */ "Scout" = "Explorador"; -/* stats.py: Explorer rank; In files: stats.py:116; */ +/* stats.py: Explorer rank; In files: stats.py:114; */ "Surveyor" = "Topógrafo"; -/* stats.py: Explorer rank; In files: stats.py:117; */ +/* stats.py: Explorer rank; In files: stats.py:115; */ "Trailblazer" = "Rastreador"; -/* stats.py: Explorer rank; In files: stats.py:118; */ +/* stats.py: Explorer rank; In files: stats.py:116; */ "Pathfinder" = "Guía"; -/* stats.py: Explorer rank; In files: stats.py:119; */ +/* stats.py: Explorer rank; In files: stats.py:117; */ "Ranger" = "Descubridor"; -/* stats.py: Explorer rank; In files: stats.py:120; */ +/* stats.py: Explorer rank; In files: stats.py:118; */ "Pioneer" = "Pionero"; -/* stats.py: CQC rank; In files: stats.py:144; */ +/* stats.py: CQC rank; In files: stats.py:142; */ "Helpless" = "Indefenso"; -/* stats.py: CQC rank; In files: stats.py:145; */ +/* stats.py: CQC rank; In files: stats.py:143; */ "Mostly Helpless" = "Casi indefenso"; -/* stats.py: CQC rank; In files: stats.py:146; */ +/* stats.py: CQC rank; In files: stats.py:144; */ "Amateur" = "Aficionado"; -/* stats.py: CQC rank; In files: stats.py:147; */ +/* stats.py: CQC rank; In files: stats.py:145; */ "Semi Professional" = "Semiprofessional"; -/* stats.py: CQC rank; In files: stats.py:148; */ +/* stats.py: CQC rank; In files: stats.py:146; */ "Professional" = "Profesional"; -/* stats.py: CQC rank; In files: stats.py:149; */ +/* stats.py: CQC rank; In files: stats.py:147; */ "Champion" = "Campeón"; -/* stats.py: CQC rank; In files: stats.py:150; */ +/* stats.py: CQC rank; In files: stats.py:148; */ "Hero" = "Héroe"; -/* stats.py: CQC rank; In files: stats.py:151; */ +/* stats.py: CQC rank; In files: stats.py:149; */ "Gladiator" = "Gladiador"; -/* stats.py: Federation rank; In files: stats.py:157; */ +/* stats.py: Federation rank; In files: stats.py:155; */ "Recruit" = "Recluta"; -/* stats.py: Federation rank; In files: stats.py:158; */ +/* stats.py: Federation rank; In files: stats.py:156; */ "Cadet" = "Cadete"; -/* stats.py: Federation rank; In files: stats.py:159; */ +/* stats.py: Federation rank; In files: stats.py:157; */ "Midshipman" = "Guardiamarina"; -/* stats.py: Federation rank; In files: stats.py:160; */ +/* stats.py: Federation rank; In files: stats.py:158; */ "Petty Officer" = "Sargento"; -/* stats.py: Federation rank; In files: stats.py:161; */ +/* stats.py: Federation rank; In files: stats.py:159; */ "Chief Petty Officer" = "Sargento primero"; -/* stats.py: Federation rank; In files: stats.py:162; */ +/* stats.py: Federation rank; In files: stats.py:160; */ "Warrant Officer" = "Subteniente"; -/* stats.py: Federation rank; In files: stats.py:163; */ +/* stats.py: Federation rank; In files: stats.py:161; */ "Ensign" = "Alférez de fragata"; -/* stats.py: Federation rank; In files: stats.py:164; */ +/* stats.py: Federation rank; In files: stats.py:162; */ "Lieutenant" = "Teniente de navío"; -/* stats.py: Federation rank; In files: stats.py:165; */ +/* stats.py: Federation rank; In files: stats.py:163; */ "Lieutenant Commander" = "Capitán de corbeta"; -/* stats.py: Federation rank; In files: stats.py:166; */ +/* stats.py: Federation rank; In files: stats.py:164; */ "Post Commander" = "Capitán de fragata"; -/* stats.py: Federation rank; In files: stats.py:167; */ +/* stats.py: Federation rank; In files: stats.py:165; */ "Post Captain" = "Capitán de navío"; -/* stats.py: Federation rank; In files: stats.py:168; */ +/* stats.py: Federation rank; In files: stats.py:166; */ "Rear Admiral" = "Contraalmirante"; -/* stats.py: Federation rank; In files: stats.py:169; */ +/* stats.py: Federation rank; In files: stats.py:167; */ "Vice Admiral" = "Vicealmirante"; -/* stats.py: Federation rank; In files: stats.py:170; */ +/* stats.py: Federation rank; In files: stats.py:168; */ "Admiral" = "Almirante"; -/* stats.py: Empire rank; In files: stats.py:176; */ +/* stats.py: Empire rank; In files: stats.py:174; */ "Outsider" = "Forastero"; -/* stats.py: Empire rank; In files: stats.py:177; */ +/* stats.py: Empire rank; In files: stats.py:175; */ "Serf" = "Siervo"; -/* stats.py: Empire rank; In files: stats.py:179; */ +/* stats.py: Empire rank; In files: stats.py:177; */ "Squire" = "Escudero"; -/* stats.py: Empire rank; In files: stats.py:180; */ +/* stats.py: Empire rank; In files: stats.py:178; */ "Knight" = "Caballero"; -/* stats.py: Empire rank; In files: stats.py:181; */ +/* stats.py: Empire rank; In files: stats.py:179; */ "Lord" = "Señor"; -/* stats.py: Empire rank; In files: stats.py:182; */ +/* stats.py: Empire rank; In files: stats.py:180; */ "Baron" = "Barón"; -/* stats.py: Empire rank; In files: stats.py:183; */ +/* stats.py: Empire rank; In files: stats.py:181; */ "Viscount" = "Vizconde"; -/* stats.py: Empire rank; In files: stats.py:184; */ +/* stats.py: Empire rank; In files: stats.py:182; */ "Count" = "Conde"; -/* stats.py: Empire rank; In files: stats.py:185; */ +/* stats.py: Empire rank; In files: stats.py:183; */ "Earl" = "Conde Palatino"; -/* stats.py: Empire rank; In files: stats.py:186; */ +/* stats.py: Empire rank; In files: stats.py:184; */ "Marquis" = "Marqués"; -/* stats.py: Empire rank; In files: stats.py:187; */ +/* stats.py: Empire rank; In files: stats.py:185; */ "Duke" = "Duque"; -/* stats.py: Empire rank; In files: stats.py:188; */ +/* stats.py: Empire rank; In files: stats.py:186; */ "Prince" = "Príncipe"; -/* stats.py: Empire rank; In files: stats.py:189; */ +/* stats.py: Empire rank; In files: stats.py:187; */ "King" = "Rey"; -/* stats.py: Power rank; In files: stats.py:195; */ +/* stats.py: Power rank; In files: stats.py:193; */ "Rating 1" = "Nivel 1"; -/* stats.py: Power rank; In files: stats.py:196; */ +/* stats.py: Power rank; In files: stats.py:194; */ "Rating 2" = "Nivel 2"; -/* stats.py: Power rank; In files: stats.py:197; */ +/* stats.py: Power rank; In files: stats.py:195; */ "Rating 3" = "Nivel 3"; -/* stats.py: Power rank; In files: stats.py:198; */ +/* stats.py: Power rank; In files: stats.py:196; */ "Rating 4" = "Nivel 4"; -/* stats.py: Power rank; In files: stats.py:199; */ +/* stats.py: Power rank; In files: stats.py:197; */ "Rating 5" = "Nivel 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" = "Valor"; -/* stats.py: Status dialog title; In files: stats.py:422; */ +/* stats.py: Status dialog title; In files: stats.py:418; */ "Ships" = "Naves"; diff --git a/L10n/fi.strings b/L10n/fi.strings index 12476e48..c2577e42 100644 --- a/L10n/fi.strings +++ b/L10n/fi.strings @@ -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"; diff --git a/L10n/fr.strings b/L10n/fr.strings index 5d7dad8a..d1ca4b60 100644 --- a/L10n/fr.strings +++ b/L10n/fr.strings @@ -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"; diff --git a/L10n/hu.strings b/L10n/hu.strings index 34f8d27b..b6d622d1 100644 --- a/L10n/hu.strings +++ b/L10n/hu.strings @@ -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"; diff --git a/L10n/it.strings b/L10n/it.strings index b5fa329c..515b65b7 100644 --- a/L10n/it.strings +++ b/L10n/it.strings @@ -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"; diff --git a/L10n/ja.strings b/L10n/ja.strings index 531e9c6d..0695827e 100644 --- a/L10n/ja.strings +++ b/L10n/ja.strings @@ -1,749 +1,773 @@ -/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; In files: inara.py:383; inara.py:386; */ -"Inara only accepts Live galaxy data" = "Inaraは現行の銀河データのみ受け付けます"; - /* 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" = "フライトログと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" = "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" = "フライトログと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" = "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}"; - -/* 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" = "自動"; - -/* 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" = "通常版"; - -/* 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" = "ベータ版"; - -/* 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='" = "coriolis.ioの船のロードアウトとして使用するURLを設定してください。URLの最後は「/import?data=」で終わる必要があります"; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "通常版URL"; - -/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */ -"Reset" = "リセット"; - -/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */ -"Beta URL" = "ベータ版URL"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "ベータ版/通常版の選択を上書きする"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "無効な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." = "EDDBジャーナル処理が無効です。ログを確認してください。"; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "EDDNジャーナルハンドラーが無効です。ログを確認してください。"; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "EDSMハンドラーが無効です。ログを確認してください。"; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inaraが無効です。ログを確認してください。"; - -/* 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: コマンダーのデータが返ってきませんでした"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "ベータ版/通常版の選択を上書きする"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDNエラー: EDDNで使用するにはEDMCのバージョンが古すぎます。更新してください。"; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDNエラー: 検証に失敗しました(EDMCが古すぎる?)。ログを確認してください。"; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "EDDNエラー: ステータスコード {STATUS} が返されました"; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "NavRoute.jsonにRoute配列が存在しません"; - -/* 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: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "エラー: E:Dジャーナルファイルの場所を確認してください"; - -/* 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: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "CAPIクエリ中止: CMDR名が不明"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "CAPIクエリ中止: ゲームモードが不明"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "CAPIクエリ中止: 現システムが不明"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "CAPIクエリ中止: 他の船でマルチクルー中"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "CAPIクエリ中止: CQC(Arena)が検出"; - -/* 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: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Frontier CAPIサーバエラー"; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI: アクセストークンを更新中..."; - -/* 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" = "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" = "次回更新まであと {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." = "有効にしている1つ以上のプラグインがPython 3.xをサポートしていません。'{FILE}' > '{SETTINGS}'\nメニューで表示される設定ダイアログの'{PLUGINS}' タブの一覧を確認してください。更新済みのバージョンがあるかを確認し、なければ開発者に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 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" = "エラー: Frontier CAPIからの応答がありません"; -/* 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" = "エラー: Frontier社のサーバが混雑しています"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "不明なステーションに着艦: EDOの基地?"; -/* 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" = "エラー: 不適切な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!" = "エラー: 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" = "エラー: トークンが取得できません"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "Frontier CAPIがメンテナンスのため停止中"; -/* 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クエリ失敗"; -/* 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: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "エラー: E:Dジャーナルファイルの場所を確認してください"; + +/* 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 > Troubleshooting; In files: EDMarketConnector.py:934; EDMarketConnector.py:954; */ +"Troubleshooting" = "トラブルシューティング"; + +/* EDMarketConnector.py: Help > Report A Bug; In files: EDMarketConnector.py:935; EDMarketConnector.py:955; */ +"Report A Bug" = "バグを報告する"; + +/* 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: CAPI auth aborted because of killswitch; EDMarketConnector.py: CAPI auth query aborted because of killswitch; In files: EDMarketConnector.py:973; EDMarketConnector.py:1067; */ +"CAPI auth disabled by killswitch" = "CAPI認証はkillswitchによって無効にされています"; + +/* 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: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "CAPIクエリ中止: CMDR名が不明"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "CAPIクエリ中止: ゲームモードが不明"; + +/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because GameVersion unknown; In files: EDMarketConnector.py:1089; EDMarketConnector.py:1170; */ +"CAPI query aborted: GameVersion unknown" = "CAPIクエリ中断: GameVersionが不明"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "CAPIクエリ中止: 現システムが不明"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "CAPIクエリ中止: 他の船でマルチクルー中"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "CAPIクエリ中止: CQC(Arena)が検出"; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ +"Fetching data..." = "データを取得中..."; + +/* EDMarketConnector.py: CAPI fleetcarrier query aborted because of killswitch; In files: EDMarketConnector.py:1157; */ +"CAPI fleetcarrier disabled by killswitch" = "CAPIフリートキャリアはkillswitchによって無効にされています"; + +/* EDMarketConnector.py: No data was returned for the fleetcarrier from the Frontier CAPI; In files: EDMarketConnector.py:1219; */ +"CAPI: No fleetcarrier data returned" = "CAPI: フリートキャリアデータの返信なし"; + +/* EDMarketConnector.py: We didn't have the fleetcarrier callsign when we should have; In files: EDMarketConnector.py:1223; */ +"CAPI: Fleetcarrier data incomplete" = "CAPI: フリートキャリアデータが不完全"; + +/* 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: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Frontier CAPIサーバエラー"; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ +"CAPI: Refreshing access token..." = "CAPI: アクセストークンを更新中..."; + +/* 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" = "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" = "次回更新まであと {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." = "有効にしている1つ以上のプラグインがPython 3.xをサポートしていません。'{FILE}' > '{SETTINGS}'\nメニューで表示される設定ダイアログの'{PLUGINS}' タブの一覧を確認してください。更新済みのバージョンがあるかを確認し、なければ開発者に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; */ +/* 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" = "自動"; + +/* 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" = "通常版"; + +/* 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" = "ベータ版"; + +/* 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='" = "coriolis.ioの船のロードアウトとして使用するURLを設定してください。URLの最後は「/import?data=」で終わる必要があります"; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "通常版URL"; + +/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */ +"Reset" = "リセット"; + +/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: coriolis.py:106; */ +"Beta URL" = "ベータ版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" = "ベータ版/通常版の選択を上書きする"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "無効なCoriolis上書きモードです!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "EDDBジャーナル処理が無効です。ログを確認してください。"; + +/* 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: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDNエラー: EDDNで使用するにはEDMCのバージョンが古すぎます。更新してください。"; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDNエラー: 検証に失敗しました(EDMCが古すぎる?)。ログを確認してください。"; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "EDDNエラー: ステータスコード {STATUS} が返されました"; + +/* 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: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "EDDNジャーナルハンドラーが無効です。ログを確認してください。"; + +/* 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" = "フライトログと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" = "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 - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "EDSMハンドラーが無効です。ログを確認してください。"; + +/* edsm.py: EDSM - Only Live data; In files: edsm.py:632; */ +"EDSM only accepts Live galaxy data" = "EDSMはLiveモードの銀河データしか受け付けません"; + +/* 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" = "フライトログとCMDRステータスを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: The Inara API only accepts Live galaxy data, not Legacy galaxy data; inara.py: Inara - Only Live data; In files: inara.py:384; inara.py:386; */ +"Inara only accepts Live galaxy data" = "InaraはLiveモードの銀河データのみ受け付けます"; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "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: Settings > Configuration - Label for CAPI section; In files: prefs.py:469; */ +"CAPI Settings" = "CAPI設定"; + +/* prefs.py: Configuration - Enable or disable the Fleet Carrier CAPI calls; In files: prefs.py:475; */ +"Enable Fleetcarrier CAPI Queries" = "フリートキャリアCAPIクエリを有効にする"; + +/* 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: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "メインUIプライバシーオプション"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "UIでプライベートグループ名を表示しない"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "マルチクルー船長名を表示しない"; -/* 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" = "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はデフォルトを意味します{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" = "Elite"; -/* stats.py: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Elite I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Elite II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Elite III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Elite IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Elite V"; -/* 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:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "Mercenary"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "Exobiologist"; -/* 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" = "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: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "Mostly Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Rookie"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Soldier"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Gunslinger"; -/* stats.py: Mercenary rank; In files: stats.py:129; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ "Warrior" = "Warrior"; -/* stats.py: Mercenary rank; In files: stats.py:131; */ +/* stats.py: Mercenary rank; In files: stats.py:129; */ "Deadeye" = "Deadeye"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:135; */ +/* stats.py: Exobiologist rank; In files: stats.py:133; */ "Mostly Directionless" = "Mostly Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:136; */ +/* stats.py: Exobiologist rank; In files: stats.py:134; */ "Compiler" = "Compiler"; -/* stats.py: Exobiologist rank; In files: stats.py:137; */ +/* stats.py: Exobiologist rank; In files: stats.py:135; */ "Collector" = "Collector"; -/* stats.py: Exobiologist rank; In files: stats.py:138; */ +/* stats.py: Exobiologist rank; In files: stats.py:136; */ "Cataloguer" = "Cataloguer"; -/* stats.py: Exobiologist rank; In files: stats.py:139; */ +/* stats.py: Exobiologist rank; In files: stats.py:137; */ "Taxonomist" = "Taxonomist"; -/* stats.py: Exobiologist rank; In files: stats.py:140; */ +/* stats.py: Exobiologist rank; In files: stats.py:138; */ "Ecologist" = "Ecologist"; -/* stats.py: Exobiologist rank; In files: stats.py:141; */ +/* stats.py: Exobiologist rank; In files: stats.py:139; */ "Geneticist" = "Geneticist"; -/* 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: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "状態: あなたのコマンダー名が不明です"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "状態: CAPIデータがありません"; -/* 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" = "所有船"; diff --git a/L10n/ko.strings b/L10n/ko.strings index b7d9032e..d1a19577 100644 --- a/L10n/ko.strings +++ b/L10n/ko.strings @@ -1,671 +1,671 @@ /* Language name */ "!Language" = "한국어(Korean)"; -/* 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에 flight 로그와 커맨더 상태 정보 전송하기"; - -/* 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에 flight 로그와 커맨더 상태 정보 전송하기"; - -/* 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}"; - -/* 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" = "자동"; - -/* 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" = "일반"; - -/* 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" = "베타"; - -/* 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='" = "함선 피팅을 내보낼 coriolis.io 사이트 URL을 설정하세요. 주소는 반드시 '/import?data='으로 끝나야 합니다"; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "일반 URL"; - -/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */ -"Reset" = "초기화"; - -/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */ -"Beta URL" = "베타 URL"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "잘못된 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." = "EDDB 저널 처리 비활성화됨. 로그 참고 바람."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "EDDN 저널 처리 비활성화됨. 로그 참고 바람."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "EDSM Handler 비활성화됨. 로그 참고 바람."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara 비활성화됨. 로그 참고 바람."; - -/* 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: 커맨더 정보가 반환되지 않음"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "베타/일반 설정 오버라이딩"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN 오류: EDDN에 접속하기에 EDMC의 버전이 너무 오래되었습니다. 업데이트하시기 바랍니다."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN 오류: 인증 실패 (EDMC가 너무 오래되었을 수 있음). 로그 참고"; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "EDDN 오류: 상태 코드 {STATUS}가 반환됨"; - -/* 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." = "새 저널 디렉토리(Journal Directory)가 이미 잠겨있습니다.{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: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "오류: E:D 저널 파일의 위치를 확인하십시오"; - -/* 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" = "함선"; - -/* 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..." = "Raw 데이터 저장하기..."; - -/* 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: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "CAPI 쿼리 중단: 커맨더 이름 알 수 없음"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "CAPI 쿼리 중단: 게임 모드 알 수 없음"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "CAPI 쿼리 중단: 현재 성계 알 수 없음"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "CAPI 쿼리 중단: 다른 함선의 멀티크루로 참여중"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "CAPI 쿼리 중단: CQC(아레나) 감지됨"; - -/* 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: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Frontier CAPI 서버 오류"; - -/* 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" = "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" = "쿨다운 {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..." = "종료하는 중..."; - -/* 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." = "활성화된 플러그인 중 1개 이상이 Python 3.x를 지원하지 않습니다. '{FILE}' > '{SETTINGS}' 에서 '{PLUGINS}' 탭에 들어가 활성화되어있는 플러그인 목록을 확인하십시오. 플러그인들 중 새 버전이 나온 것이 있는지도 확인해보시고, 만약 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 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" = "오류: Frontier CAPI가 응답이 없음"; -/* 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" = "오류: Frontier 서버 응답이 지연되고 있음"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "알 수 없는 정거장에 도킹함: Odyssey 지상 기지입니까?"; -/* 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!" = "오류: 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" = "오류: 토큰을 받지 못함"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "Frontier CAPI 점검으로 접속 불가"; -/* 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 쿼리 실패"; -/* 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: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "오류: E:D 저널 파일의 위치를 확인하십시오"; + +/* 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" = "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..." = "Raw 데이터 저장하기..."; + +/* 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: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "CAPI 쿼리 중단: 커맨더 이름 알 수 없음"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "CAPI 쿼리 중단: 게임 모드 알 수 없음"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "CAPI 쿼리 중단: 현재 성계 알 수 없음"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "CAPI 쿼리 중단: 다른 함선의 멀티크루로 참여중"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "CAPI 쿼리 중단: CQC(아레나) 감지됨"; + +/* 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: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Frontier CAPI 서버 오류"; + +/* 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" = "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" = "쿨다운 {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..." = "종료하는 중..."; + +/* 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." = "활성화된 플러그인 중 1개 이상이 Python 3.x를 지원하지 않습니다. '{FILE}' > '{SETTINGS}' 에서 '{PLUGINS}' 탭에 들어가 활성화되어있는 플러그인 목록을 확인하십시오. 플러그인들 중 새 버전이 나온 것이 있는지도 확인해보시고, 만약 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." = "새 저널 디렉토리(Journal Directory)가 이미 잠겨있습니다.{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; */ +/* 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" = "자동"; + +/* 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" = "일반"; + +/* 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" = "베타"; + +/* 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='" = "함선 피팅을 내보낼 coriolis.io 사이트 URL을 설정하세요. 주소는 반드시 '/import?data='으로 끝나야 합니다"; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "일반 URL"; + +/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */ +"Reset" = "초기화"; + +/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: coriolis.py:106; */ +"Beta URL" = "베타 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" = "베타/일반 설정 오버라이딩"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "잘못된 Coriolis 오버라이딩 모드입니다!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "EDDB 저널 처리 비활성화됨. 로그 참고 바람."; + +/* 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: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN 오류: EDDN에 접속하기에 EDMC의 버전이 너무 오래되었습니다. 업데이트하시기 바랍니다."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN 오류: 인증 실패 (EDMC가 너무 오래되었을 수 있음). 로그 참고"; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "EDDN 오류: 상태 코드 {STATUS}가 반환됨"; + +/* 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: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "EDDN 저널 처리 비활성화됨. 로그 참고 바람."; + +/* 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에 flight 로그와 커맨더 상태 정보 전송하기"; + +/* 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 - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "EDSM Handler 비활성화됨. 로그 참고 바람."; + +/* 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에 flight 로그와 커맨더 상태 정보 전송하기"; + +/* 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 support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "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 저널(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" = "단축키 설정"; -/* 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: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "메인 UI 개인정보 설정"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "UI에서 프라이빗 그룹 이름 숨기가"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "멀티크루 함장 이름 숨기기"; -/* 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" = "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은 '기본 설정'을 의미하며{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" = "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" = "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: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "상태: 아직 커맨더 이름이 확인되지 않음"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "상태: 아직 CAPI 정보 없음"; -/* 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" = "함선(들)"; diff --git a/L10n/lv.strings b/L10n/lv.strings index f553dfdd..313620ab 100644 --- a/L10n/lv.strings +++ b/L10n/lv.strings @@ -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"; diff --git a/L10n/nl.strings b/L10n/nl.strings index c25eddb6..79820570 100644 --- a/L10n/nl.strings +++ b/L10n/nl.strings @@ -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"; diff --git a/L10n/pl.strings b/L10n/pl.strings index 3c349603..9c201f7c 100644 --- a/L10n/pl.strings +++ b/L10n/pl.strings @@ -1,746 +1,740 @@ /* Language name */ "!Language" = "Polski"; -/* 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..." = "Wysłanie danych 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" = "Błąd: Brak połączenia z 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" = "Wyślij dane 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" = "Wyślij dane skanowań do 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" = "Czekaj z wysłaniem na zadokowanie"; - -/* 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" = "Wyślij zapis lotu i status pilota 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" = "Dane uwierzytelniające 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" = "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" = "Klucz 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" = "Brak"; - -/* 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}" = "Błąd: 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" = "Błąd: Brak połączenia z 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" = "Wyślij zapis lotu i status pilota do Inary"; - -/* 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 - uprawnienia"; - -/* 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}" = "Błąd: 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" = "Normalny"; - -/* 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='" = "Ustaw URL do wykorzystania z coriolis.io. Pamiętaj, że musi się on kończyć '/import?data='"; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "URL normalnej wersji"; - -/* 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" = "URL wersji Beta"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "Zastąp wybór Beta/Normalny"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "Niewłaściwy tryb nadpisania 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." = "Wyłączone przetwarzanie dziennika EDDB. Sprawdź logi."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "Wyłączona obsługa dziennika EDDB. Sprawdź logi."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "Wyłączona obsługa EDDB. Sprawdź logi."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara jest wyłączona. Sprawdź logi."; - -/* 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: Nie zwrócono danych dowódcy"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "Nadpisz wybór trybu Beta/normalnego"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "Błąd EDDN: Zbyt stara wersja EDMC. Zaktualizuj do nowszej wersji."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Błąd EDDN: Nieudana weryfikacja (stara wersja EDDN?). Sprawdź logi."; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "Błąd EDDN: Zwrócono kod {STATUS}"; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "Brak tablicy \"Route\" wewnątrz NavRoute.json"; - -/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */ -"Journal directory already locked" = "Katalog dziennika zablokowany"; - -/* 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." = "Nowa pozycja katalogu dziennika jest zablokowana. {CR}Możesz spróbować to rozwiązać na własną rękę lub zignorować."; - -/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */ -"Retry" = "Ponów"; - -/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */ -"Ignore" = "Zignoruj"; - -/* 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" = "Kopiuj"; - -/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */ -"Update" = "Aktualizacja"; - -/* 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" = "Zawsze na wierzchu"; - -/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */ -"Unknown" = "Nieznany"; - -/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "Błąd: Sprawdź lokalizację pliku dziennika E:D"; - -/* 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" = "Rola"; - -/* 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" = "Statek"; - -/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */ -"Suit" = "Kombinezon"; - -/* 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" = "Stacja"; - -/* 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" = "Plik"; - -/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */ -"Edit" = "Edycja"; - -/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */ -"View" = "Widok"; - -/* 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" = "Pomoc"; - -/* 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..." = "Sprawdź aktualizacje..."; - -/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */ -"Save Raw Data..." = "Zapisz Nieprzetworzone Dane..."; - -/* 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" = "Polityka prywatności"; - -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */ -"Release Notes" = "Informacje o wersji"; - -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */ -"Settings" = "Ustawienia"; - -/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */ -"Exit" = "Zakończ"; - -/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */ -"Documentation" = "Dokumentacja"; - -/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */ -"Logging in..." = "Logowanie..."; - -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */ -"Authentication successful" = "Autoryzacja pomyślna"; - -/* 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!" = "Nie jesteś zadokowany do stacji!"; - -/* 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!" = "Stacja jest pusta!"; - -/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */ -"Station doesn't have a market!" = "W stacji nie ma giełdy towarowej!"; - -/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "Zapytanie CAPI anulowane: nazwa komandora nieznana"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "Zapytanie CAPI anulowane: tryb gry nieznany"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "Zapytanie CAPI anulowane: obecny system nieznany"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "Zapytanie CAPI anulowane: jako załogant w innym statku"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "Zapytanie CAPI anulowane: wykryto arenę CQC"; - -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */ -"Fetching data..." = "Pobieranie danych..."; - -/* 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?!" = "Kim jesteś?!"; - -/* 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?!" = "Gdzie jesteś?!"; - -/* 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?!" = "Czym latasz?!"; - -/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Błąd serwera CAPI Frontier"; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI: Odświeżanie tokena dostępu..."; - -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */ -"Last updated at %H:%M:%S" = "Ostatnia aktualizacja %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" = "Oczekiwanie {SS} sek."; - -/* 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..." = "Wyłączanie..."; - -/* 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." = "Co najmniej jeden z uruchomionych pluginów nie wspiera Python 3.x. Sprawdź listę w '{FILE}' > '{SETTINGS}', sekcja '{PLUGINS}'. Upewnij się, że dostępna jest aktualna wersja pluginu, w przeciwnym razie poinformuj twórcę, że należy zaktualizować kod do wersji Python 3.x.\n\nMożesz wyłączyć plugin, dodając '{DISABLED}' na koniec nazwy jego folderu."; - -/* 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 Nie Wspierające 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" = "Błąd: Brak odpowiedzi od CAPI Frontier"; -/* 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" = "Błąd: Serwer Frontiera laguje"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "Zadokowany na nieznanej stacji: czyżby kolonia EDO?"; -/* 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" = "Błąd: Dane uwierzytelniające niepoprawne"; -/* 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" = "Błąd: Niepoprawny 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" = "Błąd"; -/* 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" = "Błąd: Nie można sprawdzić ID klienta z tokenu"; -/* 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!" = "Błąd: ID klienta nie pasuje!"; -/* 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" = "Błąd: Nie można pobrać tokenu"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "CAPI w trakcie prac serwisowych"; -/* 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" = "Błąd zapytania CAPI Frontier"; -/* 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" = "Aktualizacja"; + +/* 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" = "Zawsze na wierzchu"; + +/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */ +"Unknown" = "Nieznany"; + +/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "Błąd: Sprawdź lokalizację pliku dziennika E:D"; + +/* 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" = "Rola"; + +/* 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" = "Statek"; + +/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */ +"Suit" = "Kombinezon"; + +/* 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" = "Stacja"; + +/* 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" = "Plik"; + +/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */ +"Edit" = "Edycja"; + +/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */ +"View" = "Widok"; + +/* 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" = "Pomoc"; + +/* 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..." = "Sprawdź aktualizacje..."; + +/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */ +"Save Raw Data..." = "Zapisz Nieprzetworzone Dane..."; + +/* 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" = "Dokumentacja"; + +/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */ +"Privacy Policy" = "Polityka prywatności"; + +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */ +"Release Notes" = "Informacje o wersji"; + +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */ +"Settings" = "Ustawienia"; + +/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */ +"Exit" = "Zakończ"; + +/* 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" = "Kopiuj"; + +/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */ +"Logging in..." = "Logowanie..."; + +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */ +"Authentication successful" = "Autoryzacja pomyślna"; + +/* 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!" = "Nie jesteś zadokowany do stacji!"; + +/* 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!" = "Stacja jest pusta!"; + +/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */ +"Station doesn't have a market!" = "W stacji nie ma giełdy towarowej!"; + +/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "Zapytanie CAPI anulowane: nazwa komandora nieznana"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "Zapytanie CAPI anulowane: tryb gry nieznany"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "Zapytanie CAPI anulowane: obecny system nieznany"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "Zapytanie CAPI anulowane: jako załogant w innym statku"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "Zapytanie CAPI anulowane: wykryto arenę CQC"; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ +"Fetching data..." = "Pobieranie danych..."; + +/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */ +"CAPI: No commander data returned" = "CAPI: Nie zwrócono danych dowódcy"; + +/* 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?!" = "Kim jesteś?!"; + +/* 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?!" = "Gdzie jesteś?!"; + +/* 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?!" = "Czym latasz?!"; + +/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Błąd serwera CAPI Frontier"; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ +"CAPI: Refreshing access token..." = "CAPI: Odświeżanie tokena dostępu..."; + +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */ +"Last updated at %H:%M:%S" = "Ostatnia aktualizacja %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" = "Oczekiwanie {SS} sek."; + +/* 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..." = "Wyłączanie..."; + +/* 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." = "Co najmniej jeden z uruchomionych pluginów nie wspiera Python 3.x. Sprawdź listę w '{FILE}' > '{SETTINGS}', sekcja '{PLUGINS}'. Upewnij się, że dostępna jest aktualna wersja pluginu, w przeciwnym razie poinformuj twórcę, że należy zaktualizować kod do wersji Python 3.x.\n\nMożesz wyłączyć plugin, dodając '{DISABLED}' na koniec nazwy jego folderu."; + +/* 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 Nie Wspierające 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" = "Katalog dziennika zablokowany"; + +/* 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." = "Nowa pozycja katalogu dziennika jest zablokowana. {CR}Możesz spróbować to rozwiązać na własną rękę lub zignorować."; + +/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */ +"Retry" = "Ponów"; + +/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */ +"Ignore" = "Zignoruj"; + +/* 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" = "Domyślne"; -/* 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" = "Normalny"; + +/* 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='" = "Ustaw URL do wykorzystania z coriolis.io. Pamiętaj, że musi się on kończyć '/import?data='"; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "URL normalnej wersji"; + +/* 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" = "URL wersji 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" = "Nadpisz wybór trybu Beta/normalnego"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "Niewłaściwy tryb nadpisania Coriolis!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "Wyłączone przetwarzanie dziennika EDDB. Sprawdź logi."; + +/* 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" = "Błąd: Brak połączenia z EDDN"; + +/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "Błąd EDDN: Zbyt stara wersja EDMC. Zaktualizuj do nowszej wersji."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Błąd EDDN: Nieudana weryfikacja (stara wersja EDDN?). Sprawdź logi."; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "Błąd EDDN: Zwrócono kod {STATUS}"; + +/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */ +"Send station data to the Elite Dangerous Data Network" = "Wyślij dane 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" = "Wyślij dane skanowań do 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" = "Czekaj z wysłaniem na zadokowanie"; + +/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "Wyłączona obsługa dziennika EDDB. Sprawdź logi."; + +/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */ +"Sending data to EDDN..." = "Wysłanie danych 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" = "Wyślij zapis lotu i status pilota 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" = "Dane uwierzytelniające Elite Dangerous Star Map"; + +/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */ +"Commander Name" = "Commander Name"; + +/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */ +"API Key" = "Klucz 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" = "Brak"; + +/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "Wyłączona obsługa EDDB. Sprawdź logi."; + +/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */ +"Error: EDSM {MSG}" = "Błąd: 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" = "Błąd: Brak połączenia z EDSM"; + +/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */ +"Send flight log and Cmdr status to Inara" = "Wyślij zapis lotu i status pilota do Inary"; + +/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */ +"Inara credentials" = "Inara - uprawnienia"; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "Inara jest wyłączona. Sprawdź logi."; + +/* 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}" = "Błąd: Inara {MSG}"; + +/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */ "Preferences" = "Preferencje"; -/* 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" = "Jakie dane zapisywać"; -/* 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" = "Dane rynkowe w formacie 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" = "Dane rynkowe w formacie Trade Dangerous"; -/* prefs.py: Settings > Output option; In files: prefs.py:373; */ +/* prefs.py: Settings > Output option; In files: prefs.py:360; */ "Ship loadout" = "Wyposażenie statku"; -/* prefs.py: Settings > Output option; In files: prefs.py:383; */ +/* prefs.py: Settings > Output option; In files: prefs.py:370; */ "Automatically update on docking" = "Aktualizuj automatycznie po zadokowaniu"; -/* 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" = "Położenie pliku"; -/* 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..." = "Zmień..."; -/* 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..." = "Przeglądaj..."; -/* 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" = "Wyjście"; -/* 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 Lokacja pliku dziennika"; -/* 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" = "Skrót klawiaturowy"; -/* 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" = "Skr. Klaw."; -/* 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" = "Zrestartuj {APP} by użyć{CR}skrótu klawiszowego."; -/* 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} wymaga uprawnień by{CR}móc korzystać ze skrótów klawiszowych."; -/* 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" = "Otwórz Preferencje systemowe"; -/* 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" = "Tylko gdy Elite: Dangerous jest aplikacją aktywną"; -/* 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" = "Odtwórz dźwięk"; -/* 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" = "Wyłącz automatyczne wyszukiwanie aktualizacji, gdy jesteś w grze"; -/* 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" = "Preferowane strony"; -/* 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" = "Stocznia"; -/* 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" = "Użyj alternatywnej metody 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" = "Poziom logowania"; -/* 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" = "Konfiguracja"; -/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "Opcje prywatności UI"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "Ukruj nazwę grupy prywatnej w UI"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "Ukryj nazwę kapitana w \"multi-crew\""; -/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */ +/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */ "Privacy" = "Prywatność"; -/* 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" = "Zwykły 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" = "Podświetlony 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" = "Język"; -/* 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" = "Schemat kolorystyczny"; -/* 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" = "Ciemny"; -/* 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" = "Przezroczyste"; -/* 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" = "Skalowanie 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 oznacza wartość domyślną{CR}Zmiany zostaną wprowadzone po{CR}ponownym uruchomieniu programu!"; -/* 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" = "Przeźroczystość okna głównego"; -/* 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 oznacza nieprzeźroczyste.{CR}Okno aktualizowane w czasie rzeczywistym."; -/* 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" = "Zminimalizuj do zasobnika systemowego"; -/* 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" = "Wygląd"; -/* 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" = "Folder pluginów"; -/* 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" = "Otwórz"; -/* 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" = "Wskazówka: Możesz wyłączyć pluginy{CR}dodając '{EXT}' do nazwy folderu"; -/* 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" = "Włączone 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 nie obsługiwane przez 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" = "Informacja o migracji pluginów"; -/* 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" = "Pluginy wyłączone"; -/* 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" = "Pożyczka"; -/* stats.py: Top rank; In files: stats.py:65; */ +/* stats.py: Top rank; In files: stats.py:63; */ "Elite" = "Elite"; -/* stats.py: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Elite I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Elite II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Elite III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Elite IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Elite V"; -/* 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:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "Najemnik"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "Egzobiolog"; -/* 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" = "Federacja"; -/* stats.py: Ranking; In files: stats.py:83; */ +/* stats.py: Ranking; In files: stats.py:81; */ "Empire" = "Imperium"; -/* 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: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Bezbronny"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "Głównie bezbronny"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Początkujący"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Żołnierz"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Rewolwerowiec"; -/* stats.py: Mercenary rank; In files: stats.py:129; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ "Warrior" = "Wojownik"; -/* stats.py: Mercenary rank; In files: stats.py:131; */ +/* stats.py: Mercenary rank; In files: stats.py:129; */ "Deadeye" = "Strzelec"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Zagubiony"; -/* stats.py: Exobiologist rank; In files: stats.py:135; */ +/* stats.py: Exobiologist rank; In files: stats.py:133; */ "Mostly Directionless" = "Głównie zagubiony"; -/* stats.py: Exobiologist rank; In files: stats.py:136; */ +/* stats.py: Exobiologist rank; In files: stats.py:134; */ "Compiler" = "Wykonawca"; -/* stats.py: Exobiologist rank; In files: stats.py:137; */ +/* stats.py: Exobiologist rank; In files: stats.py:135; */ "Collector" = "Zbieracz"; -/* stats.py: Exobiologist rank; In files: stats.py:138; */ +/* stats.py: Exobiologist rank; In files: stats.py:136; */ "Cataloguer" = "Inwentaryzator"; -/* stats.py: Exobiologist rank; In files: stats.py:139; */ +/* stats.py: Exobiologist rank; In files: stats.py:137; */ "Taxonomist" = "Taksonomista"; -/* stats.py: Exobiologist rank; In files: stats.py:140; */ +/* stats.py: Exobiologist rank; In files: stats.py:138; */ "Ecologist" = "Ekolog"; -/* stats.py: Exobiologist rank; In files: stats.py:141; */ +/* stats.py: Exobiologist rank; In files: stats.py:139; */ "Geneticist" = "Genetyk"; -/* 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" = "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: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "Status: Nieznana nazwa komandora"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "Status: Brak danych CAPI"; -/* 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" = "Wartość"; -/* stats.py: Status dialog title; In files: stats.py:422; */ +/* stats.py: Status dialog title; In files: stats.py:418; */ "Ships" = "Statki"; diff --git a/L10n/pt-BR.strings b/L10n/pt-BR.strings index 93e34f0c..38998c70 100644 --- a/L10n/pt-BR.strings +++ b/L10n/pt-BR.strings @@ -1,749 +1,773 @@ -/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; In files: inara.py:383; inara.py:386; */ -"Inara only accepts Live galaxy data" = "Inara apenas aceita dados da versão Live."; - /* Language name */ "!Language" = "Português (Brasil)"; -/* 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..." = "Enviando log para o 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" = "Erro: Não é possível conectar-se ao 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" = "Enviar log da estação para o EDDN"; - -/* 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" = "Enviar sistemas e dados escaneados para o 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" = "Atrasar o envio até estar docado"; - -/* 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" = "Enviar dados de voo e status do cmdt para o 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" = "Credenciais do Elite Dangerous Star Map (EDSM)"; - -/* 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" = "Cmdt"; - -/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */ -"Commander Name" = "Nome do Comandante"; - -/* 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" = "Chave da 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" = "Nenhum"; - -/* 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}" = "Erro: 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" = "Erro: Não é possível conectar-se ao 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" = "Enviar dados de voo e status do cmdt para o 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" = "Credenciais do 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}" = "Erro: 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" = "Automático"; - -/* 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='" = "Define a URL a ser usada com coriolis.io. ATENÇÃO: deve terminar com '/import?data='"; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "URL Normal"; - -/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */ -"Reset" = "Redefinir"; - -/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */ -"Beta URL" = "URL Beta"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "Substituir Seleção Beta/Normal"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "Modo de substituição Coriolis inválido!"; - -/* eddb.py: Journal Processing disabled due to an active killswitch; In files: load.py:99; eddb.py:100; */ -"EDDB Journal processing disabled. See Log." = "Processamento de Jornais no EDDB desativado. Verifique o Log."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "Manipulador de Jornais do EDDN desativado. Verique o Log."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "Manipulador do EDSM desativado. Verifique o Log."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara desativado. Verifique o 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: Nenhum dado de comandante retornado"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "Substituir Seleção Beta/Normal"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "Erro EDDN: o EDMC é muito antigo para o EDDN. Por favor, atualize."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Erro EDDN: Validação falhou (EDMC antigo?). Verifique o log."; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "Erro EDDN: retornou o código {STATUS}."; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "'Rota' não definida em NavRoute.json"; - -/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */ -"Journal directory already locked" = "Diretório de Jornais já está bloqueado"; - -/* 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." = "O novo Diretório de Jornais já está bloqueado.{CR}Você pode resolver o problema e Tentar novamente, ou Ignorar o erro."; - -/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */ -"Retry" = "Tentar novamente"; - -/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */ -"Ignore" = "Ignorar"; - -/* 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" = "Copiar"; - -/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */ -"Update" = "Atualizar"; - -/* 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 no topo"; - -/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */ -"Unknown" = "Desconhecido"; - -/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "Erro: Verifique a localicação dos arquivos de Jornais E:D"; - -/* 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" = "Função"; - -/* 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" = "Traje"; - -/* 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" = "Estação"; - -/* 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" = "Arquivo"; - -/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */ -"Edit" = "Editar"; - -/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */ -"View" = "Visualizar"; - -/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */ -"Window" = "Janela"; - -/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */ -"Help" = "Ajuda"; - -/* 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}" = "Sobre {APP}"; - -/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */ -"Check for Updates..." = "Verificar por Atualizações..."; - -/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */ -"Save Raw Data..." = "Salvar dados brutos..."; - -/* 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" = "Política de Privacidade"; - -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */ -"Release Notes" = "Notas de atualização"; - -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */ -"Settings" = "Configurações"; - -/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */ -"Exit" = "Sair"; - -/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */ -"Documentation" = "Documentação"; - -/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */ -"Logging in..." = "Efetuando login..."; - -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */ -"Authentication successful" = "Autenticação bem-sucedida"; - -/* 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!" = "Você não está docado na estação!"; - -/* 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!" = "A estação não tem nada!"; - -/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */ -"Station doesn't have a market!" = "A estação não tem um mercado!"; - -/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "Requisição CAPI cancelada: nome de CMDT desconhecido"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "Requisição CAPI cancelada: modo de jogo desconhecido"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "Requisição CAPI cancelada: sistema atual desconhecido"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "Requisição CAPI cancelada: em multi-crew em outra nave"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "Requisição CAPI cancelada: CQC (Arena) detectado"; - -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */ -"Fetching data..." = "Obtendo dados..."; - -/* 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?!" = "Quem é você?!"; - -/* 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?!" = "Onde está você?!"; - -/* 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?!" = "No que você está voando?!"; - -/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Erro de servidor do CAPI da Frontier"; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI: renovando token de acesso..."; - -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */ -"Last updated at %H:%M:%S" = "Última atualização %H:%M:%S"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */ -"Fighter" = "Caça"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */ -"Gunner" = "Artilheiro"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */ -"Helm" = "Comando"; - -/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */ -"cooldown {SS}s" = "aguarde {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..." = "Encerrando..."; - -/* 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." = "Um ou mais dos plugins habilitados não possuem suporte ao Python 3.x. Você pode ver a lista na guia '{PLUGINS}' em '{FILE}' > '{SETTINGS}'. Você deve verificar se existe versão atualizada ou então avisar o desenvolvedor de que ele precisa atualizar o código para o Python 3.x.\n\nVocê pode desabilitar um plugin renomeando sua pasta para que seu nome termine com '{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 sem Suporte ao 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" = "Erro: o CAPI da Frontier não respondeu"; -/* 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" = "Erro: O servidor da Frontier está com lag"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ -"Docked but unknown station: EDO Settlement?" = "Docado, mas estação desconhecida: assentamento Odyssey?"; +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ +"Docked but unknown station: EDO Settlement?" = "Docado, mas estação desconhecida: Assentamento Odyssey?"; -/* 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" = "Erro: Credenciais Inválidas"; -/* 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" = "Erro: Cmdt Errado"; -/* 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" = "Erro"; -/* 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" = "Erro: não foi possível verificar o 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!" = "Erro: customer_id diferente!"; -/* 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" = "Erro: não foi possível obter o token"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "CAPI da Frontier indisponível por manutenção"; -/* 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" = "Falha na requisição ao CAPI da Frontier"; -/* 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" = "Atualizar"; + +/* 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 no topo"; + +/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */ +"Unknown" = "Desconhecido"; + +/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "Erro: Verifique a localicação dos arquivos de Jornais E:D"; + +/* 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" = "Cmdt"; + +/* 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" = "Função"; + +/* 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" = "Traje"; + +/* 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" = "Estação"; + +/* 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" = "Arquivo"; + +/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */ +"Edit" = "Editar"; + +/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */ +"View" = "Visualizar"; + +/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */ +"Window" = "Janela"; + +/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */ +"Help" = "Ajuda"; + +/* 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}" = "Sobre {APP}"; + +/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */ +"Check for Updates..." = "Verificar por Atualizações..."; + +/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */ +"Save Raw Data..." = "Salvar dados brutos..."; + +/* 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" = "Documentação"; + +/* EDMarketConnector.py: Help > Troubleshooting; In files: EDMarketConnector.py:934; EDMarketConnector.py:954; */ +"Troubleshooting" = "Resolução de Problemas"; + +/* EDMarketConnector.py: Help > Report A Bug; In files: EDMarketConnector.py:935; EDMarketConnector.py:955; */ +"Report A Bug" = "Reportar um Bug"; + +/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */ +"Privacy Policy" = "Política de Privacidade"; + +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */ +"Release Notes" = "Notas de atualização"; + +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */ +"Settings" = "Configurações"; + +/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */ +"Exit" = "Sair"; + +/* 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" = "Copiar"; + +/* EDMarketConnector.py: CAPI auth aborted because of killswitch; EDMarketConnector.py: CAPI auth query aborted because of killswitch; In files: EDMarketConnector.py:973; EDMarketConnector.py:1067; */ +"CAPI auth disabled by killswitch" = "Autenticação CAPI desativada pelo botão de interrupção."; + +/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */ +"Logging in..." = "Efetuando login..."; + +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */ +"Authentication successful" = "Autenticação bem-sucedida"; + +/* 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!" = "Você não está docado na estação!"; + +/* 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!" = "A estação não tem nada!"; + +/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */ +"Station doesn't have a market!" = "A estação não tem um mercado!"; + +/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "Requisição CAPI cancelada: nome de CMDT desconhecido"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "Requisição CAPI cancelada: modo de jogo desconhecido"; + +/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because GameVersion unknown; In files: EDMarketConnector.py:1089; EDMarketConnector.py:1170; */ +"CAPI query aborted: GameVersion unknown" = "Requisição CAPI cancelada: Versão de jogo desconhecida"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "Requisição CAPI cancelada: sistema atual desconhecido"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "Requisição CAPI cancelada: em multi-crew em outra nave"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "Requisição CAPI cancelada: CQC (Arena) detectado"; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ +"Fetching data..." = "Obtendo dados..."; + +/* EDMarketConnector.py: CAPI fleetcarrier query aborted because of killswitch; In files: EDMarketConnector.py:1157; */ +"CAPI fleetcarrier disabled by killswitch" = "CAPI para porta-frotas desativado pelo botão de interrupção."; + +/* EDMarketConnector.py: No data was returned for the fleetcarrier from the Frontier CAPI; In files: EDMarketConnector.py:1219; */ +"CAPI: No fleetcarrier data returned" = "CAPI: Nenhum dado de porta-fortas retornado"; + +/* EDMarketConnector.py: We didn't have the fleetcarrier callsign when we should have; In files: EDMarketConnector.py:1223; */ +"CAPI: Fleetcarrier data incomplete" = "CAPI: Dados de porta-frota incompletos"; + +/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */ +"CAPI: No commander data returned" = "CAPI: Nenhum dado de comandante retornado"; + +/* 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?!" = "Quem é você?!"; + +/* 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?!" = "Onde está você?!"; + +/* 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?!" = "No que você está voando?!"; + +/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Erro de servidor do CAPI da Frontier"; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ +"CAPI: Refreshing access token..." = "CAPI: renovando token de acesso..."; + +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */ +"Last updated at %H:%M:%S" = "Última atualização %H:%M:%S"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */ +"Fighter" = "Caça"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */ +"Gunner" = "Artilheiro"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */ +"Helm" = "Comando"; + +/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */ +"cooldown {SS}s" = "aguarde {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..." = "Encerrando..."; + +/* 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." = "Um ou mais dos plugins habilitados não possuem suporte ao Python 3.x. Você pode ver a lista na guia '{PLUGINS}' em '{FILE}' > '{SETTINGS}'. Você deve verificar se existe versão atualizada ou então avisar o desenvolvedor de que ele precisa atualizar o código para o Python 3.x.\n\nVocê pode desabilitar um plugin renomeando sua pasta para que seu nome termine com '{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 sem Suporte ao 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" = "Diretório de Jornais já está bloqueado"; + +/* 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." = "O novo Diretório de Jornais já está bloqueado.{CR}Você pode resolver o problema e Tentar novamente, ou Ignorar o erro."; + +/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */ +"Retry" = "Tentar novamente"; + +/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */ +"Ignore" = "Ignorar"; + +/* 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" = "Padrão"; -/* 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" = "Automático"; + +/* 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='" = "Define a URL a ser usada com coriolis.io. ATENÇÃO: deve terminar com '/import?data='"; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "URL Normal"; + +/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */ +"Reset" = "Redefinir"; + +/* 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" = "Substituir Seleção Beta/Normal"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "Modo de substituição Coriolis inválido!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "Processamento de Jornais no EDDB desativado. Verifique o 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" = "Erro: Não é possível conectar-se ao EDDN"; + +/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "Erro EDDN: o EDMC é muito antigo para o EDDN. Por favor, atualize."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Erro EDDN: Validação falhou (EDMC antigo?). Verifique o log."; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "Erro EDDN: retornou o código {STATUS}."; + +/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */ +"Send station data to the Elite Dangerous Data Network" = "Enviar log da estação para o EDDN"; + +/* 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" = "Enviar sistemas e dados escaneados para o 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" = "Atrasar o envio até estar docado"; + +/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "Manipulador de Jornais do EDDN desativado. Verique o Log."; + +/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */ +"Sending data to EDDN..." = "Enviando log para o EDDN..."; + +/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */ +"Send flight log and Cmdr status to EDSM" = "Enviar dados de voo e status do cmdt para o EDSM"; + +/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */ +"Elite Dangerous Star Map credentials" = "Credenciais do Elite Dangerous Star Map (EDSM)"; + +/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */ +"Commander Name" = "Nome do Comandante"; + +/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */ +"API Key" = "Chave da 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" = "Nenhum"; + +/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "Manipulador do EDSM desativado. Verifique o Log."; + +/* edsm.py: EDSM - Only Live data; In files: edsm.py:632; */ +"EDSM only accepts Live galaxy data" = "EDSM aceita apenas dados da versão Live"; + +/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */ +"Error: EDSM {MSG}" = "Erro: 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" = "Erro: Não é possível conectar-se ao EDSM"; + +/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */ +"Send flight log and Cmdr status to Inara" = "Enviar dados de voo e status do cmdt para o Inara"; + +/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */ +"Inara credentials" = "Credenciais do Inara"; + +/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; inara.py: Inara - Only Live data; In files: inara.py:384; inara.py:386; */ +"Inara only accepts Live galaxy data" = "Inara apenas aceita dados da versão Live."; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "Inara desativado. Verifique o 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}" = "Erro: Inara {MSG}"; + +/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */ "Preferences" = "Preferências"; -/* 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" = "Por favor, escolha quais dados para salvar"; -/* 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" = "Dados de mercado no arquivo de 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" = "Dados de mercado no arquivo de 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" = "Modulação da 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" = "Atualizar automaticamente na docagem"; -/* 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" = "Localização do Arquivo"; -/* 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..." = "Alterar..."; -/* 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..." = "Procurar..."; -/* 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" = "Saída"; -/* 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" = "Localização dos arquivos de Jornais E:D"; -/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */ +/* prefs.py: Settings > Configuration - Label for CAPI section; In files: prefs.py:469; */ +"CAPI Settings" = "Configurações de CAPI"; + +/* prefs.py: Configuration - Enable or disable the Fleet Carrier CAPI calls; In files: prefs.py:475; */ +"Enable Fleetcarrier CAPI Queries" = "Ativar requisições CAPI para porta-frotas"; + +/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */ "Keyboard shortcut" = "Atalho de teclado"; -/* 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" = "Tecla de atalho"; -/* 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" = "Reinicie o {APP} para usar os atalhos"; -/* 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} precisa de permissão para usar atalhos"; -/* 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" = "Abrir preferências do 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" = "Somente quando o Elite: Dangerous é o aplicativo ativo"; -/* 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" = "Tocar som"; -/* 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" = "Desativar Verificação Automática de Atualizações do EDMC enquanto jogo"; -/* 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" = "Website preferido"; -/* 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" = "Estaleiro"; -/* 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" = "Usar URL alternativa"; -/* 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" = "Nível de 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" = "Configuração"; -/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "Opções de privacidade da IU"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "Ocultar nome do grupo privado na IU"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "Ocultar nome do capitão em multi-crew."; -/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */ +/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */ "Privacy" = "Privacidade"; -/* 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" = "Texto 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" = "Texto destacado"; -/* 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" = "Idioma"; -/* 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" = "Escuro"; -/* 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" = "Transparente"; -/* 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" = "Porcentagem de escala da IU"; -/* 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 Padrão{CR}Necessário Reiniciar para as{CR}alterações entrarem em vigor!"; -/* 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" = "Transparência da janela principal"; -/* 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 significa totalmente opaco.{CR}A janela é atualizada em tempo real."; -/* 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" = "Minimizar para a área de notificação"; -/* 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" = "Aparência"; -/* 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" = "Pasta dos 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" = "Abrir"; -/* 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" = "Dica: Você pode desativar um plugin{CR}adicionando '{EXT}' ao nome da pasta"; -/* 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 Habilitados"; -/* 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:" = "Plugins sem suporte 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" = "Informações de migração de 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 desabilitados"; -/* stats.py: Cmdr stats; In files: stats.py:60; */ +/* stats.py: Cmdr stats; In files: stats.py:58; */ "Balance" = "Balanço"; -/* stats.py: Cmdr stats; In files: stats.py:61; */ +/* stats.py: Cmdr stats; In files: stats.py:59; */ "Loan" = "Empréstimo"; -/* stats.py: Top rank; In files: stats.py:65; */ +/* stats.py: Top rank; In files: stats.py:63; */ "Elite" = "Elite"; -/* stats.py: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Elite I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Elite II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Elite III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Elite IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Elite V"; -/* stats.py: Ranking; In files: stats.py:76; */ +/* stats.py: Ranking; In files: stats.py:74; */ "Combat" = "Combate"; -/* stats.py: Ranking; In files: stats.py:77; */ +/* stats.py: Ranking; In files: stats.py:75; */ "Trade" = "Comércio"; -/* stats.py: Ranking; In files: stats.py:78; */ +/* stats.py: Ranking; In files: stats.py:76; */ "Explorer" = "Exploração"; -/* stats.py: Ranking; In files: stats.py:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "Mercenário"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "Exobiologista"; -/* 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" = "Federação"; -/* stats.py: Ranking; In files: stats.py:83; */ +/* stats.py: Ranking; In files: stats.py:81; */ "Empire" = "Império"; -/* stats.py: Ranking; In files: stats.py:84; */ +/* stats.py: Ranking; In files: stats.py:82; */ "Powerplay" = "Poderes da galáxia"; -/* stats.py: Combat rank; In files: stats.py:93; */ +/* stats.py: Combat rank; In files: stats.py:91; */ "Harmless" = "Inofensivo"; -/* stats.py: Combat rank; In files: stats.py:94; */ +/* stats.py: Combat rank; In files: stats.py:92; */ "Mostly Harmless" = "Quase Inofensivo"; -/* stats.py: Combat rank; In files: stats.py:95; */ +/* stats.py: Combat rank; In files: stats.py:93; */ "Novice" = "Novato"; -/* stats.py: Combat rank; In files: stats.py:96; */ +/* stats.py: Combat rank; In files: stats.py:94; */ "Competent" = "Competente"; -/* stats.py: Combat rank; In files: stats.py:97; */ +/* stats.py: Combat rank; In files: stats.py:95; */ "Expert" = "Experiente"; -/* 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" = "Mestre"; -/* stats.py: Combat rank; In files: stats.py:99; */ +/* stats.py: Combat rank; In files: stats.py:97; */ "Dangerous" = "Perigoso"; -/* stats.py: Combat rank; In files: stats.py:100; */ +/* stats.py: Combat rank; In files: stats.py:98; */ "Deadly" = "Letal"; -/* stats.py: Trade rank; In files: stats.py:103; */ +/* stats.py: Trade rank; In files: stats.py:101; */ "Penniless" = "Pobre"; -/* stats.py: Trade rank; In files: stats.py:104; */ +/* stats.py: Trade rank; In files: stats.py:102; */ "Mostly Penniless" = "Quase pobre"; -/* stats.py: Trade rank; In files: stats.py:105; */ +/* stats.py: Trade rank; In files: stats.py:103; */ "Peddler" = "Camelô"; -/* stats.py: Trade rank; In files: stats.py:106; */ +/* stats.py: Trade rank; In files: stats.py:104; */ "Dealer" = "Negociante"; -/* stats.py: Trade rank; In files: stats.py:107; */ +/* stats.py: Trade rank; In files: stats.py:105; */ "Merchant" = "Mercador"; -/* stats.py: Trade rank; In files: stats.py:108; */ +/* stats.py: Trade rank; In files: stats.py:106; */ "Broker" = "Corretor"; -/* stats.py: Trade rank; In files: stats.py:109; */ +/* stats.py: Trade rank; In files: stats.py:107; */ "Entrepreneur" = "Empresário"; -/* stats.py: Trade rank; In files: stats.py:110; */ +/* stats.py: Trade rank; In files: stats.py:108; */ "Tycoon" = "Magnata"; -/* stats.py: Explorer rank; In files: stats.py:113; */ +/* stats.py: Explorer rank; In files: stats.py:111; */ "Aimless" = "Perdido"; -/* stats.py: Explorer rank; In files: stats.py:114; */ +/* stats.py: Explorer rank; In files: stats.py:112; */ "Mostly Aimless" = "Quase perdido"; -/* stats.py: Explorer rank; In files: stats.py:115; */ +/* stats.py: Explorer rank; In files: stats.py:113; */ "Scout" = "Explorador"; -/* stats.py: Explorer rank; In files: stats.py:116; */ +/* stats.py: Explorer rank; In files: stats.py:114; */ "Surveyor" = "Cartógrafo"; -/* stats.py: Explorer rank; In files: stats.py:117; */ +/* stats.py: Explorer rank; In files: stats.py:115; */ "Trailblazer" = "Desbravador"; -/* stats.py: Explorer rank; In files: stats.py:118; */ +/* stats.py: Explorer rank; In files: stats.py:116; */ "Pathfinder" = "Descobridor"; -/* stats.py: Explorer rank; In files: stats.py:119; */ +/* stats.py: Explorer rank; In files: stats.py:117; */ "Ranger" = "Patrulheiro"; -/* stats.py: Explorer rank; In files: stats.py:120; */ +/* stats.py: Explorer rank; In files: stats.py:118; */ "Pioneer" = "Pioneiro"; -/* stats.py: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Indefeso"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "Quase Indefeso"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Novato"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Soldado"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Pistoleiro"; -/* stats.py: Mercenary rank; In files: stats.py:129; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ "Warrior" = "Guerreiro"; -/* stats.py: Mercenary rank; In files: stats.py:131; */ +/* stats.py: Mercenary rank; In files: stats.py:129; */ "Deadeye" = "Tiro-certo"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Sem Direção"; -/* stats.py: Exobiologist rank; In files: stats.py:135; */ +/* stats.py: Exobiologist rank; In files: stats.py:133; */ "Mostly Directionless" = "Quase Sem Direção"; -/* stats.py: Exobiologist rank; In files: stats.py:136; */ +/* stats.py: Exobiologist rank; In files: stats.py:134; */ "Compiler" = "Compilador"; -/* stats.py: Exobiologist rank; In files: stats.py:137; */ +/* stats.py: Exobiologist rank; In files: stats.py:135; */ "Collector" = "Colecionador"; -/* stats.py: Exobiologist rank; In files: stats.py:138; */ +/* stats.py: Exobiologist rank; In files: stats.py:136; */ "Cataloguer" = "Catalogador"; -/* stats.py: Exobiologist rank; In files: stats.py:139; */ +/* stats.py: Exobiologist rank; In files: stats.py:137; */ "Taxonomist" = "Taxonomista"; -/* stats.py: Exobiologist rank; In files: stats.py:140; */ +/* stats.py: Exobiologist rank; In files: stats.py:138; */ "Ecologist" = "Ecologista"; -/* stats.py: Exobiologist rank; In files: stats.py:141; */ +/* stats.py: Exobiologist rank; In files: stats.py:139; */ "Geneticist" = "Geneticista"; -/* stats.py: CQC rank; In files: stats.py:144; */ +/* stats.py: CQC rank; In files: stats.py:142; */ "Helpless" = "Indefeso"; -/* stats.py: CQC rank; In files: stats.py:145; */ +/* stats.py: CQC rank; In files: stats.py:143; */ "Mostly Helpless" = "Quase Indefeso"; -/* stats.py: CQC rank; In files: stats.py:146; */ +/* stats.py: CQC rank; In files: stats.py:144; */ "Amateur" = "Amador"; -/* stats.py: CQC rank; In files: stats.py:147; */ +/* stats.py: CQC rank; In files: stats.py:145; */ "Semi Professional" = "Semi-profissional"; -/* stats.py: CQC rank; In files: stats.py:148; */ +/* stats.py: CQC rank; In files: stats.py:146; */ "Professional" = "Profissional"; -/* stats.py: CQC rank; In files: stats.py:149; */ +/* stats.py: CQC rank; In files: stats.py:147; */ "Champion" = "Campeão"; -/* stats.py: CQC rank; In files: stats.py:150; */ +/* stats.py: CQC rank; In files: stats.py:148; */ "Hero" = "Herói"; -/* stats.py: CQC rank; In files: stats.py:151; */ +/* stats.py: CQC rank; In files: stats.py:149; */ "Gladiator" = "Gladiador"; -/* stats.py: Federation rank; In files: stats.py:157; */ +/* stats.py: Federation rank; In files: stats.py:155; */ "Recruit" = "Recruta"; -/* stats.py: Federation rank; In files: stats.py:158; */ +/* stats.py: Federation rank; In files: stats.py:156; */ "Cadet" = "Aspirante"; -/* stats.py: Federation rank; In files: stats.py:159; */ +/* stats.py: Federation rank; In files: stats.py:157; */ "Midshipman" = "Cabo"; -/* stats.py: Federation rank; In files: stats.py:160; */ +/* stats.py: Federation rank; In files: stats.py:158; */ "Petty Officer" = "Terceiro-Sargento"; -/* stats.py: Federation rank; In files: stats.py:161; */ +/* stats.py: Federation rank; In files: stats.py:159; */ "Chief Petty Officer" = "Segundo-Sargento"; -/* stats.py: Federation rank; In files: stats.py:162; */ +/* stats.py: Federation rank; In files: stats.py:160; */ "Warrant Officer" = "Primeiro-Sargento"; -/* stats.py: Federation rank; In files: stats.py:163; */ +/* stats.py: Federation rank; In files: stats.py:161; */ "Ensign" = "Suboficial"; -/* stats.py: Federation rank; In files: stats.py:164; */ +/* stats.py: Federation rank; In files: stats.py:162; */ "Lieutenant" = "Tenente"; -/* stats.py: Federation rank; In files: stats.py:165; */ +/* stats.py: Federation rank; In files: stats.py:163; */ "Lieutenant Commander" = "Tenente Comandante"; -/* stats.py: Federation rank; In files: stats.py:166; */ +/* stats.py: Federation rank; In files: stats.py:164; */ "Post Commander" = "Capitão de Corveta"; -/* stats.py: Federation rank; In files: stats.py:167; */ +/* stats.py: Federation rank; In files: stats.py:165; */ "Post Captain" = "Capitão de Fragata"; -/* stats.py: Federation rank; In files: stats.py:168; */ +/* stats.py: Federation rank; In files: stats.py:166; */ "Rear Admiral" = "Contra-Almirante"; -/* stats.py: Federation rank; In files: stats.py:169; */ +/* stats.py: Federation rank; In files: stats.py:167; */ "Vice Admiral" = "Vice-Almirante"; -/* stats.py: Federation rank; In files: stats.py:170; */ +/* stats.py: Federation rank; In files: stats.py:168; */ "Admiral" = "Almirante"; -/* stats.py: Empire rank; In files: stats.py:176; */ +/* stats.py: Empire rank; In files: stats.py:174; */ "Outsider" = "Forasteiro"; -/* stats.py: Empire rank; In files: stats.py:177; */ +/* stats.py: Empire rank; In files: stats.py:175; */ "Serf" = "Servo"; -/* stats.py: Empire rank; In files: stats.py:179; */ +/* stats.py: Empire rank; In files: stats.py:177; */ "Squire" = "Escudeiro"; -/* stats.py: Empire rank; In files: stats.py:180; */ +/* stats.py: Empire rank; In files: stats.py:178; */ "Knight" = "Cavaleiro"; -/* stats.py: Empire rank; In files: stats.py:181; */ +/* stats.py: Empire rank; In files: stats.py:179; */ "Lord" = "Lorde"; -/* stats.py: Empire rank; In files: stats.py:182; */ +/* stats.py: Empire rank; In files: stats.py:180; */ "Baron" = "Barão"; -/* stats.py: Empire rank; In files: stats.py:183; */ +/* stats.py: Empire rank; In files: stats.py:181; */ "Viscount" = "Visconde"; -/* stats.py: Empire rank; In files: stats.py:184; */ +/* stats.py: Empire rank; In files: stats.py:182; */ "Count" = "Conde"; -/* stats.py: Empire rank; In files: stats.py:185; */ +/* stats.py: Empire rank; In files: stats.py:183; */ "Earl" = "Marquês"; -/* stats.py: Empire rank; In files: stats.py:186; */ +/* stats.py: Empire rank; In files: stats.py:184; */ "Marquis" = "Duque"; -/* stats.py: Empire rank; In files: stats.py:187; */ +/* stats.py: Empire rank; In files: stats.py:185; */ "Duke" = "Arqui-Duque"; -/* stats.py: Empire rank; In files: stats.py:188; */ +/* stats.py: Empire rank; In files: stats.py:186; */ "Prince" = "Príncipe"; -/* stats.py: Empire rank; In files: stats.py:189; */ +/* stats.py: Empire rank; In files: stats.py:187; */ "King" = "Rei"; -/* stats.py: Power rank; In files: stats.py:195; */ +/* stats.py: Power rank; In files: stats.py:193; */ "Rating 1" = "Nível 1"; -/* stats.py: Power rank; In files: stats.py:196; */ +/* stats.py: Power rank; In files: stats.py:194; */ "Rating 2" = "Nível 2"; -/* stats.py: Power rank; In files: stats.py:197; */ +/* stats.py: Power rank; In files: stats.py:195; */ "Rating 3" = "Nível 3"; -/* stats.py: Power rank; In files: stats.py:198; */ +/* stats.py: Power rank; In files: stats.py:196; */ "Rating 4" = "Nível 4"; -/* stats.py: Power rank; In files: stats.py:199; */ +/* stats.py: Power rank; In files: stats.py:197; */ "Rating 5" = "Nível 5"; -/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "Status: Nome de CMDT ainda desconhecido"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "Status: ainda sem dados CAPI"; -/* 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" = "Valor"; -/* stats.py: Status dialog title; In files: stats.py:422; */ +/* stats.py: Status dialog title; In files: stats.py:418; */ "Ships" = "Naves"; diff --git a/L10n/pt-PT.strings b/L10n/pt-PT.strings index 20821465..59d160b2 100644 --- a/L10n/pt-PT.strings +++ b/L10n/pt-PT.strings @@ -1,749 +1,773 @@ -/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; In files: inara.py:383; inara.py:386; */ -"Inara only accepts Live galaxy data" = "A API Inara só aceita dados da versão Live"; - /* Language name */ "!Language" = "Português (Portugal)"; -/* 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..." = "A enviar dados para o 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" = "Erro: Não é possível conectar ao 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" = "Enviar dados da estação para o 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" = "Envia dados do Sistema e Scans efectuados para o 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" = "Atrasar o envio até estar atracado"; - -/* 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" = "Enviar dados de voo e o estado do CMDT para o 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" = "Credenciais do Elite Dangerous Star Map (EDSM)"; - -/* 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" = "Cmdt"; - -/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:223; load.py:223; edsm.py:266; */ -"Commander Name" = "Nome do Comandante"; - -/* 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" = "Chave 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" = "Nenhum"; - -/* 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}" = "Erro: 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" = "Erro: Não é possível conectar ao 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" = "Enviar dados de voo e o estado do CMDT para o 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" = "Credenciais 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}" = "Erro: 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='" = "Definir URL a usar com os módulos da nave do coriolis.io. Notar que isto TEM de acabar em '/import?data='"; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "URL Normal"; - -/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */ -"Reset" = "Redefinir"; - -/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */ -"Beta URL" = "URL Beta"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "Sobrepor selecção Beta/Normal"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "Modo de sobreposição Coriolis inválido!"; - -/* eddb.py: Journal Processing disabled due to an active killswitch; In files: load.py:99; eddb.py:100; */ -"EDDB Journal processing disabled. See Log." = "Processamento do diário do EDDB desactivado. Verifique o ficheiro de registos."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "Gestor do diário do EDDN desactivado. Verifique o ficheiro de registos."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "Gestor do EDSM desactivado. Verifique o ficheiro de registos."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara desactivado. Verifique o ficheiro de registos."; - -/* 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: Dados do Comandante não recebidos"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "Sobrepor selecção Beta/Normal"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "Erro EDDN: Versão do EDMC é demasiado antiga para usar com a EDDN. Por favor actualize."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Erro EDDN: Validação falhou (Versão do EDMC demasiado antiga?). Verifique os ficheiros de registo."; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "Erro EDDN: Recebido código de estado {STATUS}"; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "Nenhuma série 'Route' encontrada em NavRoute.json"; - -/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */ -"Journal directory already locked" = "Directório do Diário já se encontra bloqueado"; - -/* 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." = "O novo directório do Diário já se encontra bloqueado.{CR}Pode tentar resolver este problema e depois Tentar Novamente, ou Ignorar isto."; - -/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */ -"Retry" = "Tentar Novamente"; - -/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */ -"Ignore" = "Ignorar"; - -/* 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" = "Copiar"; - -/* EDMarketConnector.py: Update button in main window; In files: EDMarketConnector.py:529; EDMarketConnector.py:828; EDMarketConnector.py:1520; */ -"Update" = "Actualizar"; - -/* 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 por cima"; - -/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */ -"Unknown" = "Desconhecido"; - -/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "Erro: Verifique a localização do ficheiro do diário E:D"; - -/* 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" = "Função"; - -/* 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" = "Fato"; - -/* 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" = "Estação"; - -/* 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" = "Ficheiro"; - -/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */ -"Edit" = "Editar"; - -/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:832; */ -"View" = "Ver"; - -/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:833; */ -"Window" = "Janela"; - -/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:834; EDMarketConnector.py:847; EDMarketConnector.py:850; */ -"Help" = "Ajuda"; - -/* 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}" = "Sobre {APP}"; - -/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:839; EDMarketConnector.py:862; */ -"Check for Updates..." = "Procurar por Actualizações..."; - -/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */ -"Save Raw Data..." = "Salvar dados em bruto..."; - -/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:841; EDMarketConnector.py:853; stats.py:406; */ -"Status" = "Estado"; - -/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:842; EDMarketConnector.py:860; */ -"Privacy Policy" = "Política de Privacidade"; - -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */ -"Release Notes" = "Notas da Versão"; - -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */ -"Settings" = "Definições"; - -/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */ -"Exit" = "Sair"; - -/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:859; */ -"Documentation" = "Documentação"; - -/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:872; */ -"Logging in..." = "Realizando login..."; - -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */ -"Authentication successful" = "Autenticação bem-sucedida"; - -/* 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!" = "Não está atracado numa Estação"; - -/* 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!" = "A Estação não tem nada!"; - -/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */ -"Station doesn't have a market!" = "A Estação não possui um mercado!"; - -/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "Consulta à CAPI abortada: Nome do Comandante desconhecido"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "Consulta à CAPI abortada: Modo de Jogo desconhecido"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "Consulta à CAPI abortada: Sistema actual desconhecido"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "Consulta à CAPI abortada: Jogador em multi-tripulação noutra nave."; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "Consulta à CAPI abortada: CQC (Arena) detectada."; - -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */ -"Fetching data..." = "Obtendo dados..."; - -/* 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?!" = "Quem é você?"; - -/* 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?!" = "Onde é que está?"; - -/* 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?!" = "No que é que está a voar?"; - -/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Erro do servidor CAPI da Frontier."; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI: Renovando a chave de acesso"; - -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */ -"Last updated at %H:%M:%S" = "Última actualização: %H:%M:%S"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1254; */ -"Fighter" = "Caça"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1255; */ -"Gunner" = "Artilheiro"; - -/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1256; */ -"Helm" = "Comando"; - -/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1514; */ -"cooldown {SS}s" = "aguarde {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..." = "A Desligar..."; - -/* 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." = "Um ou mais dos plugins activados não possui ainda suporte para Python 3.x. Por favor verifique a lista na aba '{PLUGINS}' em '{FILE}' > '{SETTINGS}'. Deverá verificar se está disponível uma versão mais actualizada, caso contrário, informe o desenvolvedor de que necessita de actualizar o código para suportar Python 3.x.\n\nPode desactivar um plugin colocando '{DISABLED}' no fim do nome da pasta correspondente."; - -/* 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 sem suporte para 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" = "Erro: CAPI da Frontier não respondeu."; -/* 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" = "Erro: O servidor da Frontier está atrasado"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "Atracado numa estação desconhecida. É uma colónia EDO?"; -/* 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" = "Erro: Credenciais Inválidas"; -/* 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" = "Erro: Cmdt errado"; -/* 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" = "Erro"; -/* 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" = "Erro: Impossível verificar o token de 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!" = "Erro: customer_id não foi encontrado!"; -/* 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" = "Erro: Não é possível obter o token"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "CAPI da Frontier em manutenção."; -/* 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" = "Falha ao consultar a CAPI da Frontier."; -/* 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" = "Actualizar"; + +/* 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 por cima"; + +/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */ +"Unknown" = "Desconhecido"; + +/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "Erro: Verifique a localização do ficheiro do diário E:D"; + +/* 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" = "Cmdt"; + +/* 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" = "Função"; + +/* 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" = "Fato"; + +/* 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" = "Estação"; + +/* 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" = "Ficheiro"; + +/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */ +"Edit" = "Editar"; + +/* EDMarketConnector.py: 'View' menu title on OSX; In files: EDMarketConnector.py:923; */ +"View" = "Ver"; + +/* EDMarketConnector.py: 'Window' menu title on OSX; In files: EDMarketConnector.py:924; */ +"Window" = "Janela"; + +/* EDMarketConnector.py: Help' menu title on OSX; EDMarketConnector.py: 'Help' menu title; In files: EDMarketConnector.py:925; EDMarketConnector.py:941; EDMarketConnector.py:944; */ +"Help" = "Ajuda"; + +/* 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}" = "Sobre {APP}"; + +/* EDMarketConnector.py: Help > Check for Updates...; In files: EDMarketConnector.py:930; EDMarketConnector.py:958; */ +"Check for Updates..." = "Procurar por Actualizações..."; + +/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */ +"Save Raw Data..." = "Salvar dados em bruto..."; + +/* EDMarketConnector.py: File > Status; stats.py: Status dialog title; In files: EDMarketConnector.py:932; EDMarketConnector.py:947; stats.py:402; */ +"Status" = "Estado"; + +/* EDMarketConnector.py: Help > Documentation; In files: EDMarketConnector.py:933; EDMarketConnector.py:953; */ +"Documentation" = "Documentação"; + +/* EDMarketConnector.py: Help > Troubleshooting; In files: EDMarketConnector.py:934; EDMarketConnector.py:954; */ +"Troubleshooting" = "Resolução de Problemas"; + +/* EDMarketConnector.py: Help > Report A Bug; In files: EDMarketConnector.py:935; EDMarketConnector.py:955; */ +"Report A Bug" = "Reportar Erro"; + +/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */ +"Privacy Policy" = "Política de Privacidade"; + +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */ +"Release Notes" = "Notas da Versão"; + +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */ +"Settings" = "Definições"; + +/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */ +"Exit" = "Sair"; + +/* 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" = "Copiar"; + +/* EDMarketConnector.py: CAPI auth aborted because of killswitch; EDMarketConnector.py: CAPI auth query aborted because of killswitch; In files: EDMarketConnector.py:973; EDMarketConnector.py:1067; */ +"CAPI auth disabled by killswitch" = "Autenticação CAPI desligada por botão"; + +/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */ +"Logging in..." = "Realizando login..."; + +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */ +"Authentication successful" = "Autenticação bem-sucedida"; + +/* 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!" = "Não está atracado numa Estação"; + +/* 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!" = "A Estação não tem nada!"; + +/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */ +"Station doesn't have a market!" = "A Estação não possui um mercado!"; + +/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "Consulta à CAPI cancelada: Nome do Comandante desconhecido"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "Consulta à CAPI cancelada: Modo de Jogo desconhecido"; + +/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because GameVersion unknown; In files: EDMarketConnector.py:1089; EDMarketConnector.py:1170; */ +"CAPI query aborted: GameVersion unknown" = "Consulta à CAPI cancelada: Versão de Jogo desconhecida"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "Consulta à CAPI cancelada: Sistema actual desconhecido"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "Consulta à CAPI cancelada: Jogador em multi-tripulação noutra nave."; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "Consulta à CAPI cancelada: CQC (Arena) detectada."; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ +"Fetching data..." = "Obtendo dados..."; + +/* EDMarketConnector.py: CAPI fleetcarrier query aborted because of killswitch; In files: EDMarketConnector.py:1157; */ +"CAPI fleetcarrier disabled by killswitch" = "Consulta à CAPI de Transportador de Frota cancelada por botão"; + +/* EDMarketConnector.py: No data was returned for the fleetcarrier from the Frontier CAPI; In files: EDMarketConnector.py:1219; */ +"CAPI: No fleetcarrier data returned" = "CAPI: Sem dados de Transportador de Frota"; + +/* EDMarketConnector.py: We didn't have the fleetcarrier callsign when we should have; In files: EDMarketConnector.py:1223; */ +"CAPI: Fleetcarrier data incomplete" = "CAPI: Dados de Transportador de Frota incompletos"; + +/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */ +"CAPI: No commander data returned" = "CAPI: Dados do Comandante não recebidos"; + +/* 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?!" = "Quem é você?"; + +/* 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?!" = "Onde é que está?"; + +/* 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?!" = "No que é que está a voar?"; + +/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Erro do servidor CAPI da Frontier."; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ +"CAPI: Refreshing access token..." = "CAPI: Renovando a chave de acesso"; + +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */ +"Last updated at %H:%M:%S" = "Última actualização: %H:%M:%S"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1462; */ +"Fighter" = "Caça"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1463; */ +"Gunner" = "Artilheiro"; + +/* EDMarketConnector.py: Multicrew role; In files: EDMarketConnector.py:1464; */ +"Helm" = "Comando"; + +/* EDMarketConnector.py: Cooldown on 'Update' button; In files: EDMarketConnector.py:1742; */ +"cooldown {SS}s" = "aguarde {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..." = "A Desligar..."; + +/* 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." = "Um ou mais dos plugins activados não possui ainda suporte para Python 3.x. Por favor verifique a lista na aba '{PLUGINS}' em '{FILE}' > '{SETTINGS}'. Deverá verificar se está disponível uma versão mais actualizada, caso contrário, informe o desenvolvedor de que necessita de actualizar o código para suportar Python 3.x.\n\nPode desactivar um plugin colocando '{DISABLED}' no fim do nome da pasta correspondente."; + +/* 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 sem suporte para 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" = "Directório do Diário já se encontra bloqueado"; + +/* 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." = "O novo directório do Diário já se encontra bloqueado.{CR}Pode tentar resolver este problema e depois Tentar Novamente, ou Ignorar isto."; + +/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */ +"Retry" = "Tentar Novamente"; + +/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */ +"Ignore" = "Ignorar"; + +/* 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" = "Predefinido"; -/* 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='" = "Definir URL a usar com os módulos da nave do coriolis.io. Notar que isto TEM de acabar em '/import?data='"; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "URL Normal"; + +/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */ +"Reset" = "Redefinir"; + +/* 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" = "Sobrepor selecção Beta/Normal"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "Modo de sobreposição Coriolis inválido!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "Processamento do diário do EDDB desactivado. Verifique o ficheiro de registos."; + +/* 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" = "Erro: Não é possível conectar ao EDDN"; + +/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "Erro EDDN: Versão do EDMC é demasiado antiga para usar com a EDDN. Por favor actualize."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Erro EDDN: Validação falhou (Versão do EDMC demasiado antiga?). Verifique os ficheiros de registo."; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "Erro EDDN: Recebido código de estado {STATUS}"; + +/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */ +"Send station data to the Elite Dangerous Data Network" = "Enviar dados da estação para o 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" = "Envia dados do Sistema e Scans efectuados para o 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" = "Atrasar o envio até estar atracado"; + +/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "Gestor do diário do EDDN desactivado. Verifique o ficheiro de registos."; + +/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */ +"Sending data to EDDN..." = "A enviar dados para o EDDN..."; + +/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */ +"Send flight log and Cmdr status to EDSM" = "Enviar dados de voo e o estado do CMDT para o EDSM"; + +/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */ +"Elite Dangerous Star Map credentials" = "Credenciais do Elite Dangerous Star Map (EDSM)"; + +/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */ +"Commander Name" = "Nome do Comandante"; + +/* edsm.py: EDSM API key label; inara.py: Inara API key label; In files: edsm.py:350; inara.py:278; */ +"API Key" = "Chave 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" = "Nenhum"; + +/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "Gestor do EDSM desactivado. Verifique o ficheiro de registos."; + +/* edsm.py: EDSM - Only Live data; In files: edsm.py:632; */ +"EDSM only accepts Live galaxy data" = "ESDM apenas aceita dados galácticos em tempo real"; + +/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */ +"Error: EDSM {MSG}" = "Erro: 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" = "Erro: Não é possível conectar ao EDSM"; + +/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */ +"Send flight log and Cmdr status to Inara" = "Enviar dados de voo e o estado do CMDT para o Inara"; + +/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */ +"Inara credentials" = "Credenciais Inara"; + +/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; inara.py: Inara - Only Live data; In files: inara.py:384; inara.py:386; */ +"Inara only accepts Live galaxy data" = "A API Inara só aceita dados da versão Live"; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "Inara desactivado. Verifique o ficheiro de registos."; + +/* 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}" = "Erro: Inara: {MSG}"; + +/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */ "Preferences" = "Preferências"; -/* 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" = "Por favor escolher quais os dados a guardar"; -/* 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" = "Ficheiro dos dados de Mercado no 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" = "Ficheiro dos dados de Mercado no 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" = "Módulos da 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" = "Actualizar automaticamente ao atracar"; -/* 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" = "Localização do Ficheiro"; -/* 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..." = "Alterar..."; -/* 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..." = "Procurar..."; -/* 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" = "Saída"; -/* 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" = "Localização do ficheiro do diário E:D"; -/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */ +/* prefs.py: Settings > Configuration - Label for CAPI section; In files: prefs.py:469; */ +"CAPI Settings" = "Definições CAPI"; + +/* prefs.py: Configuration - Enable or disable the Fleet Carrier CAPI calls; In files: prefs.py:475; */ +"Enable Fleetcarrier CAPI Queries" = "Ligar Consultas CAPI de Transportador de Frota"; + +/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */ "Keyboard shortcut" = "Atalho de Teclado"; -/* 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" = "Tecla Rápida"; -/* 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" = "Reinicie o {APP} para usar os atalhos"; -/* 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" = "A {APP} precisa de autorização para usar atalhos"; -/* 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" = "Abrir Preferências do 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" = "Apenas quando o Elite:Dangerous é a aplicação activa"; -/* 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" = "Reproduzir som"; -/* 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" = "Desactivar Verificação de Updates Automáticos da Aplicação enquanto joga"; -/* 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" = "Websites preferidos"; -/* 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" = "Estaleiro"; -/* 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" = "Usar método 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" = "Nível de 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" = "Configuração"; -/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "Opções Privacidade UI principal"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "Esconder nome do grupo privado na UI"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "Esconder nome de capitão em multi-tripulação."; -/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */ +/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */ "Privacy" = "Privacidade"; -/* 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" = "Texto 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" = "Texto destacado"; -/* 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" = "Linguagem"; -/* 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" = "Escuro"; -/* 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" = "Transparente"; -/* 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" = "Percentagem da escala de 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 Predefinido{CR}Requer reinício para{CR}que as mudanças façam efeito!"; -/* 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" = "Transparência da janela principal"; -/* 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 é completamente opaco.{CR}A janela é actualizada em tempo real."; -/* 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" = "Minimizar para a barra de tarefas"; -/* 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" = "Aparência"; -/* 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" = "Pasta dos 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" = "Abrir"; -/* 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" = "Dica: Pode desactivar um plugin{CR}ao adicionar '{EXT}' ao nome da sua pasta"; -/* 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 Activados"; -/* 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:" = "Plugins sem suporte para 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" = "Informação para migração de 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 Desactivados"; -/* stats.py: Cmdr stats; In files: stats.py:60; */ +/* stats.py: Cmdr stats; In files: stats.py:58; */ "Balance" = "Balanço"; -/* stats.py: Cmdr stats; In files: stats.py:61; */ +/* stats.py: Cmdr stats; In files: stats.py:59; */ "Loan" = "Empréstimo"; -/* stats.py: Top rank; In files: stats.py:65; */ +/* stats.py: Top rank; In files: stats.py:63; */ "Elite" = "Elite"; -/* stats.py: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Elite I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Elite II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Elite III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Elite IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Elite V"; -/* stats.py: Ranking; In files: stats.py:76; */ +/* stats.py: Ranking; In files: stats.py:74; */ "Combat" = "Combate"; -/* stats.py: Ranking; In files: stats.py:77; */ +/* stats.py: Ranking; In files: stats.py:75; */ "Trade" = "Comércio"; -/* stats.py: Ranking; In files: stats.py:78; */ +/* stats.py: Ranking; In files: stats.py:76; */ "Explorer" = "Exploração"; -/* stats.py: Ranking; In files: stats.py:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "Mercenário"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "Exobiólogo"; -/* 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" = "Federação"; -/* stats.py: Ranking; In files: stats.py:83; */ +/* stats.py: Ranking; In files: stats.py:81; */ "Empire" = "Império"; -/* stats.py: Ranking; In files: stats.py:84; */ +/* stats.py: Ranking; In files: stats.py:82; */ "Powerplay" = "Jogos de Poder"; -/* stats.py: Combat rank; In files: stats.py:93; */ +/* stats.py: Combat rank; In files: stats.py:91; */ "Harmless" = "Inofensivo"; -/* stats.py: Combat rank; In files: stats.py:94; */ +/* stats.py: Combat rank; In files: stats.py:92; */ "Mostly Harmless" = "Praticamente Inofensivo"; -/* stats.py: Combat rank; In files: stats.py:95; */ +/* stats.py: Combat rank; In files: stats.py:93; */ "Novice" = "Novato"; -/* stats.py: Combat rank; In files: stats.py:96; */ +/* stats.py: Combat rank; In files: stats.py:94; */ "Competent" = "Competente"; -/* stats.py: Combat rank; In files: stats.py:97; */ +/* stats.py: Combat rank; In files: stats.py:95; */ "Expert" = "Perito"; -/* 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" = "Mestre"; -/* stats.py: Combat rank; In files: stats.py:99; */ +/* stats.py: Combat rank; In files: stats.py:97; */ "Dangerous" = "Perigoso"; -/* stats.py: Combat rank; In files: stats.py:100; */ +/* stats.py: Combat rank; In files: stats.py:98; */ "Deadly" = "Mortal"; -/* stats.py: Trade rank; In files: stats.py:103; */ +/* stats.py: Trade rank; In files: stats.py:101; */ "Penniless" = "Falido"; -/* stats.py: Trade rank; In files: stats.py:104; */ +/* stats.py: Trade rank; In files: stats.py:102; */ "Mostly Penniless" = "Praticamente Pobre"; -/* stats.py: Trade rank; In files: stats.py:105; */ +/* stats.py: Trade rank; In files: stats.py:103; */ "Peddler" = "Vendedor"; -/* stats.py: Trade rank; In files: stats.py:106; */ +/* stats.py: Trade rank; In files: stats.py:104; */ "Dealer" = "Negociante"; -/* stats.py: Trade rank; In files: stats.py:107; */ +/* stats.py: Trade rank; In files: stats.py:105; */ "Merchant" = "Mercador"; -/* stats.py: Trade rank; In files: stats.py:108; */ +/* stats.py: Trade rank; In files: stats.py:106; */ "Broker" = "Corretor"; -/* stats.py: Trade rank; In files: stats.py:109; */ +/* stats.py: Trade rank; In files: stats.py:107; */ "Entrepreneur" = "Empreendedor"; -/* stats.py: Trade rank; In files: stats.py:110; */ +/* stats.py: Trade rank; In files: stats.py:108; */ "Tycoon" = "Magnata"; -/* stats.py: Explorer rank; In files: stats.py:113; */ +/* stats.py: Explorer rank; In files: stats.py:111; */ "Aimless" = "Sem Destino"; -/* stats.py: Explorer rank; In files: stats.py:114; */ +/* stats.py: Explorer rank; In files: stats.py:112; */ "Mostly Aimless" = "Quase sem destino"; -/* stats.py: Explorer rank; In files: stats.py:115; */ +/* stats.py: Explorer rank; In files: stats.py:113; */ "Scout" = "Batedor"; -/* stats.py: Explorer rank; In files: stats.py:116; */ +/* stats.py: Explorer rank; In files: stats.py:114; */ "Surveyor" = "Cartógrafo"; -/* stats.py: Explorer rank; In files: stats.py:117; */ +/* stats.py: Explorer rank; In files: stats.py:115; */ "Trailblazer" = "Guia"; -/* stats.py: Explorer rank; In files: stats.py:118; */ +/* stats.py: Explorer rank; In files: stats.py:116; */ "Pathfinder" = "Descobridor"; -/* stats.py: Explorer rank; In files: stats.py:119; */ +/* stats.py: Explorer rank; In files: stats.py:117; */ "Ranger" = "Patrulheiro"; -/* stats.py: Explorer rank; In files: stats.py:120; */ +/* stats.py: Explorer rank; In files: stats.py:118; */ "Pioneer" = "Pioneiro"; -/* stats.py: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Indefeso"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "Praticamente Indefeso"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Principiante"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Soldado"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Pistoleiro"; -/* stats.py: Mercenary rank; In files: stats.py:129; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ "Warrior" = "Guerreiro"; -/* stats.py: Mercenary rank; In files: stats.py:131; */ +/* stats.py: Mercenary rank; In files: stats.py:129; */ "Deadeye" = "Atirador Exímio"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Perdido"; -/* stats.py: Exobiologist rank; In files: stats.py:135; */ +/* stats.py: Exobiologist rank; In files: stats.py:133; */ "Mostly Directionless" = "Praticamente Perdido"; -/* stats.py: Exobiologist rank; In files: stats.py:136; */ +/* stats.py: Exobiologist rank; In files: stats.py:134; */ "Compiler" = "Compilador"; -/* stats.py: Exobiologist rank; In files: stats.py:137; */ +/* stats.py: Exobiologist rank; In files: stats.py:135; */ "Collector" = "Colecionador"; -/* stats.py: Exobiologist rank; In files: stats.py:138; */ +/* stats.py: Exobiologist rank; In files: stats.py:136; */ "Cataloguer" = "Catalogador"; -/* stats.py: Exobiologist rank; In files: stats.py:139; */ +/* stats.py: Exobiologist rank; In files: stats.py:137; */ "Taxonomist" = "Taxonomista"; -/* stats.py: Exobiologist rank; In files: stats.py:140; */ +/* stats.py: Exobiologist rank; In files: stats.py:138; */ "Ecologist" = "Ecologista"; -/* stats.py: Exobiologist rank; In files: stats.py:141; */ +/* stats.py: Exobiologist rank; In files: stats.py:139; */ "Geneticist" = "Geneticista"; -/* stats.py: CQC rank; In files: stats.py:144; */ +/* stats.py: CQC rank; In files: stats.py:142; */ "Helpless" = "Indefeso"; -/* stats.py: CQC rank; In files: stats.py:145; */ +/* stats.py: CQC rank; In files: stats.py:143; */ "Mostly Helpless" = "Praticamente Indefeso"; -/* stats.py: CQC rank; In files: stats.py:146; */ +/* stats.py: CQC rank; In files: stats.py:144; */ "Amateur" = "Amador"; -/* stats.py: CQC rank; In files: stats.py:147; */ +/* stats.py: CQC rank; In files: stats.py:145; */ "Semi Professional" = "Semi Profissional"; -/* stats.py: CQC rank; In files: stats.py:148; */ +/* stats.py: CQC rank; In files: stats.py:146; */ "Professional" = "Profissional"; -/* stats.py: CQC rank; In files: stats.py:149; */ +/* stats.py: CQC rank; In files: stats.py:147; */ "Champion" = "Campeão"; -/* stats.py: CQC rank; In files: stats.py:150; */ +/* stats.py: CQC rank; In files: stats.py:148; */ "Hero" = "Herói"; -/* stats.py: CQC rank; In files: stats.py:151; */ +/* stats.py: CQC rank; In files: stats.py:149; */ "Gladiator" = "Gladiador"; -/* stats.py: Federation rank; In files: stats.py:157; */ +/* stats.py: Federation rank; In files: stats.py:155; */ "Recruit" = "Recruta"; -/* stats.py: Federation rank; In files: stats.py:158; */ +/* stats.py: Federation rank; In files: stats.py:156; */ "Cadet" = "Cadete"; -/* stats.py: Federation rank; In files: stats.py:159; */ +/* stats.py: Federation rank; In files: stats.py:157; */ "Midshipman" = "Aspirante"; -/* stats.py: Federation rank; In files: stats.py:160; */ +/* stats.py: Federation rank; In files: stats.py:158; */ "Petty Officer" = "Subsargento"; -/* stats.py: Federation rank; In files: stats.py:161; */ +/* stats.py: Federation rank; In files: stats.py:159; */ "Chief Petty Officer" = "Segundo-Sargento"; -/* stats.py: Federation rank; In files: stats.py:162; */ +/* stats.py: Federation rank; In files: stats.py:160; */ "Warrant Officer" = "Sargento-mor"; -/* stats.py: Federation rank; In files: stats.py:163; */ +/* stats.py: Federation rank; In files: stats.py:161; */ "Ensign" = "Subtenente"; -/* stats.py: Federation rank; In files: stats.py:164; */ +/* stats.py: Federation rank; In files: stats.py:162; */ "Lieutenant" = "Tenente"; -/* stats.py: Federation rank; In files: stats.py:165; */ +/* stats.py: Federation rank; In files: stats.py:163; */ "Lieutenant Commander" = "Capitão-tenente"; -/* stats.py: Federation rank; In files: stats.py:166; */ +/* stats.py: Federation rank; In files: stats.py:164; */ "Post Commander" = "Tenente de Fragata"; -/* stats.py: Federation rank; In files: stats.py:167; */ +/* stats.py: Federation rank; In files: stats.py:165; */ "Post Captain" = "Capitão de Fragata"; -/* stats.py: Federation rank; In files: stats.py:168; */ +/* stats.py: Federation rank; In files: stats.py:166; */ "Rear Admiral" = "Contra-Almirante"; -/* stats.py: Federation rank; In files: stats.py:169; */ +/* stats.py: Federation rank; In files: stats.py:167; */ "Vice Admiral" = "Vice-Almirante"; -/* stats.py: Federation rank; In files: stats.py:170; */ +/* stats.py: Federation rank; In files: stats.py:168; */ "Admiral" = "Almirante"; -/* stats.py: Empire rank; In files: stats.py:176; */ +/* stats.py: Empire rank; In files: stats.py:174; */ "Outsider" = "Forasteiro"; -/* stats.py: Empire rank; In files: stats.py:177; */ +/* stats.py: Empire rank; In files: stats.py:175; */ "Serf" = "Servo"; -/* stats.py: Empire rank; In files: stats.py:179; */ +/* stats.py: Empire rank; In files: stats.py:177; */ "Squire" = "Escudeiro"; -/* stats.py: Empire rank; In files: stats.py:180; */ +/* stats.py: Empire rank; In files: stats.py:178; */ "Knight" = "Cavaleiro"; -/* stats.py: Empire rank; In files: stats.py:181; */ +/* stats.py: Empire rank; In files: stats.py:179; */ "Lord" = "Lorde"; -/* stats.py: Empire rank; In files: stats.py:182; */ +/* stats.py: Empire rank; In files: stats.py:180; */ "Baron" = "Barão"; -/* stats.py: Empire rank; In files: stats.py:183; */ +/* stats.py: Empire rank; In files: stats.py:181; */ "Viscount" = "Visconde"; -/* stats.py: Empire rank; In files: stats.py:184; */ +/* stats.py: Empire rank; In files: stats.py:182; */ "Count" = "Conde"; -/* 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" = "Marquês"; -/* stats.py: Empire rank; In files: stats.py:187; */ +/* stats.py: Empire rank; In files: stats.py:185; */ "Duke" = "Duque"; -/* stats.py: Empire rank; In files: stats.py:188; */ +/* stats.py: Empire rank; In files: stats.py:186; */ "Prince" = "Príncipe"; -/* stats.py: Empire rank; In files: stats.py:189; */ +/* stats.py: Empire rank; In files: stats.py:187; */ "King" = "Rei"; -/* stats.py: Power rank; In files: stats.py:195; */ +/* stats.py: Power rank; In files: stats.py:193; */ "Rating 1" = "Nível 1"; -/* stats.py: Power rank; In files: stats.py:196; */ +/* stats.py: Power rank; In files: stats.py:194; */ "Rating 2" = "Nível 2"; -/* stats.py: Power rank; In files: stats.py:197; */ +/* stats.py: Power rank; In files: stats.py:195; */ "Rating 3" = "Nível 3"; -/* stats.py: Power rank; In files: stats.py:198; */ +/* stats.py: Power rank; In files: stats.py:196; */ "Rating 4" = "Nível 4"; -/* stats.py: Power rank; In files: stats.py:199; */ +/* stats.py: Power rank; In files: stats.py:197; */ "Rating 5" = "Nível 5"; -/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "Estado: Nome de Comandante ainda desconhecido."; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "Estado: Ainda sem dados CAPI"; -/* 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" = "Valor"; -/* stats.py: Status dialog title; In files: stats.py:422; */ +/* stats.py: Status dialog title; In files: stats.py:418; */ "Ships" = "Naves"; diff --git a/L10n/ru.strings b/L10n/ru.strings index 582fdd21..99c3d70f 100644 --- a/L10n/ru.strings +++ b/L10n/ru.strings @@ -1,749 +1,773 @@ -/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; In files: inara.py:383; inara.py:386; */ -"Inara only accepts Live galaxy data" = "Inara принимает только данные Live-версии"; - /* 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}"; - -/* 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" = "Автоматический"; - -/* 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" = "Стандартный"; - -/* 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" = "Бета"; - -/* 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='" = "Установите URL для импорта сборок кораблей в coriolis.io. URL должен заканчиваться на '/import?data='"; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "Стандартный URL"; - -/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */ -"Reset" = "Сброс"; - -/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */ -"Beta URL" = "Бета URL"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "Режим переопределения URL"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "Некорректный режим переопределения URL для coriolis.io"; - -/* 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 отключена. См. логи."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "Обработчик журнала EDDN отключен. См. логи."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "Обработчик журнала EDSM отключен. См. логи."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara отключена. См. логи."; - -/* 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: Нет данных пилота"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "Режим переопределения URL"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "Ошибка EDDN: старая версия EDMC, обновитесь до последней."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Ошибка EDDN: Неудачная валидация (старая версия EDMC?). См. логи."; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "Ошибка EDDN: Возвращён статус код {STATUS}"; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "Нет Route массива в NavRoute.json"; - -/* 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: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "Ошибка: проверьте расположение журналов E:D"; - -/* 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: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "Запрос CAPI прерван: Имя командира неизвестно"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "Запрос CAPI прерван: Игровой режим неизвестен"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "Запрос CAPI прерван: Текущая система неизвестна"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "Запрос CAPI прерван: В мультиэкипаже другого корабля"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "Запрос CAPI прерван: Обнаружен CQC (Арена)"; - -/* 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: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Серверная ошибка Frontier CAPI"; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI: Обновление access токена"; - -/* 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" = "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 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" = "Ошибка: CAPI Frontier не отвечает"; -/* 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" = "Ошибка: сервера Frontier нестабильны"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "Неизвестный тип станции: поселение EDO?"; -/* 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!" = "Ошибка: 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" = "Ошибка: не удается получить токен"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "Frontier CAPI остановлен для технического обслуживания"; -/* 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"; -/* 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: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "Ошибка: проверьте расположение журналов E:D"; + +/* 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 > Troubleshooting; In files: EDMarketConnector.py:934; EDMarketConnector.py:954; */ +"Troubleshooting" = "Исправление проблем"; + +/* EDMarketConnector.py: Help > Report A Bug; In files: EDMarketConnector.py:935; EDMarketConnector.py:955; */ +"Report A Bug" = "Сообщить об ошибке"; + +/* 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: CAPI auth aborted because of killswitch; EDMarketConnector.py: CAPI auth query aborted because of killswitch; In files: EDMarketConnector.py:973; EDMarketConnector.py:1067; */ +"CAPI auth disabled by killswitch" = "CAPI аутентификация отключена с помощью killswitch"; + +/* 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: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "Запрос CAPI прерван: Имя командира неизвестно"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "Запрос CAPI прерван: Игровой режим неизвестен"; + +/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because GameVersion unknown; In files: EDMarketConnector.py:1089; EDMarketConnector.py:1170; */ +"CAPI query aborted: GameVersion unknown" = "Запрос CAPI прерван: нет информации о версии игры"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "Запрос CAPI прерван: Текущая система неизвестна"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "Запрос CAPI прерван: В мультиэкипаже другого корабля"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "Запрос CAPI прерван: Обнаружен CQC (Арена)"; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ +"Fetching data..." = "Получение данных..."; + +/* EDMarketConnector.py: CAPI fleetcarrier query aborted because of killswitch; In files: EDMarketConnector.py:1157; */ +"CAPI fleetcarrier disabled by killswitch" = "CAPI кораблей-носителей отключен с помощью killswitch"; + +/* EDMarketConnector.py: No data was returned for the fleetcarrier from the Frontier CAPI; In files: EDMarketConnector.py:1219; */ +"CAPI: No fleetcarrier data returned" = "CAPI: Нет данных о флотоносце"; + +/* EDMarketConnector.py: We didn't have the fleetcarrier callsign when we should have; In files: EDMarketConnector.py:1223; */ +"CAPI: Fleetcarrier data incomplete" = "CAPI: Неполная информация о флотоносце"; + +/* 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: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Серверная ошибка Frontier CAPI"; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ +"CAPI: Refreshing access token..." = "CAPI: Обновление access токена"; + +/* 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" = "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; */ +/* 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" = "Автоматический"; + +/* 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" = "Стандартный"; + +/* 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" = "Бета"; + +/* 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='" = "Установите URL для импорта сборок кораблей в coriolis.io. URL должен заканчиваться на '/import?data='"; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "Стандартный URL"; + +/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */ +"Reset" = "Сброс"; + +/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: coriolis.py:106; */ +"Beta URL" = "Бета 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" = "Режим переопределения URL"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "Некорректный режим переопределения URL для coriolis.io"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "Обработка журнала EDDB отключена. См. логи."; + +/* 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: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "Ошибка EDDN: старая версия EDMC, обновитесь до последней."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "Ошибка EDDN: Неудачная валидация (старая версия EDMC?). См. логи."; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "Ошибка EDDN: Возвращён статус код {STATUS}"; + +/* 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: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "Обработчик журнала EDDN отключен. См. логи."; + +/* 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 - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "Обработчик журнала EDSM отключен. См. логи."; + +/* edsm.py: EDSM - Only Live data; In files: edsm.py:632; */ +"EDSM only accepts Live galaxy data" = "EDSM принимает только данные Live-версии"; + +/* 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: The Inara API only accepts Live galaxy data, not Legacy galaxy data; inara.py: Inara - Only Live data; In files: inara.py:384; inara.py:386; */ +"Inara only accepts Live galaxy data" = "Inara принимает только данные Live-версии"; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "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: Settings > Configuration - Label for CAPI section; In files: prefs.py:469; */ +"CAPI Settings" = "Настройки CAPI"; + +/* prefs.py: Configuration - Enable or disable the Fleet Carrier CAPI calls; In files: prefs.py:475; */ +"Enable Fleetcarrier CAPI Queries" = "Включить запросы к CAPI о флотоносце"; + +/* 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: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "Настройки приватности главного окна"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "Скрывать название приватной группы в главном окне"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "Скрывать ник капитана мультикрю сессии в главном окне"; -/* 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: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Элита I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Элита II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Элита III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Элита IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Элита V"; -/* 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:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "Наемник"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "Экзобиолог"; -/* 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: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Беззащитный"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "В целом беззащитный"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Новичок"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Солдат"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Стрелок"; -/* stats.py: Mercenary rank; In files: stats.py:129; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ "Warrior" = "Воин"; -/* stats.py: Mercenary rank; In files: stats.py:131; */ +/* stats.py: Mercenary rank; In files: stats.py:129; */ "Deadeye" = "Меткий глаз"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Беспомощный"; -/* stats.py: Exobiologist rank; In files: stats.py:135; */ +/* stats.py: Exobiologist rank; In files: stats.py:133; */ "Mostly Directionless" = "Практически беспомощный"; -/* stats.py: Exobiologist rank; In files: stats.py:136; */ +/* stats.py: Exobiologist rank; In files: stats.py:134; */ "Compiler" = "Компилятор"; -/* stats.py: Exobiologist rank; In files: stats.py:137; */ +/* stats.py: Exobiologist rank; In files: stats.py:135; */ "Collector" = "Коллекционер"; -/* stats.py: Exobiologist rank; In files: stats.py:138; */ +/* stats.py: Exobiologist rank; In files: stats.py:136; */ "Cataloguer" = "Каталогизатор"; -/* stats.py: Exobiologist rank; In files: stats.py:139; */ +/* stats.py: Exobiologist rank; In files: stats.py:137; */ "Taxonomist" = "Таксономист"; -/* stats.py: Exobiologist rank; In files: stats.py:140; */ +/* stats.py: Exobiologist rank; In files: stats.py:138; */ "Ecologist" = "Эколог"; -/* stats.py: Exobiologist rank; In files: stats.py:141; */ +/* stats.py: Exobiologist rank; In files: stats.py:139; */ "Geneticist" = "Генетик"; -/* 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" = "Капитан-лейтенант"; -/* stats.py: Federation rank; In files: stats.py:166; */ +/* stats.py: Federation rank; In files: stats.py:164; */ "Post Commander" = "Начальник гарнизона"; -/* stats.py: Federation rank; In files: stats.py:167; */ +/* stats.py: Federation rank; In files: stats.py:165; */ "Post Captain" = "Командир корабля"; -/* 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: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "Статус: На текущий момент имя командира неизвестно"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "Статус: На текущий момент данные CAPI отсутствуют"; -/* 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" = "Корабли"; diff --git a/L10n/sl.strings b/L10n/sl.strings index 76209eb6..acef1bdf 100644 --- a/L10n/sl.strings +++ b/L10n/sl.strings @@ -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"; diff --git a/L10n/sr-Latn-BA.strings b/L10n/sr-Latn-BA.strings index bdc47cd8..e80d4f90 100644 --- a/L10n/sr-Latn-BA.strings +++ b/L10n/sr-Latn-BA.strings @@ -1,749 +1,743 @@ -/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; In files: inara.py:383; inara.py:386; */ -"Inara only accepts Live galaxy data" = "Inara prihvata samo Live galaxy podatke"; - /* Language name */ "!Language" = "Srpski (Latinica, Bosna i Hercegovina)"; -/* 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..." = "Slanje podataka 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" = "Greška: Nemoguće povezivanje sa 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" = "Slanje podataka o stanici na 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" = "Slanje podataka o sistemu i skeniranju na 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" = "Odgodi slanje do pristajanja"; - -/* 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" = "Pošalji log leta i Cmdr status na 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" = "Kredencijali za 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" = "Ime komandanta"; - -/* 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" = "Nije definisano"; - -/* 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}" = "Greška: 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" = "Greška: Nemoguće povezivanje sa 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" = "Pošalji log leta i Cmdr status na 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" = "Kredencijali za 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}" = "Greška: 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" = "Automatski"; - -/* 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" = "Normalni"; - -/* 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='" = "Podesite coriolis.io URL koji će se koristiti za brodsku opremu. Napomena: MORA da se završava sa '/import?data='"; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "Normalni 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"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "Režim rada"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "Neispravan Coriolis režim rada!"; - -/* 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 obrada journala je deaktivirana. Pogledajte Log."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "EDDN obrada journala je deaktivirana. Pogledajte Log."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "EDSM obrada je deaktivirana. Pogledajte Log."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara je deaktivirana. Pogledajte 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: Nema podataka o komandantu"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "Režim rada"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN Greška: EDMC je prestar za EDDN. Molimo ažurirajte."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN Greška: Validacija nije uspjela (EDMC prestar?). Pogledajte log."; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "EDDN Greška: Statusni kod {STATUS}"; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "Nema 'Route' polja u sadržaju NavRoute.json"; - -/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */ -"Journal directory already locked" = "Journal direktorijum je već zaključan"; - -/* 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." = "Novi journal direktorijum je već zaključan.{CR}Možete pokušati da riješite problem i Probate ponovo ili da ga Ignorišete."; - -/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */ -"Retry" = "Probaj ponovo"; - -/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */ -"Ignore" = "Ignoriši"; - -/* 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" = "Osvjež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" = "Uvijek na vrhu"; - -/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */ -"Unknown" = "Nepoznato"; - -/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "Greška: Provjerite lokaciju E:D journal fajla"; - -/* 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" = "Uloga"; - -/* 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" = "Brod"; - -/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */ -"Suit" = "Odijelo"; - -/* 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" = "Stanica"; - -/* 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" = "Fajl"; - -/* 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" = "Prozor"; - -/* 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..." = "Provjeri nadogradnje..."; - -/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */ -"Save Raw Data..." = "Snimi sirove 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" = "Politika privatnosti"; - -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */ -"Release Notes" = "Informacije o verziji"; - -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */ -"Settings" = "Podešavanja"; - -/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */ -"Exit" = "Izlaz"; - -/* 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..." = "Prijavljivanje..."; - -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */ -"Authentication successful" = "Autentifikacija uspješna"; - -/* 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!" = "Niste pristali na stanicu"; - -/* 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!" = "Stanica nema ništa!"; - -/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */ -"Station doesn't have a market!" = "Stanica nema market!"; - -/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "CAPI upit prekinut: nepoznato ime komandanta"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "CAPI upit prekinut: nepoznat režim igre"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "CAPI upit prekinut: nepoznat trenutni sistem"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "CAPI upit prekinut: u višečlanoj posadi drugog broda"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "CAPI upit prekinut: detektovana CQC (Arena)"; - -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */ -"Fetching data..." = "Preuzimanje podataka..."; - -/* 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?!" = "Ko ste vi?!"; - -/* 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?!" = "Gdje se nalazite?!"; - -/* 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?!" = "U čemu letite?!"; - -/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Frontier CAPI serverska greška"; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI: osvježavanje pristupnog tokena..."; - -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */ -"Last updated at %H:%M:%S" = "Posljednji put osvježeno %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" = "pauza {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..." = "Zatvaranje programa..."; - -/* 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." = "Jedan ili više aktiviranih dodataka (plugins) nemaju podršku za Python 3.x. Pogledajte listu u '{PLUGINS}' tabu u '{FILE}' > '{SETTINGS}'. Provjerite da li postoji nadograđena verzija ili obavijesite autora da treba da promijeni kod za Python 3.x.\n\nMožete deaktivirati dodatak (plugin) dodavanjem '{DISABLED}' na kraju imena njegovog foldera."; - -/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */ -"Plugins" = "Dodaci (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: Dodaci (plugins) bez Python 3.x podrške"; - -/* 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" = "Greška: Frontier CAPI nije odgovorio"; -/* 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" = "Greška: Frontier server je usporen"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "Pristali ste, ali stanica je nepoznata: EDO naselje?"; -/* 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" = "Greška: Neispravni kredencijali"; -/* 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" = "Greška: Pogrešan 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" = "Greška"; -/* 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" = "Greška: Nemoguća provjera tokena 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!" = "Greška: customer_id se ne poklapa!"; -/* 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" = "Greška: Nemoguće dobaviti token"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "Frontier CAPI nedostupan zbog održavanja"; -/* 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 neuspješan upit"; -/* 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" = "Osvjež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" = "Uvijek na vrhu"; + +/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */ +"Unknown" = "Nepoznato"; + +/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "Greška: Provjerite lokaciju E:D journal fajla"; + +/* 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" = "Uloga"; + +/* 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" = "Brod"; + +/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */ +"Suit" = "Odijelo"; + +/* 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" = "Stanica"; + +/* 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" = "Fajl"; + +/* 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" = "Prozor"; + +/* 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..." = "Provjeri nadogradnje..."; + +/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */ +"Save Raw Data..." = "Snimi sirove 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" = "Politika privatnosti"; + +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */ +"Release Notes" = "Informacije o verziji"; + +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */ +"Settings" = "Podešavanja"; + +/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */ +"Exit" = "Izlaz"; + +/* 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..." = "Prijavljivanje..."; + +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */ +"Authentication successful" = "Autentifikacija uspješna"; + +/* 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!" = "Niste pristali na stanicu"; + +/* 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!" = "Stanica nema ništa!"; + +/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */ +"Station doesn't have a market!" = "Stanica nema market!"; + +/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "CAPI upit prekinut: nepoznato ime komandanta"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "CAPI upit prekinut: nepoznat režim igre"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "CAPI upit prekinut: nepoznat trenutni sistem"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "CAPI upit prekinut: u višečlanoj posadi drugog broda"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "CAPI upit prekinut: detektovana CQC (Arena)"; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ +"Fetching data..." = "Preuzimanje podataka..."; + +/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */ +"CAPI: No commander data returned" = "CAPI: Nema podataka o komandantu"; + +/* 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?!" = "Ko ste vi?!"; + +/* 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?!" = "Gdje se nalazite?!"; + +/* 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?!" = "U čemu letite?!"; + +/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Frontier CAPI serverska greška"; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ +"CAPI: Refreshing access token..." = "CAPI: osvježavanje pristupnog tokena..."; + +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */ +"Last updated at %H:%M:%S" = "Posljednji put osvježeno %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" = "pauza {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..." = "Zatvaranje programa..."; + +/* 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." = "Jedan ili više aktiviranih dodataka (plugins) nemaju podršku za Python 3.x. Pogledajte listu u '{PLUGINS}' tabu u '{FILE}' > '{SETTINGS}'. Provjerite da li postoji nadograđena verzija ili obavijesite autora da treba da promijeni kod za Python 3.x.\n\nMožete deaktivirati dodatak (plugin) dodavanjem '{DISABLED}' na kraju imena njegovog foldera."; + +/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */ +"Plugins" = "Dodaci (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: Dodaci (plugins) bez Python 3.x podrške"; + +/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:208; */ +"Journal directory already locked" = "Journal direktorijum je već zaključan"; + +/* 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." = "Novi journal direktorijum je već zaključan.{CR}Možete pokušati da riješite problem i Probate ponovo ili da ga Ignorišete."; + +/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */ +"Retry" = "Probaj ponovo"; + +/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */ +"Ignore" = "Ignoriš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" = "Standardna"; -/* 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" = "Automatski"; + +/* 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" = "Normalni"; + +/* 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='" = "Podesite coriolis.io URL koji će se koristiti za brodsku opremu. Napomena: MORA da se završava sa '/import?data='"; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "Normalni 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" = "Režim rada"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "Neispravan Coriolis režim rada!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "EDDB obrada journala je deaktivirana. Pogledajte 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" = "Greška: Nemoguće povezivanje sa EDDN"; + +/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN Greška: EDMC je prestar za EDDN. Molimo ažurirajte."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN Greška: Validacija nije uspjela (EDMC prestar?). Pogledajte log."; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "EDDN Greška: Statusni kod {STATUS}"; + +/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */ +"Send station data to the Elite Dangerous Data Network" = "Slanje podataka o stanici na 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" = "Slanje podataka o sistemu i skeniranju na 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" = "Odgodi slanje do pristajanja"; + +/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "EDDN obrada journala je deaktivirana. Pogledajte Log."; + +/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */ +"Sending data to EDDN..." = "Slanje podataka na EDDN..."; + +/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */ +"Send flight log and Cmdr status to EDSM" = "Pošalji log leta i Cmdr status na EDSM"; + +/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */ +"Elite Dangerous Star Map credentials" = "Kredencijali za Elite Dangerous Star Map"; + +/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */ +"Commander Name" = "Ime komandanta"; + +/* 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" = "Nije definisano"; + +/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "EDSM obrada je deaktivirana. Pogledajte Log."; + +/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */ +"Error: EDSM {MSG}" = "Greška: 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" = "Greška: Nemoguće povezivanje sa EDSM"; + +/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */ +"Send flight log and Cmdr status to Inara" = "Pošalji log leta i Cmdr status na Inara"; + +/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */ +"Inara credentials" = "Kredencijali za Inara"; + +/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; inara.py: Inara - Only Live data; In files: inara.py:384; inara.py:386; */ +"Inara only accepts Live galaxy data" = "Inara prihvata samo Live galaxy podatke"; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "Inara je deaktivirana. Pogledajte 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}" = "Greška: Inara {MSG}"; + +/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */ "Preferences" = "Podešavanja"; -/* 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" = "Izaberite koji podaci se snimaju"; -/* 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" = "Fajl sa market podacima u 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" = "Fajl sa market podacima u 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" = "Brodska oprema"; -/* prefs.py: Settings > Output option; In files: prefs.py:383; */ +/* prefs.py: Settings > Output option; In files: prefs.py:370; */ "Automatically update on docking" = "Automatsko slanje nakon pristajanja"; -/* 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 fajlova"; -/* 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..." = "Promijeni..."; -/* 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..." = "Potraži..."; -/* 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" = "Izvoz"; -/* 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" = "Lokacija E:D journal fajlova"; -/* 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" = "Prečica"; -/* 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" = "Prečica"; -/* 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} da bi ste koristili prečice"; -/* 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} traži dozvolu da koristi prečice"; -/* 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" = "Otvori sistemska podešavanja"; -/* 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 kada 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" = "Zvučni efekat"; -/* 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" = "Isključi automatsku provjeru nadogradnji za vrijeme igranja"; -/* 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" = "Preferirani web sajtovi"; -/* 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" = "Brodogradilište"; -/* 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" = "Koristi alternativni URL metod"; -/* 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" = "Log nivo"; -/* 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: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "Podešavanja privatnosti glavnog prozora"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "Ne prikazuj naziv privatne grupe"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "Ne prikazuj ime kapetana u višečlanoj posadi"; -/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */ +/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */ "Privacy" = "Privatnost"; -/* 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" = "Normalan 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" = "Označeni 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" = "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" = "Tamna"; -/* 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" = "Prozirna"; -/* 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" = "Procenat UI skaliranja"; -/* 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 standardna vrijednost{CR}Potreban je restart{CR}za primjenu podešavanja!"; -/* 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" = "Prozirnost glavnog prozora"; -/* 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 znači potpuno neprozirno.{CR}Prozor se osvježava u realnom vremenu"; -/* 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" = "Minimiziranje u 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" = "Izgled"; -/* 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" = "Folder za dodatke (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" = "Otvori"; -/* 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" = "Savjet: Možete da deaktivirate dodatak (plugin){CR}dodavanjem '{EXT}' na ime njegovog foldera"; -/* 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" = "Aktivirani dodaci (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:" = "Dodaci (plugins) bez Python 3.x podrške:"; -/* 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" = "Informacije o migraciji dodataka (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" = "Deaktivirani dodaci (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" = "Zajam"; -/* stats.py: Top rank; In files: stats.py:65; */ +/* stats.py: Top rank; In files: stats.py:63; */ "Elite" = "Elite"; -/* stats.py: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Elite I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Elite II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Elite III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Elite IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Elite V"; -/* stats.py: Ranking; In files: stats.py:76; */ +/* stats.py: Ranking; In files: stats.py:74; */ "Combat" = "Borba (Combat)"; -/* stats.py: Ranking; In files: stats.py:77; */ +/* stats.py: Ranking; In files: stats.py:75; */ "Trade" = "Trgovina (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:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "Mercenary"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "Exobiologist"; -/* 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 (Federation)"; -/* stats.py: Ranking; In files: stats.py:83; */ +/* stats.py: Ranking; In files: stats.py:81; */ "Empire" = "Imperija (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: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "Mostly Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Rookie"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Soldier"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Gunslinger"; -/* stats.py: Mercenary rank; In files: stats.py:129; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ "Warrior" = "Warrior"; -/* stats.py: Mercenary rank; In files: stats.py:131; */ +/* stats.py: Mercenary rank; In files: stats.py:129; */ "Deadeye" = "Deadeye"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:135; */ +/* stats.py: Exobiologist rank; In files: stats.py:133; */ "Mostly Directionless" = "Mostly Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:136; */ +/* stats.py: Exobiologist rank; In files: stats.py:134; */ "Compiler" = "Compiler"; -/* stats.py: Exobiologist rank; In files: stats.py:137; */ +/* stats.py: Exobiologist rank; In files: stats.py:135; */ "Collector" = "Collector"; -/* stats.py: Exobiologist rank; In files: stats.py:138; */ +/* stats.py: Exobiologist rank; In files: stats.py:136; */ "Cataloguer" = "Cataloguer"; -/* stats.py: Exobiologist rank; In files: stats.py:139; */ +/* stats.py: Exobiologist rank; In files: stats.py:137; */ "Taxonomist" = "Taxonomist"; -/* stats.py: Exobiologist rank; In files: stats.py:140; */ +/* stats.py: Exobiologist rank; In files: stats.py:138; */ "Ecologist" = "Ecologist"; -/* stats.py: Exobiologist rank; In files: stats.py:141; */ +/* stats.py: Exobiologist rank; In files: stats.py:139; */ "Geneticist" = "Geneticist"; -/* 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: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "Status: još uvijek nije poznato ime komandanta"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "Status: još uvijek nema CAPI podataka"; -/* 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" = "Vrijednost"; -/* stats.py: Status dialog title; In files: stats.py:422; */ +/* stats.py: Status dialog title; In files: stats.py:418; */ "Ships" = "Brodovi"; diff --git a/L10n/sr-Latn.strings b/L10n/sr-Latn.strings index ed3cee47..d6d937cc 100644 --- a/L10n/sr-Latn.strings +++ b/L10n/sr-Latn.strings @@ -1,749 +1,773 @@ -/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; In files: inara.py:383; inara.py:386; */ -"Inara only accepts Live galaxy data" = "Inara prihvata samo \"žive\" podatke o galaksiji"; - /* Language name */ "!Language" = "Srpski (Latinica)"; -/* 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..." = "Slanje podataka 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" = "Greška: Nemoguće povezivanje na 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" = "Slanje podataka o stanici na 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" = "Slanje podataka o sistemu i skeniranju na 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" = "Odloži slanje pre pristajanja"; - -/* 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" = "Pošalji log leta i Cmdr status na 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" = "Kredencijali za 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" = "Ime komandira"; - -/* 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" = "Ništa"; - -/* 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}" = "Greška: 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" = "Greška: Nemoguće povezivanje na 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" = "Pošalji log leta i Cmdr status na 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 kredencijali"; - -/* 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}" = "Greška: 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='" = "Postavite URL za korišćenje sa coriolis.io brodskim izborom opreme. Obratite pažnju da ovo MORA da se završi sa '/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" = "Resetuj"; - -/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */ -"Beta URL" = "Beta URL"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "Preinači Beta/Normal izbor"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "Pogrešan Coriolis preinačeni mod!"; - -/* eddb.py: Journal Processing disabled due to an active killswitch; In files: load.py:99; eddb.py:100; */ -"EDDB Journal processing disabled. See Log." = "Obrada žurnala za EDDB je deaktivirana. Pogledajte Log."; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "Obrada žurnala za EDDN je deaktivirana. Pogledajte Log."; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "EDSM obrada je deaktivirana. Pogledajte Log."; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara je deaktivirana. Pogledajte 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: Nema podataka o komandiru"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "Preinači Beta/Normal izbor"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN Greška: EDMC je prestar za EDDN. Molimo ažurirajte."; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN Greška: Validacija nije uspela (EDMC prestar?). Pogledajte log."; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "EDDN Greška: Vraćen {STATUS} statusni kod."; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "Nema 'Route' niza u NavRoute.json sadržaju"; - -/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:206; */ -"Journal directory already locked" = "Žurnal direktorijum je već zaključan"; - -/* 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." = "Novi Žurnal direktorijum je već zaključan.{CR}Možete probati da rešite problem i probate ponovo ili da ga ignorišete."; - -/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:228; */ -"Retry" = "Probaj ponovo"; - -/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:232; */ -"Ignore" = "Ignoriši"; - -/* 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" = "Uvek na vrhu"; - -/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:746; */ -"Unknown" = "Nepoznato"; - -/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "Greška: Proverite lokaciju E:D žurnal fajla"; - -/* 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" = "Uloga"; - -/* 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" = "Brod"; - -/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:825; */ -"Suit" = "Odelo"; - -/* 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" = "Stanica"; - -/* 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" = "Fajl"; - -/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:831; EDMarketConnector.py:846; EDMarketConnector.py:849; */ -"Edit" = "Izmeni"; - -/* 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" = "Prozor"; - -/* 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..." = "Proveri da li postoje izmene..."; - -/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:840; EDMarketConnector.py:854; */ -"Save Raw Data..." = "Snimi sirove 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" = "Polisa o privatnosti"; - -/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:843; EDMarketConnector.py:861; EDMarketConnector.py:1600; */ -"Release Notes" = "Informacije o ovoj verziji"; - -/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:855; EDMarketConnector.py:2020; prefs.py:255; */ -"Settings" = "Podešavanja"; - -/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:856; */ -"Exit" = "Izlaz"; - -/* 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..." = "Prijavljivanje..."; - -/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:888; EDMarketConnector.py:1431; */ -"Authentication successful" = "Autentifikacija uspešna"; - -/* 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!" = "Niste pristali na stanicu!"; - -/* 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!" = "Stanica nema ništa!"; - -/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:932; */ -"Station doesn't have a market!" = "Stanica nema market!"; - -/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "CAPI upit prekinut: Ime komandira nepoznato"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "CAPI upit prekinut: Režim igre nepoznat"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "CAPI upit prekinut: Trenutni sistem nepoznat"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "CAPI upit prekinut: U multi-posadi drugog broda"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "CAPI upit prekinut: CQC (Arena) detektovana"; - -/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1006; */ -"Fetching data..." = "Preuzimanje podataka..."; - -/* 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?!" = "Ko ste vi?"; - -/* 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?!" = "Gde se nalazite?"; - -/* 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?!" = "U čemu letite?"; - -/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Greška na Frontier CAPI serveru"; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI: Osvežavanje pristupnog tokena..."; - -/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1226; */ -"Last updated at %H:%M:%S" = "Poslednji put osveženo %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" = "cooldown {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..." = "Gasim..."; - -/* 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." = "Jedan ili više aktiviranih dodataka (plugins) nemaju podršku za Python 3.x. Pogledajte listu u '{PLUGINS}' tabu u '{FILE}' > '{SETTINGS}'. Proverite da li postoji nadograđena verzija ili obavesite autora da treba da promeni kod za Python 3.x.\n\nMožete deaktivirati dodatak (plugin) dodavanjem '{DISABLED}' na kraju imena njegovog foldera."; - -/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2018; prefs.py:978; */ -"Plugins" = "Dodaci (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: Dodaci (plugins) bez Python 3.x podrške"; - -/* 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" = "Greška: Frontier CAPI nije odgovorio"; -/* 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" = "Greška: Frontier server je usporen"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "Dokovan ali stanica nepoznata: EDO Naselje?"; -/* 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" = "Greška: Pogrešni kredencijali"; -/* 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" = "Greška: Pogrešan 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" = "Greška"; -/* 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" = "Greška: Nemoguća provera tokena 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!" = "Greška: customer_id se ne poklapa!"; -/* 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" = "Greška: nemoguće dobaviti token"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "Frontier CAPI isključen radi održavanja"; -/* 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" = "Greška pri Frontier CAPI upitu"; -/* 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" = "Uvek na vrhu"; + +/* EDMarketConnector.py: Unknown suit; In files: EDMarketConnector.py:837; */ +"Unknown" = "Nepoznato"; + +/* EDMarketConnector.py: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "Greška: Proverite lokaciju E:D žurnal fajla"; + +/* 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" = "Uloga"; + +/* 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" = "Brod"; + +/* EDMarketConnector.py: Label for 'Suit' line in main UI; In files: EDMarketConnector.py:916; */ +"Suit" = "Odelo"; + +/* 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" = "Stanica"; + +/* 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" = "Fajl"; + +/* EDMarketConnector.py: 'Edit' menu title on OSX; EDMarketConnector.py: 'Edit' menu title; In files: EDMarketConnector.py:922; EDMarketConnector.py:940; EDMarketConnector.py:943; */ +"Edit" = "Izmeni"; + +/* 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" = "Prozor"; + +/* 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..." = "Proveri da li postoje izmene..."; + +/* EDMarketConnector.py: File > Save Raw Data...; In files: EDMarketConnector.py:931; EDMarketConnector.py:948; */ +"Save Raw Data..." = "Snimi sirove 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 > Troubleshooting; In files: EDMarketConnector.py:934; EDMarketConnector.py:954; */ +"Troubleshooting" = "Otklanjanje problema"; + +/* EDMarketConnector.py: Help > Report A Bug; In files: EDMarketConnector.py:935; EDMarketConnector.py:955; */ +"Report A Bug" = "Prijavite Bug"; + +/* EDMarketConnector.py: Help > Privacy Policy; In files: EDMarketConnector.py:936; EDMarketConnector.py:956; */ +"Privacy Policy" = "Polisa o privatnosti"; + +/* EDMarketConnector.py: Help > Release Notes; In files: EDMarketConnector.py:937; EDMarketConnector.py:957; EDMarketConnector.py:1838; */ +"Release Notes" = "Informacije o ovoj verziji"; + +/* EDMarketConnector.py: File > Settings; prefs.py: File > Settings (macOS); In files: EDMarketConnector.py:949; EDMarketConnector.py:2265; prefs.py:241; */ +"Settings" = "Podešavanja"; + +/* EDMarketConnector.py: File > Exit; In files: EDMarketConnector.py:950; */ +"Exit" = "Izlaz"; + +/* 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: CAPI auth aborted because of killswitch; EDMarketConnector.py: CAPI auth query aborted because of killswitch; In files: EDMarketConnector.py:973; EDMarketConnector.py:1067; */ +"CAPI auth disabled by killswitch" = "CAPI autentifikacija deaktivirana preko sistemskog prekidača"; + +/* EDMarketConnector.py: Status - Attempting to get a Frontier Auth Access Token; In files: EDMarketConnector.py:978; */ +"Logging in..." = "Prijavljivanje..."; + +/* EDMarketConnector.py: Successfully authenticated with the Frontier website; In files: EDMarketConnector.py:994; EDMarketConnector.py:1657; */ +"Authentication successful" = "Autentifikacija uspešna"; + +/* 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!" = "Niste pristali na stanicu!"; + +/* 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!" = "Stanica nema ništa!"; + +/* EDMarketConnector.py: Status - No station market data from Frontier CAPI; In files: EDMarketConnector.py:1038; */ +"Station doesn't have a market!" = "Stanica nema market!"; + +/* EDMarketConnector.py: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "CAPI upit prekinut: Ime komandira nepoznato"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "CAPI upit prekinut: Režim igre nepoznat"; + +/* EDMarketConnector.py: CAPI queries aborted because GameVersion unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because GameVersion unknown; In files: EDMarketConnector.py:1089; EDMarketConnector.py:1170; */ +"CAPI query aborted: GameVersion unknown" = "CAPI upit prekinut: GameVersion nepoznat"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "CAPI upit prekinut: Trenutni sistem nepoznat"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "CAPI upit prekinut: U multi-posadi drugog broda"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "CAPI upit prekinut: CQC (Arena) detektovana"; + +/* EDMarketConnector.py: Status - Attempting to retrieve data from Frontier CAPI; In files: EDMarketConnector.py:1128; EDMarketConnector.py:1179; */ +"Fetching data..." = "Preuzimanje podataka..."; + +/* EDMarketConnector.py: CAPI fleetcarrier query aborted because of killswitch; In files: EDMarketConnector.py:1157; */ +"CAPI fleetcarrier disabled by killswitch" = "CAPI fleetcarrier deaktiviran preko sistemskog prekidača"; + +/* EDMarketConnector.py: No data was returned for the fleetcarrier from the Frontier CAPI; In files: EDMarketConnector.py:1219; */ +"CAPI: No fleetcarrier data returned" = "CAPI: Podaci o fleetcarrier-u nisu dobijeni"; + +/* EDMarketConnector.py: We didn't have the fleetcarrier callsign when we should have; In files: EDMarketConnector.py:1223; */ +"CAPI: Fleetcarrier data incomplete" = "CAPI: Podaci o fleetcarrier-u su nepotpuni"; + +/* EDMarketConnector.py: No data was returned for the commander from the Frontier CAPI; In files: EDMarketConnector.py:1242; */ +"CAPI: No commander data returned" = "CAPI: Nema podataka o komandiru"; + +/* 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?!" = "Ko ste vi?"; + +/* 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?!" = "Gde se nalazite?"; + +/* 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?!" = "U čemu letite?"; + +/* EDMarketConnector.py: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Greška na Frontier CAPI serveru"; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ +"CAPI: Refreshing access token..." = "CAPI: Osvežavanje pristupnog tokena..."; + +/* EDMarketConnector.py: Time when we last obtained Frontier CAPI data; In files: EDMarketConnector.py:1434; */ +"Last updated at %H:%M:%S" = "Poslednji put osveženo %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" = "cooldown {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..." = "Gasim..."; + +/* 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." = "Jedan ili više aktiviranih dodataka (plugins) nemaju podršku za Python 3.x. Pogledajte listu u '{PLUGINS}' tabu u '{FILE}' > '{SETTINGS}'. Proverite da li postoji nadograđena verzija ili obavesite autora da treba da promeni kod za Python 3.x.\n\nMožete deaktivirati dodatak (plugin) dodavanjem '{DISABLED}' na kraju imena njegovog foldera."; + +/* EDMarketConnector.py: Settings > Plugins tab; prefs.py: Label on Settings > Plugins tab; In files: EDMarketConnector.py:2263; prefs.py:986; */ +"Plugins" = "Dodaci (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: Dodaci (plugins) bez Python 3.x podrške"; + +/* journal_lock.py: Title text on popup when Journal directory already locked; In files: journal_lock.py:208; */ +"Journal directory already locked" = "Žurnal direktorijum je već zaključan"; + +/* 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." = "Novi Žurnal direktorijum je već zaključan.{CR}Možete probati da rešite problem i probate ponovo ili da ga ignorišete."; + +/* journal_lock.py: Generic 'Retry' button label; In files: journal_lock.py:230; */ +"Retry" = "Probaj ponovo"; + +/* journal_lock.py: Generic 'Ignore' button label; In files: journal_lock.py:234; */ +"Ignore" = "Ignoriš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" = "Podrazumevano"; -/* 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='" = "Postavite URL za korišćenje sa coriolis.io brodskim izborom opreme. Obratite pažnju da ovo MORA da se završi sa '/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" = "Resetuj"; + +/* 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" = "Preinači Beta/Normal izbor"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "Pogrešan Coriolis preinačeni mod!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "Obrada žurnala za EDDB je deaktivirana. Pogledajte 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" = "Greška: Nemoguće povezivanje na EDDN"; + +/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN Greška: EDMC je prestar za EDDN. Molimo ažurirajte."; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN Greška: Validacija nije uspela (EDMC prestar?). Pogledajte log."; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "EDDN Greška: Vraćen {STATUS} statusni kod."; + +/* eddn.py: Enable EDDN support for station data checkbox label; In files: eddn.py:2041; */ +"Send station data to the Elite Dangerous Data Network" = "Slanje podataka o stanici na 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" = "Slanje podataka o sistemu i skeniranju na 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" = "Odloži slanje pre pristajanja"; + +/* eddn.py: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "Obrada žurnala za EDDN je deaktivirana. Pogledajte Log."; + +/* eddn.py: Status text shown while attempting to send data; In files: eddn.py:2507; */ +"Sending data to EDDN..." = "Slanje podataka na EDDN..."; + +/* edsm.py: Settings>EDSM - Label on checkbox for 'send data'; In files: edsm.py:308; */ +"Send flight log and Cmdr status to EDSM" = "Pošalji log leta i Cmdr status na EDSM"; + +/* edsm.py: Settings>EDSM - Label on header/URL to EDSM API key page; In files: edsm.py:319; */ +"Elite Dangerous Star Map credentials" = "Kredencijali za Elite Dangerous Star Map"; + +/* edsm.py: EDSM Commander name label in EDSM settings; In files: edsm.py:341; */ +"Commander Name" = "Ime komandira"; + +/* 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" = "Ništa"; + +/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "EDSM obrada je deaktivirana. Pogledajte Log."; + +/* edsm.py: EDSM - Only Live data; In files: edsm.py:632; */ +"EDSM only accepts Live galaxy data" = "EDSM prihvata samo \"žive\" galaktičke podatke"; + +/* edsm.py: EDSM Plugin - Error message from EDSM API; In files: edsm.py:916; edsm.py:1048; */ +"Error: EDSM {MSG}" = "Greška: 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" = "Greška: Nemoguće povezivanje na EDSM"; + +/* inara.py: Checkbox to enable INARA API Usage; In files: inara.py:257; */ +"Send flight log and Cmdr status to Inara" = "Pošalji log leta i Cmdr status na Inara"; + +/* inara.py: Text for INARA API keys link ( goes to https://inara.cz/settings-api ); In files: inara.py:269; */ +"Inara credentials" = "Inara kredencijali"; + +/* inara.py: The Inara API only accepts Live galaxy data, not Legacy galaxy data; inara.py: Inara - Only Live data; In files: inara.py:384; inara.py:386; */ +"Inara only accepts Live galaxy data" = "Inara prihvata samo \"žive\" podatke o galaksiji"; + +/* inara.py: INARA support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "Inara je deaktivirana. Pogledajte 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}" = "Greška: Inara {MSG}"; + +/* prefs.py: File > Preferences menu entry for macOS; In files: prefs.py:237; */ "Preferences" = "Podešavanja"; -/* 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" = "Izaberite koji se podaci snimaju"; -/* 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" = "Fajl sa market podacima u 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" = "Fajl sa market podacima u 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 na brodu"; -/* prefs.py: Settings > Output option; In files: prefs.py:383; */ +/* prefs.py: Settings > Output option; In files: prefs.py:370; */ "Automatically update on docking" = "Automatsko slanje prilikom pristajanja"; -/* 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 fajlova"; -/* 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..." = "Izmeni..."; -/* 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..." = "Potraži..."; -/* 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" = "Izlaz"; -/* 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" = "Lokacija E:D Journal fajlova"; -/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:484; */ +/* prefs.py: Settings > Configuration - Label for CAPI section; In files: prefs.py:469; */ +"CAPI Settings" = "CAPI Podešavanja"; + +/* prefs.py: Configuration - Enable or disable the Fleet Carrier CAPI calls; In files: prefs.py:475; */ +"Enable Fleetcarrier CAPI Queries" = "Aktiviraj Fleetcarrier CAPIU Upite"; + +/* prefs.py: Hotkey/Shortcut settings prompt on OSX; In files: prefs.py:490; */ "Keyboard shortcut" = "Skraćenica"; -/* 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" = "Skraćenica"; -/* 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} da bi ste koristili skraćenice"; -/* 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} traži dozvolu da koristi skraćenice"; -/* 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" = "Otvori sistemska podešavanja"; -/* 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 kada 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" = "Zvučni efekat"; -/* 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" = "Isključi automatsko proveravanje izmena aplikacije za vreme igranja"; -/* 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" = "Željeni web sajtovi"; -/* 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" = "Koristi alternativni URL metod"; -/* 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" = "Log Nivo"; -/* 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: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "Podešavanja privatnosti za osnovni pogled"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "Ukloni ime privatne grupe iz osnovnog pogleda"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "Ukloni ime kapetana iz višečlane posade"; -/* prefs.py: Preferences privacy tab title; In files: prefs.py:696; */ +/* prefs.py: Preferences privacy tab title; In files: prefs.py:703; */ "Privacy" = "Privatnost"; -/* 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" = "Normalan 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" = "Označeni 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" = "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" = "Tamno"; -/* 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" = "Transparentno"; -/* 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" = "Procenat UI skaliranja"; -/* 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 znači podrazumevano{CR}Restart je potreban{CR}da bi se promene primenile!"; -/* 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" = "Prozirnost glavnog prozora"; -/* 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 znači potpuno neprozirno.{CR}Prozor se osvežava u realnom vremenu."; -/* 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" = "Minimizuj u sistemsku paletu (SysTray)"; -/* 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" = "Izgled"; -/* 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" = "Folder za dodatke (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" = "Otvori"; -/* 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: Možete deaktivirati dodatak (plugin) dodavanjem{CR}'{EXT}' na ime njegovog foldera"; -/* 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" = "Aktivirani dodaci (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:" = "Pluginovi bez podrške za 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" = "Informacije o migraciji dodataka (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" = "Deaktivirani dodaci (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" = "Pozajmica"; -/* stats.py: Top rank; In files: stats.py:65; */ +/* stats.py: Top rank; In files: stats.py:63; */ "Elite" = "Elite"; -/* stats.py: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Elite I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Elite II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Elite III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Elite IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Elite V"; -/* stats.py: Ranking; In files: stats.py:76; */ +/* stats.py: Ranking; In files: stats.py:74; */ "Combat" = "Borba (Combat)"; -/* stats.py: Ranking; In files: stats.py:77; */ +/* stats.py: Ranking; In files: stats.py:75; */ "Trade" = "Trgovina (Trade)"; -/* stats.py: Ranking; In files: stats.py:78; */ +/* stats.py: Ranking; In files: stats.py:76; */ "Explorer" = "Istraživanje (Explorer)"; -/* stats.py: Ranking; In files: stats.py:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "Mercenary"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "Exobiologist"; -/* 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" = "Imperija"; -/* 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: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "Mostly Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Rookie"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Soldier"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Gunslinger"; -/* stats.py: Mercenary rank; In files: stats.py:129; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ "Warrior" = "Warrior"; -/* stats.py: Mercenary rank; In files: stats.py:131; */ +/* stats.py: Mercenary rank; In files: stats.py:129; */ "Deadeye" = "Deadeye"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:135; */ +/* stats.py: Exobiologist rank; In files: stats.py:133; */ "Mostly Directionless" = "Mostly Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:136; */ +/* stats.py: Exobiologist rank; In files: stats.py:134; */ "Compiler" = "Compiler"; -/* stats.py: Exobiologist rank; In files: stats.py:137; */ +/* stats.py: Exobiologist rank; In files: stats.py:135; */ "Collector" = "Collector"; -/* stats.py: Exobiologist rank; In files: stats.py:138; */ +/* stats.py: Exobiologist rank; In files: stats.py:136; */ "Cataloguer" = "Cataloguer"; -/* stats.py: Exobiologist rank; In files: stats.py:139; */ +/* stats.py: Exobiologist rank; In files: stats.py:137; */ "Taxonomist" = "Taxonomist"; -/* stats.py: Exobiologist rank; In files: stats.py:140; */ +/* stats.py: Exobiologist rank; In files: stats.py:138; */ "Ecologist" = "Ecologist"; -/* stats.py: Exobiologist rank; In files: stats.py:141; */ +/* stats.py: Exobiologist rank; In files: stats.py:139; */ "Geneticist" = "Geneticist"; -/* 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" = "Rejting 1"; -/* stats.py: Power rank; In files: stats.py:196; */ +/* stats.py: Power rank; In files: stats.py:194; */ "Rating 2" = "Rejting 2"; -/* stats.py: Power rank; In files: stats.py:197; */ +/* stats.py: Power rank; In files: stats.py:195; */ "Rating 3" = "Rejting 3"; -/* stats.py: Power rank; In files: stats.py:198; */ +/* stats.py: Power rank; In files: stats.py:196; */ "Rating 4" = "Rejting 4"; -/* stats.py: Power rank; In files: stats.py:199; */ +/* stats.py: Power rank; In files: stats.py:197; */ "Rating 5" = "Rejting 5"; -/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "Status: Još uvek nije poznato ime vašeg komandira"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "Status: Još uvek nema CAPI podataka"; -/* 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" = "Brodovi"; diff --git a/L10n/sv-SE.strings b/L10n/sv-SE.strings index 8bc2adcc..fa6ad247 100644 --- a/L10n/sv-SE.strings +++ b/L10n/sv-SE.strings @@ -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"; diff --git a/L10n/uk.strings b/L10n/uk.strings index b9f0b914..3791318c 100644 --- a/L10n/uk.strings +++ b/L10n/uk.strings @@ -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" = "Кораблі"; diff --git a/L10n/zh-Hans.strings b/L10n/zh-Hans.strings index fee797f1..d77b8184 100644 --- a/L10n/zh-Hans.strings +++ b/L10n/zh-Hans.strings @@ -1,746 +1,740 @@ /* 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 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" = "无"; - -/* 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}"; - -/* 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" = "自动"; - -/* 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" = "普通版"; - -/* 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" = "测试版"; - -/* 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='" = "设置链接以使用 coriolis.io 的飞船配置。注意,链接必须以 /import?data= 结尾"; - -/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: load.py:69; coriolis.py:75; */ -"Normal URL" = "普通版链接"; - -/* coriolis.py: Generic 'Reset' button label; In files: load.py:71; load.py:78; coriolis.py:78; coriolis.py:87; */ -"Reset" = "重置"; - -/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: load.py:76; coriolis.py:84; */ -"Beta URL" = "测试版链接"; - -/* In files: load.py:83; */ -"Override Beta/Normal selection" = "覆盖模式选项"; - -/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: load.py:120; coriolis.py:134; */ -"Invalid Coriolis override mode!" = "无效的 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." = "EDDB Journal Processing 已禁用。请查看诊断日志。"; - -/* eddn.py: Killswitch disabled EDDN; In files: load.py:756; eddn.py:1233; */ -"EDDN journal handler disabled. See Log." = "EDDN Journal Handler 已禁用。请查看诊断日志。"; - -/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: load.py:346; edsm.py:402; */ -"EDSM Handler disabled. See Log." = "EDSM Handler 已禁用。请查看诊断日志。"; - -/* inara.py: INARA support disabled via killswitch; In files: load.py:331; inara.py:341; */ -"Inara disabled. See Log." = "Inara 已禁用。请查看诊断日志。"; - -/* 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:没有指挥官数据"; - -/* coriolis.py: Settings>Coriolis: Label for selection of using Normal, Beta or 'auto' Coriolis URL; In files: coriolis.py:94; */ -"Override Beta/Normal Selection" = "覆盖模式选项"; - -/* eddn.py: EDDN has banned this version of our client; In files: eddn.py:334; */ -"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN 错误:EDDN 禁止了此旧版本的 EDMC 应用。请更新应用。"; - -/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:340; */ -"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN 错误:数据有效性检查失败。可能是 EDMC 应用版本过旧,请查看诊断日志。"; - -/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:345; */ -"EDDN Error: Returned {STATUS} status code" = "EDDN 错误:返回错误代码 {STATUS}"; - -/* eddn.py: No 'Route' found in NavRoute.json file; In files: eddn.py:971; */ -"No 'Route' array in NavRoute.json contents" = "NavRoute.json 文件中没有“Route”数组"; - -/* 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: ED Journal file location appears to be in error; In files: EDMarketConnector.py:815; */ -"Error: Check E:D journal file location" = "错误:请检查 E:D 日志文件位置"; - -/* 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: CAPI queries aborted because Cmdr name is unknown; In files: EDMarketConnector.py:961; */ -"CAPI query aborted: Cmdr name unknown" = "CAPI 访问中止:指挥官名称未知"; - -/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:967; */ -"CAPI query aborted: Game mode unknown" = "CAPI 访问中止:游戏模式未知"; - -/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:973; */ -"CAPI query aborted: Current system unknown" = "CAPI 访问中止:现星系名称未知"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:979; */ -"CAPI query aborted: In other-ship multi-crew" = "CAPI 访问中止:正在他人飞船上进行多人共乘 (multi-crew)"; - -/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:985; */ -"CAPI query aborted: CQC (Arena) detected" = "CAPI 访问中止:检测到 CQC (Arena) 正在运行"; - -/* 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: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1176; */ -"Frontier CAPI server error" = "Frontier CAPI 服务器错误"; - -/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1182; */ -"CAPI: Refreshing access token..." = "CAPI:获取新的访问令牌中…"; - -/* 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,详情请见 {FILE} > {SETTINGS} > {PLUGINS}。请检查上述插件是否有可用的更新,若没有,则应与插件的开发者就 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 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" = "错误:Frontier CAPI 无响应"; -/* 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" = "错误:Frontier 服务器繁忙"; -/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:253; */ +/* companion.py: Commander is docked at an EDO settlement, got out and back in, we forgot the station; In files: companion.py:261; */ "Docked but unknown station: EDO Settlement?" = "已靠站但站点未知:可能是 ED: Odyssey 的地面设施?"; -/* 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!" = "错误: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" = "错误:无法获取令牌"; -/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:797; */ +/* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "Frontier CAPI 下线维护"; -/* 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"; -/* 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: ED Journal file location appears to be in error; In files: EDMarketConnector.py:906; */ +"Error: Check E:D journal file location" = "错误:请检查 E:D 日志文件位置"; + +/* 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: CAPI queries aborted because Cmdr name is unknown; EDMarketConnector.py: CAPI fleetcarrier query aborted because Cmdr name is unknown; In files: EDMarketConnector.py:1077; EDMarketConnector.py:1164; */ +"CAPI query aborted: Cmdr name unknown" = "CAPI 访问中止:指挥官名称未知"; + +/* EDMarketConnector.py: CAPI queries aborted because game mode unknown; In files: EDMarketConnector.py:1083; */ +"CAPI query aborted: Game mode unknown" = "CAPI 访问中止:游戏模式未知"; + +/* EDMarketConnector.py: CAPI queries aborted because current star system name unknown; In files: EDMarketConnector.py:1095; */ +"CAPI query aborted: Current system unknown" = "CAPI 访问中止:现星系名称未知"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in multi-crew on other Cmdr's ship; In files: EDMarketConnector.py:1101; */ +"CAPI query aborted: In other-ship multi-crew" = "CAPI 访问中止:正在他人飞船上进行多人共乘 (multi-crew)"; + +/* EDMarketConnector.py: CAPI queries aborted because player is in CQC (Arena); In files: EDMarketConnector.py:1107; */ +"CAPI query aborted: CQC (Arena) detected" = "CAPI 访问中止:检测到 CQC (Arena) 正在运行"; + +/* 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: Frontier CAPI server error when fetching data; In files: EDMarketConnector.py:1384; */ +"Frontier CAPI server error" = "Frontier CAPI 服务器错误"; + +/* EDMarketConnector.py: Frontier CAPI Access Token expired, trying to get a new one; In files: EDMarketConnector.py:1390; */ +"CAPI: Refreshing access token..." = "CAPI:获取新的访问令牌中…"; + +/* 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,详情请见 {FILE} > {SETTINGS} > {PLUGINS}。请检查上述插件是否有可用的更新,若没有,则应与插件的开发者就 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; */ +/* 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" = "自动"; + +/* 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" = "普通版"; + +/* 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" = "测试版"; + +/* 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='" = "设置链接以使用 coriolis.io 的飞船配置。注意,链接必须以 /import?data= 结尾"; + +/* coriolis.py: Settings>Coriolis: Label for 'NOT alpha/beta game version' URL; In files: coriolis.py:97; */ +"Normal URL" = "普通版链接"; + +/* coriolis.py: Generic 'Reset' button label; In files: coriolis.py:100; coriolis.py:109; */ +"Reset" = "重置"; + +/* coriolis.py: Settings>Coriolis: Label for 'alpha/beta game version' URL; In files: coriolis.py:106; */ +"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" = "覆盖模式选项"; + +/* coriolis.py: Settings>Coriolis - invalid override mode found; In files: coriolis.py:156; */ +"Invalid Coriolis override mode!" = "无效的 Coriolis 覆盖模式!"; + +/* eddb.py: Journal Processing disabled due to an active killswitch; In files: eddb.py:179; */ +"EDDB Journal processing disabled. See Log." = "EDDB Journal Processing 已禁用。请查看诊断日志。"; + +/* 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: EDDN has banned this version of our client; In files: eddn.py:576; */ +"EDDN Error: EDMC is too old for EDDN. Please update." = "EDDN 错误:EDDN 禁止了此旧版本的 EDMC 应用。请更新应用。"; + +/* eddn.py: EDDN returned an error that indicates something about what we sent it was wrong; In files: eddn.py:582; */ +"EDDN Error: Validation Failed (EDMC Too Old?). See Log" = "EDDN 错误:数据有效性检查失败。可能是 EDMC 应用版本过旧,请查看诊断日志。"; + +/* eddn.py: EDDN returned some sort of HTTP error, one we didn't expect. {STATUS} contains a number; In files: eddn.py:587; */ +"EDDN Error: Returned {STATUS} status code" = "EDDN 错误:返回错误代码 {STATUS}"; + +/* 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: Killswitch disabled EDDN; In files: eddn.py:2178; */ +"EDDN journal handler disabled. See Log." = "EDDN Journal Handler 已禁用。请查看诊断日志。"; + +/* 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 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" = "无"; + +/* edsm.py: EDSM plugin - Journal handling disabled by killswitch; In files: edsm.py:516; */ +"EDSM Handler disabled. See Log." = "EDSM Handler 已禁用。请查看诊断日志。"; + +/* 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 support disabled via killswitch; In files: inara.py:395; */ +"Inara disabled. See Log." = "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" = "若链接过长无法打开,请勾选此项"; -/* 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: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:683; */ +/* prefs.py: UI elements privacy section header in privacy tab of preferences; In files: prefs.py:690; */ "Main UI privacy options" = "用户界面隐私选项"; -/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:688; */ +/* prefs.py: Hide private group owner name from UI checkbox; In files: prefs.py:695; */ "Hide private group name in UI" = "在用户界面中隐藏私人组 (private group) 名称"; -/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:692; */ +/* prefs.py: Hide multicrew captain name from main UI checkbox; In files: prefs.py:699; */ "Hide multi-crew captain name" = "在用户界面中隐藏多人共乘 (multi-crew) 时的舰长名称"; -/* 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" = "Elite"; -/* stats.py: Top rank +1; In files: stats.py:66; */ +/* stats.py: Top rank +1; In files: stats.py:64; */ "Elite I" = "Elite I"; -/* stats.py: Top rank +2; In files: stats.py:67; */ +/* stats.py: Top rank +2; In files: stats.py:65; */ "Elite II" = "Elite II"; -/* stats.py: Top rank +3; In files: stats.py:68; */ +/* stats.py: Top rank +3; In files: stats.py:66; */ "Elite III" = "Elite III"; -/* stats.py: Top rank +4; In files: stats.py:69; */ +/* stats.py: Top rank +4; In files: stats.py:67; */ "Elite IV" = "Elite IV"; -/* stats.py: Top rank +5; In files: stats.py:70; */ +/* stats.py: Top rank +5; In files: stats.py:68; */ "Elite V" = "Elite V"; -/* 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:79; */ +/* stats.py: Ranking; In files: stats.py:77; */ "Mercenary" = "佣兵等级"; -/* stats.py: Ranking; In files: stats.py:80; */ +/* stats.py: Ranking; In files: stats.py:78; */ "Exobiologist" = "生物学者等级"; -/* stats.py: Ranking; In files: stats.py:81; */ +/* stats.py: Ranking; In files: stats.py:79; */ "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" = "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: Mercenary rank; In files: stats.py:124; */ +/* stats.py: Mercenary rank; In files: stats.py:122; */ "Defenceless" = "Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:125; */ +/* stats.py: Mercenary rank; In files: stats.py:123; */ "Mostly Defenceless" = "Mostly Defenceless"; -/* stats.py: Mercenary rank; In files: stats.py:126; */ +/* stats.py: Mercenary rank; In files: stats.py:124; */ "Rookie" = "Rookie"; -/* stats.py: Mercenary rank; In files: stats.py:127; */ +/* stats.py: Mercenary rank; In files: stats.py:125; */ "Soldier" = "Soldier"; -/* stats.py: Mercenary rank; In files: stats.py:128; stats.py:130; */ +/* stats.py: Mercenary rank; In files: stats.py:126; stats.py:128; */ "Gunslinger" = "Gunslinger"; -/* stats.py: Mercenary rank; In files: stats.py:129; */ +/* stats.py: Mercenary rank; In files: stats.py:127; */ "Warrior" = "Warrior"; -/* stats.py: Mercenary rank; In files: stats.py:131; */ +/* stats.py: Mercenary rank; In files: stats.py:129; */ "Deadeye" = "Deadeye"; -/* stats.py: Exobiologist rank; In files: stats.py:134; */ +/* stats.py: Exobiologist rank; In files: stats.py:132; */ "Directionless" = "Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:135; */ +/* stats.py: Exobiologist rank; In files: stats.py:133; */ "Mostly Directionless" = "Mostly Directionless"; -/* stats.py: Exobiologist rank; In files: stats.py:136; */ +/* stats.py: Exobiologist rank; In files: stats.py:134; */ "Compiler" = "Compiler"; -/* stats.py: Exobiologist rank; In files: stats.py:137; */ +/* stats.py: Exobiologist rank; In files: stats.py:135; */ "Collector" = "Collector"; -/* stats.py: Exobiologist rank; In files: stats.py:138; */ +/* stats.py: Exobiologist rank; In files: stats.py:136; */ "Cataloguer" = "Cataloguer"; -/* stats.py: Exobiologist rank; In files: stats.py:139; */ +/* stats.py: Exobiologist rank; In files: stats.py:137; */ "Taxonomist" = "Taxonomist"; -/* stats.py: Exobiologist rank; In files: stats.py:140; */ +/* stats.py: Exobiologist rank; In files: stats.py:138; */ "Ecologist" = "Ecologist"; -/* stats.py: Exobiologist rank; In files: stats.py:141; */ +/* stats.py: Exobiologist rank; In files: stats.py:139; */ "Geneticist" = "Geneticist"; -/* 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: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:317; */ +/* stats.py: Current commander unknown when trying to use 'File' > 'Status'; In files: stats.py:315; */ "Status: Don't yet know your Commander name" = "状态:暂时未知你的指挥官名称"; -/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:325; */ +/* stats.py: No Frontier CAPI data yet when trying to use 'File' > 'Status'; In files: stats.py:323; */ "Status: No CAPI data yet" = "状态:暂无 CAPI 数据"; -/* 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" = "所有飞船"; From 5b9464b8c4e36f8ee70ea492a77e61ccc32700ea Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 17 Jan 2023 17:05:30 +0000 Subject: [PATCH 251/257] Pre-Release 5.8.0-rc1: appversion & changelog --- ChangeLog.md | 202 +++++++++++++++++++++++++++++++++++++++++++++ config/__init__.py | 2 +- 2 files changed, 203 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index c7b24dae..8081cb0d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -27,6 +27,208 @@ produce the Windows executables and installer. --- +Pre-Release 5.8.0-rc1 +=== + +* This release, and all future ones, now create two additional archive files + in the GitHub release: + + 1. `EDMarketConnector-release-.zip` + 2. `EDMarketConnector-release-.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_.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...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_`, 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 diff --git a/config/__init__.py b/config/__init__.py index a2f05062..aa4a927f 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -52,7 +52,7 @@ appcmdname = 'EDMC' # # Major.Minor.Patch(-prerelease)(+buildmetadata) # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() -_static_appversion = '5.7.1-alpha0' +_static_appversion = '5.8.0-rc1' _cached_version: Optional[semantic_version.Version] = None copyright = '© 2015-2019 Jonathan Harris, 2020-2023 EDCD' From fad4690200bb7c1e477b84332a39991b34ff363c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 17 Jan 2023 18:14:29 +0000 Subject: [PATCH 252/257] Build-exe: pkg_resources now has .vendor/platformdirs as well For now we can manually add this to `packages`. Will open an issue with py2exe. --- Build-exe-and-msi.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Build-exe-and-msi.py b/Build-exe-and-msi.py index 33f95a5b..bc0ec600 100644 --- a/Build-exe-and-msi.py +++ b/Build-exe-and-msi.py @@ -84,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 ], From 70f5f30f1caae0040105f17edad5faf355651aba Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 17 Jan 2023 18:25:16 +0000 Subject: [PATCH 253/257] Pre-Release 5.8.0-rc2: appversion & changelog --- ChangeLog.md | 7 +++++++ config/__init__.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 8081cb0d..f6cced93 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -27,6 +27,13 @@ produce the Windows executables and installer. --- +Pre-Release 5.8.0-rc2 +=== +An issue with building the Windows executable has been found and fixed. This +release is otherwise identical to 5.8.0-rc1. + +--- + Pre-Release 5.8.0-rc1 === diff --git a/config/__init__.py b/config/__init__.py index aa4a927f..bbfa95c3 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -52,7 +52,7 @@ appcmdname = 'EDMC' # # Major.Minor.Patch(-prerelease)(+buildmetadata) # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() -_static_appversion = '5.8.0-rc1' +_static_appversion = '5.8.0-rc2' _cached_version: Optional[semantic_version.Version] = None copyright = '© 2015-2019 Jonathan Harris, 2020-2023 EDCD' From 9e57bda8f86dc625a2e11b1f088ac3452d4e014c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 17 Jan 2023 18:46:45 +0000 Subject: [PATCH 254/257] requirements: We also need `charset_normalizer` now --- requirements.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/requirements.txt b/requirements.txt index 44d3f92d..069eb227 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,8 @@ certifi==2022.12.7 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' From 9efcc19c73348c2e1e704ecc56cf43a5b0e5c01a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Tue, 17 Jan 2023 18:57:56 +0000 Subject: [PATCH 255/257] Pre-Release 5.8.0-rc3: appversion & changelog --- ChangeLog.md | 7 +++++++ config/__init__.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index f6cced93..e3444d4e 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -27,6 +27,13 @@ produce the Windows executables and installer. --- +Pre-Release 5.8.0-rc3 +=== +A further issue with building the Windows executable has been found and fixed. +This release is otherwise identical to 5.8.0-rc1 & -rc2 combined. + +--- + Pre-Release 5.8.0-rc2 === An issue with building the Windows executable has been found and fixed. This diff --git a/config/__init__.py b/config/__init__.py index bbfa95c3..0600f689 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -52,7 +52,7 @@ appcmdname = 'EDMC' # # Major.Minor.Patch(-prerelease)(+buildmetadata) # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() -_static_appversion = '5.8.0-rc2' +_static_appversion = '5.8.0-rc3' _cached_version: Optional[semantic_version.Version] = None copyright = '© 2015-2019 Jonathan Harris, 2020-2023 EDCD' From fd0c9c505bdb11e023de6e8bfae7a5d116dff322 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 20 Jan 2023 11:33:43 +0000 Subject: [PATCH 256/257] Release: appversion & changelog * This includes adding a mention of Windows 8.1 EOL to the header. --- ChangeLog.md | 30 +++++++++++++++--------------- config/__init__.py | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index e3444d4e..e94b376f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -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,22 +34,15 @@ produce the Windows executables and installer. --- -Pre-Release 5.8.0-rc3 +Release 5.8.0 === -A further issue with building the Windows executable has been found and fixed. -This release is otherwise identical to 5.8.0-rc1 & -rc2 combined. +This release is essentially the same as 5.8.0-rc3 with only the version and +this changelog updated. ---- - -Pre-Release 5.8.0-rc2 -=== -An issue with building the Windows executable has been found and fixed. This -release is otherwise identical to 5.8.0-rc1. - ---- - -Pre-Release 5.8.0-rc1 -=== +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: diff --git a/config/__init__.py b/config/__init__.py index 0600f689..da573fb1 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -52,7 +52,7 @@ appcmdname = 'EDMC' # # Major.Minor.Patch(-prerelease)(+buildmetadata) # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() -_static_appversion = '5.8.0-rc3' +_static_appversion = '5.8.0' _cached_version: Optional[semantic_version.Version] = None copyright = '© 2015-2019 Jonathan Harris, 2020-2023 EDCD' From ee5931db4a249eb343b354f7eea912d84db01b32 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 20 Jan 2023 11:46:57 +0000 Subject: [PATCH 257/257] windows-build: Revert WinSparkle DLL to 32-bit, not 64-bit Some testing of 64-bit builds must have accidentally left this in place. --- .github/workflows/windows-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 3f306884..d28fca90 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -108,7 +108,7 @@ jobs: run: | Invoke-Webrequest -UseBasicParsing https://github.com/vslavik/winsparkle/releases/download/v0.7.0/WinSparkle-0.7.0.zip -OutFile out.zip Expand-Archive out.zip - Move-Item 'out\WinSparkle-0.7.0\x64\Release\*' '.\' + Move-Item 'out\WinSparkle-0.7.0\Release\*' '.\' - name: Build EDMC run: |