1#!/usr/bin/env python2
2# -*- coding: utf-8 -*-
3#
4# Copyright (C) 2018 Wildfire Games.
5# This file is part of 0 A.D.
6#
7# 0 A.D. is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 2 of the License, or
10# (at your option) any later version.
11#
12# 0 A.D. is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
19
20from __future__ import absolute_import, division, print_function, unicode_literals
21
22import codecs, datetime, json, os, string, textwrap
23
24from pology.catalog import Catalog
25from pology.message import Message
26from pology.monitored import Monpair, Monlist
27
28from lxml import etree
29
30
31l10nToolsDirectory = os.path.dirname(os.path.realpath(__file__))
32projectRootDirectory = os.path.abspath(os.path.join(l10nToolsDirectory, os.pardir, os.pardir, os.pardir))
33l10nFolderName = "l10n"
34messagesFilename = "messages.json"
35
36
37def warnAboutUntouchedMods():
38    """
39        Warn about mods that are not properly configured to get their messages extracted.
40    """
41    modsRootFolder = os.path.join(projectRootDirectory, "binaries", "data", "mods")
42    untouchedMods = {}
43    for modFolder in os.listdir(modsRootFolder):
44        if modFolder[0] != "_":
45            if not os.path.exists(os.path.join(modsRootFolder, modFolder, l10nFolderName)):
46                untouchedMods[modFolder] = "There is no '{folderName}' folder in the root folder of this mod.".format(folderName=l10nFolderName)
47            elif not os.path.exists(os.path.join(modsRootFolder, modFolder, l10nFolderName, messagesFilename)):
48                untouchedMods[modFolder] = "There is no '{filename}' file within the '{folderName}' folder in the root folder of this mod.".format(folderName=l10nFolderName, filename=messagesFilename)
49    if untouchedMods:
50        print(textwrap.dedent("""
51                Warning: No messages were extracted from the following mods:
52            """))
53        for mod in untouchedMods:
54            print("• {modName}: {warningMessage}".format(modName=mod, warningMessage=untouchedMods[mod]))
55        print(textwrap.dedent("""
56                For this script to extract messages from a mod folder, this mod folder must contain a '{folderName}'
57                folder, and this folder must contain a '{filename}' file that describes how to extract messages for the
58                mod. See the folder of the main mod ('public') for an example, and see the documentation for more
59                information.
60                """.format(folderName=l10nFolderName, filename=messagesFilename)
61             ))
62
63
64def generateTemplatesForMessagesFile(messagesFilePath):
65
66    with open(messagesFilePath, 'r') as fileObject:
67        settings = json.load(fileObject)
68
69    rootPath = os.path.dirname(messagesFilePath)
70
71    for templateSettings in settings:
72        if "skip" in templateSettings and templateSettings["skip"] == "yes":
73            continue
74
75        inputRootPath = rootPath
76        if "inputRoot" in templateSettings:
77            inputRootPath = os.path.join(rootPath, templateSettings["inputRoot"])
78
79        template = Catalog(os.path.join(rootPath, templateSettings["output"]), create=True, truncate=True)
80        h = template.update_header(
81            templateSettings["project"],
82            "Translation template for %project.",
83            "Copyright (C) {year} {holder}".format(
84                year=datetime.datetime.now().year,
85                holder=templateSettings["copyrightHolder"]
86            ),
87            "This file is distributed under the same license as the %project project.",
88            plforms="nplurals=2; plural=(n != 1);"
89        )
90        h.remove_field("Report-Msgid-Bugs-To")
91        h.remove_field("Last-Translator")
92        h.remove_field("Language-Team")
93        h.remove_field("Language")
94        h.author = Monlist()
95
96        for rule in templateSettings["rules"]:
97            if "skip" in rule and rule["skip"] == "yes":
98                continue
99
100            options = rule.get("options", {})
101            extractorClass = getattr(__import__("extractors.extractors", {}, {}, [rule["extractor"]]), rule["extractor"])
102            extractor = extractorClass(inputRootPath, rule["filemasks"], options)
103            formatFlag = None
104            if "format" in options:
105                formatFlag = options["format"]
106            for message, plural, context, location, comments in extractor.run():
107                msg = Message({"msgid": message, "msgid_plural": plural, "msgctxt": context, "auto_comment": comments, "flag": [formatFlag] if formatFlag and string.find(message, "%") != -1 else None, "source": [location]})
108                if template.get(msg):
109                    template.get(msg).source.append(Monpair(location))
110                else:
111                    template.add(msg)
112
113        template.set_encoding("utf-8")
114        template.sync(fitplural=True)
115        print(u"Generated \"{}\" with {} messages.".format(templateSettings["output"], len(template)))
116
117
118def main():
119
120    for root, folders, filenames in os.walk(projectRootDirectory):
121        for folder in folders:
122            if folder == l10nFolderName:
123                messagesFilePath = os.path.join(root, folder, messagesFilename)
124                if os.path.exists(messagesFilePath):
125                    generateTemplatesForMessagesFile(messagesFilePath)
126
127    warnAboutUntouchedMods()
128
129
130if __name__ == "__main__":
131    main()
132