~chromium-team/chromium-browser/translations-pump

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
"""POT files contain the template for transltion.

This module is write-only.  It doesn't read any data from launchpad exports.
The data it writes out is completely the GRD data.  We map languages out to
what launchpad expects.

white-space
#  translator-comments
#. extracted-comments
#: reference...
#, flag...
#| msgid previous-untranslated-string
msgid untranslated-string
msgstr translated-string

"""

import logging
import re
import os

from .gettext import gettext_file_sorting_function, grd_msg_write_in_po


COND_DEFINES = frozenset("linux/use_third_party_translations/use_titlecase/_google_chrome".split("/"))
COND_UNDEFINED_BUT_KNOWN = frozenset("ios/chromeos/android/use_ash/enable_settings_app".split("/"))
def evaluate_grd_condition(expression_string):
    """Evaluate a expression in string form that we got from a GRD file, after
    we rewrite all lang-referencing subexpressions to Truthness.  Return true
    or false.
    
    >>> evaluate_grd_condition("False")
    False
    >>> evaluate_grd_condition("lang   =='ar'")
    True
    >>> evaluate_grd_condition("lang != 'ar'")
    True
    >>> evaluate_grd_condition("lang not in ['zh-CN', 'zh-TW', 'ko', 'ja', 'vi', 'tr', 'kn']")
    True
    >>> evaluate_grd_condition(" lang  in[ 'zh-CN',  'zh-TW', 'ko', 'ja', 'vi', 'tr', 'kn'] ")
    True
    """
    def  pp_ifdef(n):
        """GRIT function we reimplement for use by evaluator."""
        if n in COND_DEFINES:
            return True
        if not n in COND_UNDEFINED_BUT_KNOWN:
            logging.warn("name %r might be new. Define it or add it to undefined_but_known in conditions", n)
        return False

    # munge conditions here to convert all "lang"-referencing expressions terms to true.
    expression_string = re.sub(r"\blang\s*(?:!|=)=\s*'\w+'", "True", expression_string)
    expression_string = re.sub(r"\blang(\s+not)?\s+in\s*\[\s*('[^']+',?\s*)*\]", "True", expression_string)

    global_variables = { "__builtins__": { "True":True, "False":False } }
    local_variables = dict(pp_ifdef=pp_ifdef, is_android=False, is_macosx=False, is_posix=True, is_win=False, is_linux=True)
    try:
        condition_result = eval(expression_string, global_variables, local_variables)
    except NameError:
        logging.warn("A name used in condition %r is unknown! You have to define it.", expression_string)
        raise
    return condition_result


def save_pot(txln_info, container_directory, template_name):
    file_map = dict()

    try:
        os.makedirs(os.path.join(container_directory, template_name))
    except:
        pass
    out = open(os.path.join(container_directory, template_name, template_name + ".pot"), "w")
    out.write("""# Chromium Translation Template.\n# Copyright 2013 Canonical\n# This file is distributed inder the same license as the chromium-browser package.\n# Contact Chad MILLER <chad.miller@canonical.com>\n\nmsgid ""\nmsgstr ""\n"Project-Id-Version: chromium-browser.head\\n"\n"Report-Msgid-Bugs-To: https://bugs.launchpad.net/ubuntu/+source/chromium-"\n"browser/+filebug\\n"\n"Language-Team: Launchpad Translators <launchpad-translators@lists.launchpad.net>\\n"\n"MIME-Version: 1.0\\n"\n"Content-Type: text/plain; charset=UTF-8\\n"\n"Content-Transfer-Encoding: 8bit\\n"\n\n""")

    try:
        for grdsid, template_info in sorted(txln_info.items(), key=gettext_file_sorting_function):
            if "refs" in template_info:
                # For each of these, create a template stanza.
                condition_evaluation = False
                for ref in template_info["refs"]:

                    # If ANY language needs this, then we need it.  No condition means True.
                    if not ref["conditions"]:
                        condition_evaluation = True
                    else:
                        # For this language, we can have many conditions, and all have to pass for this language to pass.
                        this_cond = all(evaluate_grd_condition(x) for x in set(ref["conditions"]))
                        condition_evaluation = condition_evaluation or this_cond
                        if not condition_evaluation:
                            break

                if not condition_evaluation:
                    out.write("#. UNUSED: {0} == False\n".format(" OR ".join(sorted(set(("("+ " and ".join(c for c in ref["conditions"] if c != "()") + ")") for ref in template_info["refs"])))))

                for note in sorted(set(r["note"].strip() for r in template_info["refs"]))[:5]:
                    if not note:
                        continue
                    out.write("#. note: {0!r}\n".format(note))

                # Notes to nonprogrammer translators about tricky things they might mess up.
                if "\\x" in template_info["text"]:
                    out.write("#. note: Take care to keep backslash-x-letter-letter together.\n")

                for example in sorted(r.get("example", "") for r in template_info["refs"]):
                    if example:
                        out.write("#. ex: {0}\n".format(example))

                for ref in sorted(template_info["refs"], key=lambda r: r["file"])[:2]:
                    out.write("#. in: {file}, as {id}\n".format(**ref))

                out.write("#: id: {0}; intermediary: cmlpgrid v1\n".format(grdsid))
                
                grd_msg_write_in_po("msgid", template_info["text"], out)
                grd_msg_write_in_po("msgstr", "", out)
                out.write("\n")
    finally:
        for f in file_map.values():
            f.close()