Skip to content

Commit

Permalink
Add-on store: support localisation for installed add-ons (#15137)
Browse files Browse the repository at this point in the history
Part of #14973

Summary of the issue:
Installed add-ons do not have their display name and description localised, even if localised manifests exist for the installed add-on.

Description of user facing changes
Reinstate localisation for installed add-ons of the display name and description

Description of development approach
Fetch translated strings from the localised manifests

Testing strategy:
Ensure add-on with localisations is correctly displayed in the installed add-ons tab of the store.
Available and updatable add-ons rely on the strings to be translated when fetching from the store.
  • Loading branch information
seanbudd authored Jul 14, 2023
1 parent 384a742 commit 435f540
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 25 deletions.
31 changes: 20 additions & 11 deletions source/_addonStore/models/addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from addonHandler import ( # noqa: F401
Addon as AddonHandlerModel,
AddonBase as AddonHandlerBaseModel,
AddonManifest,
)
AddonGUICollectionT = Dict[Channel, CaseInsensitiveDict["_AddonGUIModel"]]
"""
Expand Down Expand Up @@ -110,25 +111,35 @@ def asdict(self) -> Dict[str, Any]:


@dataclasses.dataclass(frozen=True)
class AddonGUIModel(_AddonGUIModel):
class AddonManifestModel(_AddonGUIModel):
"""Can be displayed in the add-on store GUI.
May come from manifest or add-on store data.
Comes from add-on manifest.
"""
addonId: str
displayName: str
description: str
publisher: str
addonVersionName: str
channel: Channel
homepage: Optional[str]
minNVDAVersion: MajorMinorPatch
lastTestedVersion: MajorMinorPatch
_manifest: "AddonManifest"
legacy: bool = False
"""
Legacy add-ons contain invalid metadata
and should not be accessible through the add-on store.
"""

@property
def displayName(self) -> str:
return self._manifest["summary"]

@property
def description(self) -> str:
return self._manifest["description"]

@property
def publisher(self) -> str:
return self._manifest["author"]


@dataclasses.dataclass(frozen=True) # once created, it should not be modified.
class AddonStoreModel(_AddonGUIModel):
Expand Down Expand Up @@ -229,21 +240,19 @@ def _createStoreModelFromData(addon: Dict[str, Any]) -> AddonStoreModel:
)


def _createGUIModelFromManifest(addon: "AddonHandlerBaseModel") -> AddonGUIModel:
homepage = addon.manifest.get("url")
def _createGUIModelFromManifest(addon: "AddonHandlerBaseModel") -> AddonManifestModel:
homepage: Optional[str] = addon.manifest.get("url")
if homepage == "None":
# Manifest strings can be set to "None"
homepage = None
return AddonGUIModel(
return AddonManifestModel(
addonId=addon.name,
displayName=addon.manifest["summary"],
description=addon.manifest["description"],
publisher=addon.manifest["author"],
channel=Channel.EXTERNAL,
addonVersionName=addon.version,
homepage=homepage,
minNVDAVersion=MajorMinorPatch(*addon.minimumNVDAVersion),
lastTestedVersion=MajorMinorPatch(*addon.lastTestedNVDAVersion),
_manifest=addon.manifest
)


Expand Down
4 changes: 2 additions & 2 deletions source/_addonStore/models/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from .version import SupportsVersionCheck

if TYPE_CHECKING:
from .addon import AddonGUIModel # noqa: F401
from .addon import _AddonGUIModel # noqa: F401
from addonHandler import AddonsState # noqa: F401


Expand Down Expand Up @@ -144,7 +144,7 @@ class AddonStateCategory(str, enum.Enum):
"""Add-ons that are blocked from running because they are incompatible"""


def getStatus(model: "AddonGUIModel") -> Optional[AvailableAddonStatus]:
def getStatus(model: "_AddonGUIModel") -> Optional[AvailableAddonStatus]:
from addonHandler import (
state as addonHandlerState,
)
Expand Down
3 changes: 2 additions & 1 deletion source/_addonStore/models/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class SupportsVersionCheck(Protocol):
""" Examples implementing this protocol include:
- addonHandler.Addon
- addonHandler.AddonBundle
- _addonStore.models.AddonGUIModel
- _addonStore.models._AddonGUIModel
- _addonStore.models.AddonManifestModel
- _addonStore.models.AddonStoreModel
"""
minimumNVDAVersion: addonAPIVersion.AddonApiVersionT
Expand Down
4 changes: 2 additions & 2 deletions source/addonHandler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@

if TYPE_CHECKING:
from _addonStore.models.addon import ( # noqa: F401
AddonGUIModel,
AddonManifestModel,
AddonHandlerModelGeneratorT,
AddonStoreModel,
)
Expand Down Expand Up @@ -392,7 +392,7 @@ def _addonStoreData(self) -> Optional["AddonStoreModel"]:
return addonDataManager._getCachedInstalledAddonData(self.name)

@property
def _addonGuiModel(self) -> "AddonGUIModel":
def _addonGuiModel(self) -> "AddonManifestModel":
from _addonStore.models.addon import _createGUIModelFromManifest
return _createGUIModelFromManifest(self)

Expand Down
10 changes: 5 additions & 5 deletions source/gui/_addonStoreGui/controls/messageDialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import wx

import addonAPIVersion
from _addonStore.models.addon import AddonGUIModel
from _addonStore.models.addon import _AddonGUIModel
from gui.addonGui import ErrorAddonInstallDialog
from gui.message import messageBox

Expand Down Expand Up @@ -49,7 +49,7 @@ def _addButtons(self, buttonHelper: "ButtonHelper") -> None:

def _shouldProceedWhenInstalledAddonVersionUnknown(
parent: wx.Window,
addon: AddonGUIModel
addon: _AddonGUIModel
) -> bool:
# an installed add-on should have an addon Handler Model
assert addon._addonHandlerModel
Expand Down Expand Up @@ -97,7 +97,7 @@ def _shouldProceedToRemoveAddonDialog(

def _shouldInstallWhenAddonTooOldDialog(
parent: wx.Window,
addon: AddonGUIModel
addon: _AddonGUIModel
) -> bool:
incompatibleMessage = pgettext(
"addonStore",
Expand Down Expand Up @@ -126,7 +126,7 @@ def _shouldInstallWhenAddonTooOldDialog(

def _shouldEnableWhenAddonTooOldDialog(
parent: wx.Window,
addon: AddonGUIModel
addon: _AddonGUIModel
) -> bool:
incompatibleMessage = pgettext(
"addonStore",
Expand All @@ -153,7 +153,7 @@ def _shouldEnableWhenAddonTooOldDialog(
).ShowModal() == wx.YES


def _showAddonInfo(addon: AddonGUIModel) -> None:
def _showAddonInfo(addon: _AddonGUIModel) -> None:
message = [
pgettext(
"addonStore",
Expand Down
8 changes: 4 additions & 4 deletions source/gui/_addonStoreGui/viewModels/addonList.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from requests.structures import CaseInsensitiveDict

from _addonStore.models.addon import (
AddonGUIModel,
_AddonGUIModel,
)
from _addonStore.models.status import (
_StatusFilterKey,
Expand Down Expand Up @@ -86,15 +86,15 @@ class AddonListField(_AddonListFieldData, Enum):
class AddonListItemVM:
def __init__(
self,
model: AddonGUIModel,
model: _AddonGUIModel,
status: AvailableAddonStatus = AvailableAddonStatus.AVAILABLE
):
self._model: AddonGUIModel = model # read-only
self._model: _AddonGUIModel = model # read-only
self._status: AvailableAddonStatus = status # modifications triggers L{updated.notify}
self.updated = extensionPoints.Action() # Notify of changes to VM, argument: addonListItemVM

@property
def model(self) -> AddonGUIModel:
def model(self) -> _AddonGUIModel:
return self._model

@property
Expand Down

0 comments on commit 435f540

Please sign in to comment.