Skip to content
Snippets Groups Projects
utils.py 6.89 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ##### 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"])
    
    Campbell Barton's avatar
    Campbell Barton committed
        print("enum label: %r" % 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"])
    
    Campbell Barton's avatar
    Campbell Barton committed
        print("rna label: %r" % rlbl, rlbl in msgid_to_msg, rlbl in msgstr_to_msg)
    
            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)])
    
    Campbell Barton's avatar
    Campbell Barton committed
        print("button label: %r" % 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"])
    
    Campbell Barton's avatar
    Campbell Barton committed
        print("enum tip: %r" % 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"])
    
    Campbell Barton's avatar
    Campbell Barton committed
        print("rna tip: %r" % 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"])
    
    Campbell Barton's avatar
    Campbell Barton committed
        print("button tip: %r" % 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