Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PICARD-2870: Get rid of monkeypatched gettext-related builtins #2421

Merged
merged 8 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,7 @@ min-similarity-lines=4

# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=_, N_, ngettext, gettext_attributes, pgettext_attributes,
gettext_constants, gettext_countries
additional-builtins=

# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
Expand Down
1 change: 1 addition & 0 deletions picard/acoustid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
)
from picard.const.sys import IS_WIN
from picard.file import File
from picard.i18n import N_
from picard.util import (
find_executable,
win_prefix_longpath,
Expand Down
1 change: 1 addition & 0 deletions picard/acoustid/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from PyQt6 import QtCore

from picard import log
from picard.i18n import N_
from picard.util import load_json


Expand Down
4 changes: 4 additions & 0 deletions picard/album.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
from picard.const import VARIOUS_ARTISTS_ID
from picard.dataobj import DataObject
from picard.file import File
from picard.i18n import (
N_,
gettext as _,
)
from picard.mbjson import (
medium_to_metadata,
release_group_to_metadata,
Expand Down
1 change: 1 addition & 0 deletions picard/browser/addrelease.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from PyQt6.QtCore import QCoreApplication

from picard import log
from picard.i18n import gettext as _
from picard.util import format_time
from picard.util.mbserver import build_submission_url
from picard.util.webbrowser2 import open
Expand Down
4 changes: 4 additions & 0 deletions picard/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@

from picard.config import get_config
from picard.file import File
from picard.i18n import (
N_,
gettext as _,
)
from picard.metadata import (
Metadata,
SimMatchRelease,
Expand Down
4 changes: 4 additions & 0 deletions picard/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@

from picard import log
from picard.config import get_config
from picard.i18n import (
N_,
ngettext,
)
from picard.webservice.api_helpers import MBAPIHelper


Expand Down
4 changes: 4 additions & 0 deletions picard/config_upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
DEFAULT_SCRIPT_NAME,
)
from picard.const.sys import IS_FROZEN
from picard.i18n import (
gettext as _,
gettext_constants,
)
from picard.util import unique_numbered_title
from picard.version import (
Version,
Expand Down
6 changes: 1 addition & 5 deletions picard/const/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,12 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.


import builtins
from collections import OrderedDict

from picard import PICARD_VERSION
from picard.const import appdirs
from picard.const.attributes import MB_ATTRIBUTES


# Install gettext "noop" function in case const.py gets imported directly.
builtins.__dict__['N_'] = lambda a: a
from picard.i18n import N_


# Config directory
Expand Down
2 changes: 2 additions & 0 deletions picard/const/languages.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

from picard.i18n import N_


# List of available user interface languages
UI_LANGUAGES = [
Expand Down
2 changes: 2 additions & 0 deletions picard/const/locales.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

from picard.i18n import N_


# List of alias locales
ALIAS_LOCALES = {
Expand Down
5 changes: 5 additions & 0 deletions picard/const/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

from picard.i18n import (
N_,
gettext as _,
)


# List of available scripts (character sets)
SCRIPTS = {
Expand Down
1 change: 1 addition & 0 deletions picard/coverart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
CoverArtProvider,
cover_art_providers,
)
from picard.i18n import N_
from picard.metadata import register_album_metadata_processor


Expand Down
4 changes: 4 additions & 0 deletions picard/coverart/providers/caa.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
CAA_TYPES,
translate_caa_type,
)
from picard.i18n import (
N_,
gettext as _,
)
from picard.webservice import ratecontrol

from picard.ui.caa_types_selector import display_caa_types_selector
Expand Down
1 change: 1 addition & 0 deletions picard/coverart/providers/caa_release_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
CaaThumbnailCoverArtImage,
)
from picard.coverart.providers.caa import CoverArtProviderCaa
from picard.i18n import N_


class CaaCoverArtImageRg(CaaCoverArtImage):
Expand Down
1 change: 1 addition & 0 deletions picard/coverart/providers/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
ProviderOptions,
)
from picard.coverart.utils import CAA_TYPES
from picard.i18n import N_

from picard.ui.ui_provider_options_local import Ui_LocalOptions

Expand Down
1 change: 1 addition & 0 deletions picard/coverart/providers/urlrels.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from picard import log
from picard.coverart.image import CoverArtImage
from picard.coverart.providers.provider import CoverArtProvider
from picard.i18n import N_


class CoverArtProviderUrlRelationships(CoverArtProvider):
Expand Down
5 changes: 5 additions & 0 deletions picard/coverart/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
from enum import IntEnum

from picard.const import MB_ATTRIBUTES
from picard.i18n import (
N_,
gettext as _,
pgettext_attributes,
)


# list of types from http://musicbrainz.org/doc/Cover_Art/Types
Expand Down
2 changes: 2 additions & 0 deletions picard/debug_opts.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

from enum import Enum

from picard.i18n import N_


class DebugOptEnum(int, Enum):
__registry__ = set()
Expand Down
4 changes: 4 additions & 0 deletions picard/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
IS_MACOS,
IS_WIN,
)
from picard.i18n import (
N_,
gettext as _,
)
from picard.metadata import (
Metadata,
SimMatchTrack,
Expand Down
79 changes: 54 additions & 25 deletions picard/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.


import builtins
import gettext
import gettext as module_gettext
import locale
import os

Expand All @@ -35,11 +33,16 @@
)


builtins.__dict__['N_'] = lambda a: a


_logger = None

_null_translations = module_gettext.NullTranslations()
_translation = {
'main': _null_translations,
'attributes': _null_translations,
'constants': _null_translations,
'countries': _null_translations,
}


def set_locale_from_env():
"""
Expand Down Expand Up @@ -116,10 +119,10 @@ def _try_locales(language):
def _load_translation(domain, localedir, language):
try:
_logger("Loading gettext translation for %s, localedir=%r, language=%r", domain, localedir, language)
return gettext.translation(domain, localedir, languages=[language])
return module_gettext.translation(domain, localedir, languages=[language])
except OSError as e:
_logger(e)
return gettext.NullTranslations()
return module_gettext.NullTranslations()


def _log_lang_env_vars():
Expand Down Expand Up @@ -171,20 +174,46 @@ def setup_gettext(localedir, ui_language=None, logger=None):
_logger("Using locale: %r", current_locale)
QLocale.setDefault(QLocale(current_locale))

trans = _load_translation('picard', localedir, language=current_locale)
trans_attributes = _load_translation('picard-attributes', localedir, language=current_locale)
trans_constants = _load_translation('picard-constants', localedir, language=current_locale)
trans_countries = _load_translation('picard-countries', localedir, language=current_locale)

trans.install(['ngettext'])
builtins.__dict__['gettext_attributes'] = trans_attributes.gettext
builtins.__dict__['gettext_constants'] = trans_constants.gettext
builtins.__dict__['gettext_countries'] = trans_countries.gettext
builtins.__dict__['pgettext_attributes'] = trans_attributes.pgettext

_logger("_ = %r", _)
_logger("N_ = %r", N_)
_logger("ngettext = %r", ngettext)
_logger("gettext_countries = %r", gettext_countries)
_logger("gettext_attributes = %r", gettext_attributes)
_logger("pgettext_attributes = %r", pgettext_attributes)
global _translation
_translation = {
'main': _load_translation('picard', localedir, language=current_locale),
'attributes': _load_translation('picard-attributes', localedir, language=current_locale),
'constants': _load_translation('picard-constants', localedir, language=current_locale),
'countries': _load_translation('picard-countries', localedir, language=current_locale),
}
_logger(_translation)


def gettext(message: str) -> str:
"""Translate the messsage using the current translator."""
return _translation['main'].gettext(message)


def _(message: str) -> str:
"""Alias for gettext"""
return gettext(message)


def N_(message: str) -> str:
"""No-op marker for translatable strings"""
return message


def ngettext(singular: str, plural: str, n: int) -> str:
return _translation['main'].ngettext(singular, plural, n)


def pgettext_attributes(context: str, message: str) -> str:
return _translation['attributes'].pgettext(context, message)


def gettext_attributes(message: str) -> str:
return _translation['attributes'].gettext(message)


def gettext_countries(message: str) -> str:
return _translation['countries'].gettext(message)


def gettext_constants(message: str) -> str:
return _translation['constants'].gettext(message)
1 change: 1 addition & 0 deletions picard/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
IS_FROZEN,
)
from picard.debug_opts import DebugOpt
from picard.i18n import N_


# Get the absolute path for the picard module
Expand Down
1 change: 1 addition & 0 deletions picard/oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
MUSICBRAINZ_OAUTH_CLIENT_ID,
MUSICBRAINZ_OAUTH_CLIENT_SECRET,
)
from picard.i18n import gettext as _
from picard.util import (
build_qurl,
load_json,
Expand Down
4 changes: 4 additions & 0 deletions picard/pluginmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
USER_PLUGIN_DIR,
)
from picard.const.sys import IS_FROZEN
from picard.i18n import (
N_,
gettext as _,
)
from picard.plugin import (
_PLUGIN_MODULE_PREFIX,
PluginData,
Expand Down
3 changes: 1 addition & 2 deletions picard/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
namedtuple,
)

# Imported to trigger inclusion of N_() in builtins
from picard import i18n # noqa: F401,E402 # pylint: disable=unused-import
from picard.i18n import N_


SettingDesc = namedtuple('SettingDesc', ('name', 'fields'))
Expand Down
5 changes: 5 additions & 0 deletions picard/releasegroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@

from picard import log
from picard.dataobj import DataObject
from picard.i18n import (
N_,
gettext as _,
pgettext_attributes,
)
from picard.mbjson import (
countries_from_node,
label_info_from_node,
Expand Down
4 changes: 4 additions & 0 deletions picard/script/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
DEFAULT_FILE_NAMING_FORMAT,
DEFAULT_NAMING_PRESET_ID,
)
from picard.i18n import (
N_,
gettext as _,
)
from picard.script.functions import ( # noqa: F401 # pylint: disable=unused-import
register_script_function,
script_function,
Expand Down
5 changes: 5 additions & 0 deletions picard/script/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
import unicodedata

from picard.const.countries import RELEASE_COUNTRIES
from picard.i18n import (
N_,
gettext as _,
gettext_countries,
)
from picard.metadata import MULTI_VALUED_JOINER
from picard.script.parser import (
MultiValue,
Expand Down
4 changes: 4 additions & 0 deletions picard/script/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
DEFAULT_SCRIPT_NAME,
SCRIPT_LANGUAGE_VERSION,
)
from picard.i18n import (
N_,
gettext as _,
)
from picard.util import make_filename_from_title


Expand Down
Loading
Loading