Skip to content

[Feature] Add plugin dependencies (prerequisite for third-party localization) #823

Description

@WkdXeqtr

Before Requesting

  • I found no existing issue matching my feature request
  • This request is related to Millennium, and not a request for a specific theme/addon

Describe the feature you'd like!

You said a plugin localization system could work but would need proper planning, so here it is. The short version: I want third parties to be able to ship translations for plugins they don't own, and for that a plugin needs to be able to depend on another and load after it. So dependencies come first, localization builds on top. This is the dependency design - I want your take before I write any code, and it would land in both Millennium and the PluginTemplate.

Add an optional dependencies to plugin.json - a list of internal plugin names (the same name the loader already uses), with an optional semver range since CMP_VERSION already exists:

"dependencies": ["steam-some-plugin", "another-plugin@>=1.2.0"]

On install. No auto-installing anything - same stance you took on the sidebar PR. If a plugin has missing dependencies, the installer shows a dialog listing them and lets the user install anyway or cancel. The plugin is expected to degrade gracefully if a dependency is absent.

Resolution. Check what's actually on disk, so a dependency someone installed manually counts. Three states: missing, present but disabled, present and enabled. Each dependency name is resolved to its page via the same plugin API the installer uses, shown as a link; if the lookup fails, show the raw id.

Load order. Backends already all start before any frontend, but the order among them is arbitrary, so I'd topologically sort the spawn order (cycle detection falls back to current order with a warning). Frontends have no ordering at all today since the shims are appended as async module scripts, so I'd sort them in dependency order and make injection ordered. Plus a Millennium.whenPluginReady(name) as a safety net.

openQuickAccess({ plugin }) fits here as a compatibility affordance: a plugin can deep-link into a dependency's settings panel, including from the dependency dialog.

How localization uses this (for context): a plugin ships a locales/ folder with english.json as the source of truth, plus a small helper in the SDK (same pattern as the core locale manager). A translation plugin then depends on the target and contributes its strings to a shared registry in core - it has to be in core because plugins run in isolated worlds and can't patch each other directly. The target's lookup merges its own strings with any contributed overrides. No target installed means the translation plugin is a no-op. I'm not trying to extract strings from old plugins; a plugin is localizable once it adopts the system.

A few open questions:

  • Dependencies referencing internal name with optional name@range - good, or bare names only for v1?
  • Warn-and-allow vs hard block on missing deps. I lean warn.
  • The ordered frontend loading touches the loader and shim injection - want me to take a pass at it, or own that part yourself like you did with quick access?

Anything else?

References for context:

  • Millennium.openQuickAccess({ plugin }) from the quick access work in next.
  • Version comparison already wired through the CMP_VERSION IPC in the plugin loader.
  • The core locale manager (src/typescript/frontend/utils/localization-manager.ts) as the pattern for the per-plugin helper.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions