Welcome to mirror list, hosted at ThFree Co, Russian Federation.

utils.py « ui_translate - git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2f19889440582542f7f49fcb7a47638d5d07366b (plain)
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# ##### BEGIN GPL LICENSE BLOCK #####
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; either version 2
#  of the License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

# <pep8 compliant>

#from bl_i18n_utils import utils as i18n_utils
from bl_i18n_utils import settings

import os


# module-level cache, as parsing po files takes a few seconds...
# Keys are po file paths, data are the results of i18n_utils.parse_messages().
WORK_CACHE = {}

# Same as in BLF_translation.h
BLF_I18NCONTEXT_DEFAULT = ""


# Num buttons report their label with a trailing ': '...
NUM_BUTTON_SUFFIX = ": "



# Mo root datapath.
MO_PATH_ROOT = "locale"

# Mo path generator for a given language.
MO_PATH_TEMPLATE = os.path.join(MO_PATH_ROOT, "{}", "LC_MESSAGES")

# Mo filename.
MO_FILENAME = "blender.mo"


def bpy_path(rstruct, rprop, renum):
    src = src_rna = src_enum = ""
    if rstruct:
        if rprop:
            src = src_rna = ".".join((rstruct, rprop))
            if renum:
                src = src_enum = "{}.{}:'{}'".format(rstruct, rprop, renum)
        else:
            src = src_rna = rstruct
    return src, src_rna, src_enum


def find_best_msgs_matches(obj, cache_key, msgmap, msgs, state, rna_ctxt, rstruct, rprop, renum):
    comm_prfx = settings.COMMENT_PREFIX_SOURCE + "bpy.types."

    # Build helper mappings.
    # XXX We do not update this cache when editing a translation, as it would
    #     prevent the same msgid/msgstr to be find again.
    #     We only invalidate the cache once new po/mo have been generated!
    if cache_key in WORK_CACHE:
        src_to_msg, ctxt_to_msg, msgid_to_msg, msgstr_to_msg = WORK_CACHE[cache_key]
    else:
        src_to_msg = {}
        ctxt_to_msg = {}
        msgid_to_msg = {}
        msgstr_to_msg = {}
        for key, val in msgs.items():
            ctxt, msgid = key
            if key in state["comm_msg"]:
                continue
            ctxt_to_msg.setdefault(ctxt, set()).add(key)
            msgid_to_msg.setdefault(msgid, set()).add(key)
            msgstr_to_msg.setdefault("".join(val["msgstr_lines"]), set()).add(key)
            for comm in val["comment_lines"]:
                if comm.startswith(comm_prfx):
                    comm = comm[len(comm_prfx):]
                    src_to_msg.setdefault(comm, set()).add(key)
        WORK_CACHE[cache_key] = (src_to_msg, ctxt_to_msg, msgid_to_msg, msgstr_to_msg)

#    print(len(src_to_msg), len(ctxt_to_msg), len(msgid_to_msg), len(msgstr_to_msg))

    # Build RNA key.
    src, src_rna, src_enum = bpy_path(rstruct, rprop, renum)
    print("src: ", src_rna, src_enum)

    # Labels.
    elbl = getattr(obj, msgmap["enum_label"]["msgstr"])
    print("enum label: '"+elbl+"'")
    if elbl:
        # Enum items' labels have no i18n context...
        k = ctxt_to_msg[BLF_I18NCONTEXT_DEFAULT].copy()
        if elbl in msgid_to_msg:
            k &= msgid_to_msg[elbl]
        elif elbl in msgstr_to_msg:
            k &= msgstr_to_msg[elbl]
        else:
            k = set()
        # We assume if we already have only one key, it's the good one!
        if len(k) > 1 and src_enum in src_to_msg:
            k &= src_to_msg[src_enum]
        msgmap["enum_label"]["key"] = k
    rlbl = getattr(obj, msgmap["rna_label"]["msgstr"])
    print("rna label: '"+rlbl+"'", rlbl in msgid_to_msg, rlbl in msgstr_to_msg)
    if rlbl:
        k = ctxt_to_msg[rna_ctxt].copy()
        if k and rlbl in msgid_to_msg:
            k &= msgid_to_msg[rlbl]
        elif k and rlbl in msgstr_to_msg:
            k &= msgstr_to_msg[rlbl]
        else:
            k = set()
        # We assume if we already have only one key, it's the good one!
        if len(k) > 1 and src_rna in src_to_msg:
            k &= src_to_msg[src_rna]
        msgmap["rna_label"]["key"] = k
    blbl = getattr(obj, msgmap["but_label"]["msgstr"])
    blbls = [blbl]
    if blbl.endswith(NUM_BUTTON_SUFFIX):
        # Num buttons report their label with a trailing ': '...
        blbls.append(blbl[:-len(NUM_BUTTON_SUFFIX)])
    print("button label: '"+blbl+"'")
    if blbl and elbl not in blbls and (rlbl not in blbls or rna_ctxt != BLF_I18NCONTEXT_DEFAULT):
        # Always Default context for button label :/
        k = ctxt_to_msg[BLF_I18NCONTEXT_DEFAULT].copy()
        found = False
        for bl in blbls:
            if bl in msgid_to_msg:
                k &= msgid_to_msg[bl]
                found = True
                break
            elif bl in msgstr_to_msg:
                k &= msgstr_to_msg[bl]
                found = True
                break
        if not found:
            k = set()
        # XXX No need to check against RNA path here, if blabel is different
        #     from rlabel, should not match anyway!
        msgmap["but_label"]["key"] = k

    # Tips (they never have a specific context).
    etip = getattr(obj, msgmap["enum_tip"]["msgstr"])
    print("enum tip: '"+etip+"'")
    if etip:
        k = ctxt_to_msg[BLF_I18NCONTEXT_DEFAULT].copy()
        if etip in msgid_to_msg:
            k &= msgid_to_msg[etip]
        elif etip in msgstr_to_msg:
            k &= msgstr_to_msg[etip]
        else:
            k = set()
        # We assume if we already have only one key, it's the good one!
        if len(k) > 1 and src_enum in src_to_msg:
            k &= src_to_msg[src_enum]
        msgmap["enum_tip"]["key"] = k
    rtip = getattr(obj, msgmap["rna_tip"]["msgstr"])
    print("rna tip: '"+rtip+"'")
    if rtip:
        k = ctxt_to_msg[BLF_I18NCONTEXT_DEFAULT].copy()
        if k and rtip in msgid_to_msg:
            k &= msgid_to_msg[rtip]
        elif k and rtip in msgstr_to_msg:
            k &= msgstr_to_msg[rtip]
        else:
            k = set()
        # We assume if we already have only one key, it's the good one!
        if len(k) > 1 and src_rna in src_to_msg:
            k &= src_to_msg[src_rna]
        msgmap["rna_tip"]["key"] = k
        print(k)
    btip = getattr(obj, msgmap["but_tip"]["msgstr"])
    print("button tip: '"+btip+"'")
    if btip and btip not in {rtip, etip}:
        k = ctxt_to_msg[BLF_I18NCONTEXT_DEFAULT].copy()
        if btip in msgid_to_msg:
            k &= msgid_to_msg[btip]
        elif btip in msgstr_to_msg:
            k &= msgstr_to_msg[btip]
        else:
            k = set()
        # XXX No need to check against RNA path here, if btip is different
        #     from rtip, should not match anyway!
        msgmap["but_tip"]["key"] = k