This currently only affects system colonisation ships, which have '$EXT_PANEL_ColonisationShip;' in their StationName
entries in the journal. Other strings may need to be added in future.
Fixes#2404
diff --git a/L10n/en.template b/L10n/en.template
index faac3259..f670e39c 100644
--- a/L10n/en.template
+++ b/L10n/en.template
@@ -839,3 +839,9 @@
/* edastro_core.py: Settings>EDAstro - Label on checkbox for 'send data'; */
"Send data to EDAstro" = "Send data to EDAstro";
+
+/* common_coreutils.py: Colonisation ship name, with title; In files: common_coreutils.py:81:81 */
+"System Colonisation Ship {NAME}" = "System Colonisation Ship {NAME}";
+
+/* common_coreutils.py: Unidentified colonisation ship; In files: common_coreutils.py:84:84 */
+"System Colonisation Ship" = "System Colonisation Ship";
diff --git a/plugins/common_coreutils.py b/plugins/common_coreutils.py
index 6b90d4dc..a488de46 100644
--- a/plugins/common_coreutils.py
+++ b/plugins/common_coreutils.py
@@ -29,6 +29,7 @@ import gzip
import io
import json
import os
+import re
import myNotebook as nb # noqa: N813
from EDMCLogging import get_main_logger
from companion import CAPIData
@@ -47,6 +48,49 @@ SEPY = 10 # seperator line spacing
STATION_UNDOCKED = '×' # "Station" name to display when not docked = U+00D7
+# Known colonisation ship names match one of the following:
+# "$EXT_PANEL_ColonisationShip;"
+# "$EXT_PANEL_ColonisationShip; <ship name>" with "<ship name>" being eg; "Okawara Horizons"
+# "$EXT_PANEL_ColonisationShip:#index=<number>;"
+# "$EXT_PANEL_ColonisationShip:#index=<number>; <ship name>"
+_RE_COLONISATION_SHIP = re.compile(r'\$EXT_PANEL_ColonisationShip(?::#index=(\d+))?;(?: (.+))?')
+
+
+def localised_name(value: str | None) -> str | None:
+ """
+ Handle localisation of strings in places like station names.
+
+ This is currently an issue for system colonisation ships that have a station name along the
+ lines of "$EXT_PANEL_ColonisationShip; Okawara Horizons" when written to the journal, but would
+ be better displayed as "System Colonisation Ship Okawara Horizona" (or other appropriately
+ localised equivalent).
+
+ If no (known) localisable strings are present, the input will be returned unmodified.
+
+ :param value: The non-localised string.
+ :return: The localised string, or None if the input was None.
+ """
+ if value is None:
+ return None
+
+ colonisation_ship_match = _RE_COLONISATION_SHIP.match(value)
+ if colonisation_ship_match:
+ ship_index = colonisation_ship_match.group(1)
+ ship_name = colonisation_ship_match.group(2)
+ # Use the ship's index as its name if no name was provided.
+ ship_id = ship_name or ship_index
+
+ if ship_id:
+ # LANG: Colonisation ship name, with title
+ value = tr.tl("System Colonisation Ship {NAME}").format(NAME=ship_id)
+
+ else:
+ # LANG: Unidentified colonisation ship
+ value = tr.tl("System Colonisation Ship")
+
+ return value
+
+
def plugin_start3(plugin_dir: str) -> str:
"""
Start the plugin.
@@ -121,7 +165,7 @@ def station_link_common(data: CAPIData, this):
:param this: The module global from the calling module.
"""
if data['commander']['docked'] or this.on_foot and this.station_name:
- this.station_link['text'] = this.station_name
+ this.station_link['text'] = localised_name(this.station_name)
elif data['lastStarport']['name'] and data['lastStarport']['name'] != "":
this.station_link['text'] = STATION_UNDOCKED
else:
@@ -163,12 +207,14 @@ def station_name_setter_common(this):
:param this: The module global from the calling module.
"""
to_set: str = cast(str, this.station_name)
+
if not to_set:
if this.system_population is not None and this.system_population > 0:
to_set = STATION_UNDOCKED
else:
to_set = ''
+ to_set = str(localised_name(to_set))
this.station_link['text'] = to_set
diff --git a/plugins/edsm.py b/plugins/edsm.py
index e1e6b168..902e248b 100644
--- a/plugins/edsm.py
+++ b/plugins/edsm.py
@@ -43,7 +43,7 @@ from ttkHyperlinkLabel import HyperlinkLabel
from l10n import translations as tr
from plugins.common_coreutils import (api_keys_label_common, PADX, PADY, BUTTONX, SEPY, BOXY, STATION_UNDOCKED,
show_pwd_var_common, station_link_common, this_format_common,
- cmdr_data_initial_common)
+ cmdr_data_initial_common, localised_name)
# TODO:
@@ -543,7 +543,7 @@ entry: {entry!r}'''
to_set = ''
if this.station_link:
- this.station_link['text'] = to_set
+ this.station_link['text'] = localised_name(to_set)
this.station_link['url'] = station_url(str(this.system_name), str(this.station_name))
this.station_link.update_idletasks()
Mostly related to adjusting `if sys.platform == 'win32'` logic so things that are only defined on win32 platforms don't
cause issues on other platforms.
diff --git a/PLUGINS.md b/PLUGINS.md
index 6fd20ef9..71aaec7a 100644
--- a/PLUGINS.md
+++ b/PLUGINS.md
@@ -163,6 +163,19 @@ circular imports.
For an example of how this is done, look at the code in `plugins/common_coreutils.py`
and the usage of these functions in other core plugins.
+Plugins may import additional code modules from `load.py` in the usual way. Note
+that using an import statement like `import my_module` or `from my_module import
+foo` will only import one module with that name **across all plugins**. This can
+be used to create a shared library used by several plugins if used carefully,
+but may create a conflict if another plugin also has a module of the same name
+containing different code. For example if two plugins both contain a
+`widgets.py` file and both do `import widgets`, only one of the two modules will
+actually be imported.
+
+To avoid this issue, use a relative import statement such as `import .widgets`
+or `from .widgets import foo` to ensure that the module is loaded from the
+current plugin, even if the name conflicts with another plugin's code.
+
---
## Logging
Fixes a race identified where long plugin init times can result in
the following error being thrown in the journal monitor thread,
requiring a preferences reload to have journals continuing to be
processed:
```
Exception in thread Journal worker:
Traceback (most recent call last):
File "/home/testing/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 1045, in _bootstrap_inner
self.run()
File "/home/testing/.pyenv/versions/3.11.9/lib/python3.11/threading.py", line 982, in run
self._target(*self._args, **self._kwargs)
File "/home/testing/gitstuff/EDMarketConnector/monitor.py", line 461, in worker
self.root.event_generate('<<JournalEvent>>', when="tail")
File "/home/testing/.pyenv/versions/3.11.9/lib/python3.11/tkinter/__init__.py", line 1933, in event_generate
self.tk.call(args)
RuntimeError: main thread is not in main loop
```