File: trans.py

package info (click to toggle)
dupeguru 4.3.1-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,604 kB
  • sloc: python: 16,846; ansic: 424; makefile: 123
file content (164 lines) | stat: -rw-r--r-- 5,010 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# Created By: Virgil Dupras
# Created On: 2010-06-23
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html

# Doing i18n with GNU gettext for the core text gets complicated, so what I do is that I make the
# GUI layer responsible for supplying a tr() function.

import locale
import logging
import os
import os.path as op
from typing import Callable, Union

from hscommon.plat import ISLINUX

_trfunc = None
_trget = None
installed_lang = None


def tr(s: str, context: Union[str, None] = None) -> str:
    if _trfunc is None:
        return s
    else:
        if context:
            return _trfunc(s, context)
        else:
            return _trfunc(s)


def trget(domain: str) -> Callable[[str], str]:
    # Returns a tr() function for the specified domain.
    if _trget is None:
        return lambda s: tr(s, domain)
    else:
        return _trget(domain)


def set_tr(
    new_tr: Callable[[str, Union[str, None]], str], new_trget: Union[Callable[[str], Callable[[str], str]], None] = None
) -> None:
    global _trfunc, _trget
    _trfunc = new_tr
    if new_trget is not None:
        _trget = new_trget


def get_locale_name(lang: str) -> Union[str, None]:
    # Removed old conversion code as windows seems to support these
    LANG2LOCALENAME = {
        "cs": "cs_CZ",
        "de": "de_DE",
        "el": "el_GR",
        "en": "en",
        "es": "es_ES",
        "fr": "fr_FR",
        "hy": "hy_AM",
        "it": "it_IT",
        "ja": "ja_JP",
        "ko": "ko_KR",
        "ms": "ms_MY",
        "nl": "nl_NL",
        "pl_PL": "pl_PL",
        "pt_BR": "pt_BR",
        "ru": "ru_RU",
        "tr": "tr_TR",
        "uk": "uk_UA",
        "vi": "vi_VN",
        "zh_CN": "zh_CN",
    }
    if lang not in LANG2LOCALENAME:
        return None
    result = LANG2LOCALENAME[lang]
    if ISLINUX:
        result += ".UTF-8"
    return result


# --- Qt
def install_qt_trans(lang: str = None) -> None:
    from PyQt5.QtCore import QCoreApplication, QTranslator, QLocale

    if not lang:
        lang = str(QLocale.system().name())[:2]
    localename = get_locale_name(lang)
    if localename is not None:
        try:
            locale.setlocale(locale.LC_ALL, localename)
        except locale.Error:
            logging.warning("Couldn't set locale %s", localename)
    else:
        lang = "en"
    qtr1 = QTranslator(QCoreApplication.instance())
    qtr1.load(":/qt_%s" % lang)
    QCoreApplication.installTranslator(qtr1)
    qtr2 = QTranslator(QCoreApplication.instance())
    qtr2.load(":/%s" % lang)
    QCoreApplication.installTranslator(qtr2)

    def qt_tr(s: str, context: Union[str, None] = "core") -> str:
        if context is None:
            context = "core"
        return str(QCoreApplication.translate(context, s, None))

    set_tr(qt_tr)


# --- gettext
def install_gettext_trans(base_folder: os.PathLike, lang: str) -> None:
    import gettext

    def gettext_trget(domain: str) -> Callable[[str], str]:
        if not lang:
            return lambda s: s
        try:
            return gettext.translation(domain, localedir=base_folder, languages=[lang]).gettext
        except OSError:
            return lambda s: s

    default_gettext = gettext_trget("core")

    def gettext_tr(s: str, context: Union[str, None] = None) -> str:
        if not context:
            return default_gettext(s)
        else:
            trfunc = gettext_trget(context)
            return trfunc(s)

    set_tr(gettext_tr, gettext_trget)
    global installed_lang
    installed_lang = lang


def install_gettext_trans_under_qt(base_folder: os.PathLike, lang: str = None) -> None:
    # So, we install the gettext locale, great, but we also should try to install qt_*.qm if
    # available so that strings that are inside Qt itself over which I have no control are in the
    # right language.
    from PyQt5.QtCore import QCoreApplication, QTranslator, QLocale, QLibraryInfo

    if not lang:
        lang = str(QLocale.system().name())[:2]
    localename = get_locale_name(lang)
    if localename is None:
        lang = "en"
        localename = get_locale_name(lang)
    try:
        locale.setlocale(locale.LC_ALL, localename)
    except locale.Error:
        logging.warning("Couldn't set locale %s", localename)
    qmname = "qt_%s" % lang
    if ISLINUX:
        # Under linux, a full Qt installation is already available in the system, we didn't bundle
        # up the qm files in our package, so we have to load translations from the system.
        qmpath = op.join(QLibraryInfo.location(QLibraryInfo.TranslationsPath), qmname)
    else:
        qmpath = op.join(base_folder, qmname)
    qtr = QTranslator(QCoreApplication.instance())
    qtr.load(qmpath)
    QCoreApplication.installTranslator(qtr)
    install_gettext_trans(base_folder, lang)