Skip to content

Commit 8b64f5e

Browse files
authored
Localize UnsupportedSystemError messages (#4255)
1 parent b2bfac8 commit 8b64f5e

4 files changed

Lines changed: 58 additions & 6 deletions

File tree

music_assistant/helpers/util.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,11 @@ def verify_system_meets_requirements(
153153
:raises UnsupportedSystemError: If the system does not meet the requirements.
154154
"""
155155
if shortfall := _resource_shortfall(min_memory_gb=min_memory_gb, min_cpu_cores=min_cpu_cores):
156+
message, translation_key, translation_args = shortfall
156157
raise UnsupportedSystemError(
157-
f"This system does not meet the minimal requirements for {feature_name}: {shortfall}"
158+
f"This system does not meet the minimal requirements for {feature_name}: {message}",
159+
translation_key=translation_key,
160+
translation_args=[feature_name, *translation_args],
158161
)
159162
if require_ml_inference:
160163
verify_cpu_supports_ml_inference()
@@ -178,22 +181,32 @@ def system_meets_requirements(
178181
return _resource_shortfall(min_memory_gb=min_memory_gb, min_cpu_cores=min_cpu_cores) is None
179182

180183

181-
def _resource_shortfall(*, min_memory_gb: float, min_cpu_cores: int) -> str | None:
184+
def _resource_shortfall(
185+
*, min_memory_gb: float, min_cpu_cores: int
186+
) -> tuple[str, str, list[Any]] | None:
182187
"""
183-
Return why the host falls short of the RAM/CPU thresholds, or None if it meets them.
188+
Return an unmet RAM/CPU threshold as (message, translation_key, translation_args), or None.
189+
190+
translation_args exclude the feature name, which the caller prepends.
184191
185192
:param min_memory_gb: Minimum total system RAM in GB (0 disables the check).
186193
:param min_cpu_cores: Minimum CPU core count (0 disables the check).
187194
"""
188195
cpu_cores = os.process_cpu_count() or os.cpu_count() or 1
189196
if min_cpu_cores and cpu_cores < min_cpu_cores:
190-
return f"at least {min_cpu_cores} CPU cores are required ({cpu_cores} detected)."
197+
return (
198+
f"at least {min_cpu_cores} CPU cores are required ({cpu_cores} detected).",
199+
"errors.unsupported_system_cpu_cores",
200+
[min_cpu_cores, cpu_cores],
201+
)
191202
total_memory_gb = get_total_system_memory()
192203
# get_total_system_memory() returns 0.0 when the platform cannot report memory
193204
# (e.g. Windows); treat that as unknown and pass rather than block on a guess.
194205
if min_memory_gb and total_memory_gb and total_memory_gb < min_memory_gb:
195206
return (
196-
f"at least {min_memory_gb:.0f}GB of RAM is required ({total_memory_gb:.1f}GB detected)."
207+
f"at least {min_memory_gb:.0f}GB of RAM is required ({total_memory_gb:.1f}GB detected).",
208+
"errors.unsupported_system_memory",
209+
[f"{min_memory_gb:.0f}", f"{total_memory_gb:.1f}"],
197210
)
198211
return None
199212

@@ -215,7 +228,8 @@ def verify_cpu_supports_ml_inference() -> None:
215228
"On-device audio analysis requires a CPU with AVX2 support "
216229
"(Intel Haswell / AMD Zen or newer). This CPU does not support AVX2. "
217230
"If you are running in a virtual machine (e.g. Proxmox), changing the "
218-
"CPU type to 'host' may expose AVX2 to the guest."
231+
"CPU type to 'host' may expose AVX2 to the guest.",
232+
translation_key="errors.unsupported_system_avx2",
219233
)
220234

221235

music_assistant/strings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,10 @@
864864
"audio_error": "An error occurred while processing audio.",
865865
"queue_empty": "The queue is empty.",
866866
"unsupported_feature": "This feature is not supported.",
867+
"unsupported_system": "This is not supported on this system.",
868+
"unsupported_system_cpu_cores": "This system does not meet the minimal requirements for {0}: at least {1} CPU cores are required ({2} detected).",
869+
"unsupported_system_memory": "This system does not meet the minimal requirements for {0}: at least {1}GB of RAM is required ({2}GB detected).",
870+
"unsupported_system_avx2": "On-device audio analysis requires a CPU with AVX2 support (Intel Haswell / AMD Zen or newer). This CPU does not support AVX2. If you are running in a virtual machine (e.g. Proxmox), changing the CPU type to 'host' may expose AVX2 to the guest.",
867871
"player_unavailable": "The player is not available.",
868872
"player_command_failed": "The command to the player failed.",
869873
"invalid_command": "Invalid or unsupported command.",

music_assistant/translations/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,10 @@
279279
"common.errors.setup_required": "Music Assistant is not set up yet.",
280280
"common.errors.unplayable_media": "This media item cannot be played.",
281281
"common.errors.unsupported_feature": "This feature is not supported.",
282+
"common.errors.unsupported_system": "This is not supported on this system.",
283+
"common.errors.unsupported_system_avx2": "On-device audio analysis requires a CPU with AVX2 support (Intel Haswell / AMD Zen or newer). This CPU does not support AVX2. If you are running in a virtual machine (e.g. Proxmox), changing the CPU type to 'host' may expose AVX2 to the guest.",
284+
"common.errors.unsupported_system_cpu_cores": "This system does not meet the minimal requirements for {0}: at least {1} CPU cores are required ({2} detected).",
285+
"common.errors.unsupported_system_memory": "This system does not meet the minimal requirements for {0}: at least {1}GB of RAM is required ({2}GB detected).",
282286
"common.media.folder.albums.name": "Albums",
283287
"common.media.folder.artists.name": "Artists",
284288
"common.media.folder.audiobooks.name": "Audiobooks",

tests/core/test_helpers.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,36 @@ def test_verify_system_meets_requirements_ml_inference() -> None:
510510
util.verify_system_meets_requirements(feature_name="X", min_cpu_cores=4, min_memory_gb=8.0)
511511

512512

513+
def test_unsupported_system_error_translation() -> None:
514+
"""Each raise path carries the right translation key + ordered args (feature name first)."""
515+
with (
516+
patch("music_assistant.helpers.util.os.process_cpu_count", return_value=2),
517+
patch("music_assistant.helpers.util.get_total_system_memory", return_value=64.0),
518+
pytest.raises(UnsupportedSystemError) as cpu_err,
519+
):
520+
util.verify_system_meets_requirements(feature_name="Smart Fades", min_cpu_cores=4)
521+
assert cpu_err.value.translation_key == "errors.unsupported_system_cpu_cores"
522+
assert cpu_err.value.translation_args == ["Smart Fades", 4, 2]
523+
524+
with (
525+
patch("music_assistant.helpers.util.os.process_cpu_count", return_value=16),
526+
patch("music_assistant.helpers.util.get_total_system_memory", return_value=2.0),
527+
pytest.raises(UnsupportedSystemError) as mem_err,
528+
):
529+
util.verify_system_meets_requirements(feature_name="Smart Fades", min_memory_gb=8.0)
530+
assert mem_err.value.translation_key == "errors.unsupported_system_memory"
531+
assert mem_err.value.translation_args == ["Smart Fades", "8", "2.0"]
532+
533+
with (
534+
patch("music_assistant.helpers.util.platform.machine", return_value="x86_64"),
535+
patch("torch.backends.cpu.get_cpu_capability", return_value="DEFAULT"),
536+
pytest.raises(UnsupportedSystemError) as avx_err,
537+
):
538+
util.verify_cpu_supports_ml_inference()
539+
assert avx_err.value.translation_key == "errors.unsupported_system_avx2"
540+
assert avx_err.value.translation_args == []
541+
542+
513543
@pytest.mark.parametrize(
514544
("cpu_cores", "total_gb", "expected"),
515545
[

0 commit comments

Comments
 (0)