File indexing completed on 2024-04-28 15:08:12

0001 #!/usr/bin/python3
0002 #
0003 # GCompris - fdroid_update_fastlane_metadata.py
0004 #
0005 # SPDX-FileCopyrightText: 2023 Johnny Jazeix <jazeix@gmail.com>
0006 #
0007 #   SPDX-License-Identifier: GPL-3.0-or-later
0008 
0009 import sys
0010 import os
0011 import re
0012 import glob
0013 import subprocess
0014 import xml.etree.ElementTree as ET
0015 
0016 from PyQt5.QtCore import QCoreApplication, QUrl
0017 from PyQt5.QtQml import qmlRegisterType, QQmlComponent, QQmlEngine
0018 import polib
0019 
0020 from python.ActivityInfo import ActivityInfo
0021 
0022 if len(sys.argv) < 2:
0023     print("Usage: fdroid_update_fastlane_metadata.py <version> [-v]")
0024     sys.exit(1)
0025 
0026 version = sys.argv[1]
0027 verbose = len(sys.argv) >= 3 and sys.argv[2] == "-v"
0028 
0029 def generate_files_for_locale(changelog_qml, locale):
0030     # Generate in fastlane/metadata/android/$locale/
0031     # short_description.txt
0032     # full_description.txt
0033     # title.txt
0034     # changelogs for the version in parameter
0035     gcompris_locale = locale.replace("-", "_")
0036 
0037     locale_root_dir = f"fastlane/metadata/android/{locale}"
0038     if not os.path.isdir(locale_root_dir):
0039         os.mkdir(locale_root_dir)
0040 
0041     suffix = '[@{http://www.w3.org/XML/1998/namespace}lang="%s"]' % locale if locale != "en-US" else ""
0042 
0043     # Open org.kde.gcompris.appdata.xml to retrieve information
0044     tree = ET.parse("org.kde.gcompris.appdata.xml")
0045     appdata = tree.getroot()
0046     children = appdata.findall(f'name{suffix}')
0047     if not children:
0048         suffix = '[@{http://www.w3.org/XML/1998/namespace}lang="%s"]' % locale[0:2]
0049         children = appdata.findall(f'name{suffix}')
0050 
0051     if not children:
0052         if verbose:
0053             print(f"Language {locale} not translated")
0054         return False
0055 
0056     child = children[0]
0057     with open(f'{locale_root_dir}/title.txt', 'w', encoding="utf8") as title_file:
0058         title_file.write(child.text)
0059 
0060     children = appdata.findall(f'summary{suffix}')
0061     if not children:
0062         print(f"Language {locale} not translated")
0063         return False
0064 
0065     child = children[0]
0066     with open(f'{locale_root_dir}/short_description.txt', 'w', encoding="utf8") as short_description_file:
0067         short_description_file.write(child.text)
0068 
0069     # Get full description from summary elements
0070     children = appdata.findall(f'description//*{suffix}')
0071     with open(f'{locale_root_dir}/full_description.txt', 'w', encoding="utf8") as full_description_file:
0072         for c in children:
0073             if locale == "en-US" and c.attrib:
0074                 continue
0075             if c.tag == 'ul':
0076                 continue
0077             if c.tag == 'li':
0078                 full_description_file.write("- ")
0079             full_description_file.write(c.text + '\n')
0080 
0081     # We use polib to translate as QTranslator only handles .qm files and we don't need to have GCompris compiled to generate this file
0082     translation_file_path = 'poqm/'+gcompris_locale+'/gcompris_qt.po'
0083     if not os.path.isfile(translation_file_path):
0084         # Short locale
0085         gcompris_locale = gcompris_locale[0:gcompris_locale.find("_")]
0086         translation_file_path = 'poqm/'+gcompris_locale+'/gcompris_qt.po'
0087         if not os.path.isfile(translation_file_path):
0088             if verbose:
0089                 print(f"Locale {locale} [{gcompris_locale}] not handled, skip it")
0090             return False
0091     if verbose:
0092         print(f"Generate for locale {locale} [{gcompris_locale}]")
0093     po = polib.pofile(translation_file_path)
0094 
0095     output = ""
0096 
0097     # Get new activities for this version
0098     # With regex for each ActivityInfo.qml, no need to use Qt there
0099     for activityInfo in glob.glob('src/activities/*/ActivityInfo.qml'):
0100         try:
0101             if activityInfo.find("template") != -1:
0102                 continue
0103             with open(activityInfo, encoding="utf8") as f:
0104                 content = f.readlines()
0105                 title = ""
0106                 for line in content:
0107                     titleMatch = re.match('.*title:.*\"(.*)\"', line)
0108                     if titleMatch:
0109                         title = titleMatch.group(1)
0110 
0111                     m = re.match('.*createdInVersion:(.*)', line)
0112                     if m:
0113                         activityVersion = m.group(1)
0114                         if int(activityVersion) == int(version):
0115                             po_title = po.find(title)
0116                             if locale == "en-US":
0117                                 translated_title = title
0118                             elif po_title and po_title.translated():
0119                                 translated_title = po_title.msgstr
0120                             else: # The translation is not complete, we skip the language
0121                                 if verbose:
0122                                     print(f"Skip {locale} because {title} is not translated")
0123                                 return False
0124                             output += "- " + translated_title + '\n'
0125         except IOError as e:
0126             if verbose:
0127                 print(f"ERROR: Failed to parse {activityInfo}: {e.strerror}")
0128 
0129     # Get changelog information
0130     versions_data = changelog_qml.property('changelog')
0131     for version_data in versions_data.toVariant():
0132         if version == str(version_data['versionCode']):
0133             content = version_data['content']
0134             for feature in content:
0135                 po_feature = po.find(feature)
0136                 if locale == "en-US":
0137                     translated_feature = feature
0138                 elif po_feature and po_feature.translated():
0139                     translated_feature = po.find(feature).msgstr
0140                 else: # The translation is not complete, we skip the language
0141                     if verbose:
0142                         print("Skip %s because %s is not translated" % (locale, feature))
0143                     return False, ""
0144 
0145                 output += "- " + translated_feature + '\n'
0146     changelog_dir = "%s/changelogs" % locale_root_dir
0147     if not os.path.isdir(changelog_dir):
0148         os.mkdir(changelog_dir)
0149     with open(changelog_dir+'/%s.txt' % version, 'w', encoding="utf8") as changelog_file:
0150         changelog_file.write(output)
0151 
0152     return True
0153 
0154 def main(argv):
0155     if sys.argv[0] != "./tools/fdroid_update_fastlane_metadata.py":
0156         print("Needs to be run from top level of GCompris")
0157         sys.exit(1)
0158     app = QCoreApplication(sys.argv)
0159 
0160     engine = QQmlEngine()
0161     # We need to register at least one file for GCompris package else it is not found
0162     qmlRegisterType(ActivityInfo, "GCompris", 1, 0, "ActivityInfo")
0163     component = QQmlComponent(engine)
0164     component.loadUrl(QUrl("src/core/ChangeLog.qml"))
0165     changelog_qml = component.create()
0166 
0167     # List taken from the android list
0168     for locale in ["en-US", "ar-AR", "az-AZ", "be", "ca", "cs-CZ", "de-DE", "el-GR", "en-GB", "es-ES", "eu-ES", "fi-FI", "fr-FR", "gl-ES", "he", "hr", "hu-HU", "id", "it-IT", "lt", "mk-MK", "ml-IN", "nl-NL", "no-NO", "pl-PL", "pt-BR", "pt-PT", "ro", "ru-RU", "sk", "sl", "sq", "sv-SE", "tr-TR", "uk", "zh-CN", "zh-TW"]:
0169         is_translation_ok = generate_files_for_locale(changelog_qml, locale)
0170         if not is_translation_ok and verbose:
0171             print(f"Error when generating files for {locale}")
0172 
0173     PIPE = subprocess.PIPE
0174     process = subprocess.Popen(["git", "ls-files", "-o", "-m", "fastlane"], stdout = PIPE, stderr = PIPE)
0175     stdoutput, _ = process.communicate()
0176     if stdoutput:
0177         if verbose:
0178             print("git ls-files output:\n", stdoutput.decode("utf-8"))
0179         process = subprocess.Popen(["git", "add", "fastlane"], stdout = PIPE, stderr = PIPE)
0180         stdoutput, _ = process.communicate()
0181         process = subprocess.Popen(["git", "commit", "-m", 'fastlane, update metadata'], stdout = PIPE, stderr = PIPE)
0182         stdoutput, _ = process.communicate()
0183 
0184 if __name__ == '__main__':
0185     main(sys.argv)