implement gettext localization

This allows all the text to be localized via Weblate.  This is a quick
overview of all the strings, but there are certainly some that were left
out.

closes #342
This commit is contained in:
Hans-Christoph Steiner 2017-09-13 18:03:57 +02:00
parent e4ca82d80c
commit 278d67d960
24 changed files with 285 additions and 235 deletions

3
.gitignore vendored
View File

@ -44,3 +44,6 @@ makebuildserver.config.py
/tests/repo/info.guardianproject.checkey/en-US/phoneScreenshots/checkey.png
/tests/urzip-πÇÇπÇÇ现代汉语通用字-български-عربي1234.apk
/unsigned/
# generated by gettext
locale/*/LC_MESSAGES/fdroidserver.mo

50
fdroid
View File

@ -22,36 +22,38 @@ import logging
import fdroidserver.common
import fdroidserver.metadata
from fdroidserver import _
from argparse import ArgumentError
from collections import OrderedDict
commands = OrderedDict([
("build", "Build a package from source"),
("init", "Quickly start a new repository"),
("publish", "Sign and place packages in the repo"),
("gpgsign", "Add gpg signatures for packages in repo"),
("update", "Update repo information for new packages"),
("verify", "Verify the integrity of downloaded packages"),
("checkupdates", "Check for updates to applications"),
("import", "Add a new application from its source code"),
("install", "Install built packages on devices"),
("readmeta", "Read all the metadata files and exit"),
("rewritemeta", "Rewrite all the metadata files"),
("lint", "Warn about possible metadata errors"),
("scanner", "Scan the source code of a package"),
("dscanner", "Dynamically scan APKs post build"),
("stats", "Update the stats of the repo"),
("server", "Interact with the repo HTTP server"),
("signindex", "Sign indexes created using update --nosign"),
("btlog", "Update the binary transparency log for a URL"),
("signatures", "Extract signatures from APKs"),
("build", _("Build a package from source")),
("init", _("Quickly start a new repository")),
("publish", _("Sign and place packages in the repo")),
("gpgsign", _("Add gpg signatures for packages in repo")),
("update", _("Update repo information for new packages")),
("verify", _("Verify the integrity of downloaded packages")),
("checkupdates", _("Check for updates to applications")),
("import", _("Add a new application from its source code")),
("install", _("Install built packages on devices")),
("readmeta", _("Read all the metadata files and exit")),
("rewritemeta", _("Rewrite all the metadata files")),
("lint", _("Warn about possible metadata errors")),
("scanner", _("Scan the source code of a package")),
("dscanner", _("Dynamically scan APKs post build")),
("stats", _("Update the stats of the repo")),
("server", _("Interact with the repo HTTP server")),
("signindex", _("Sign indexes created using update --nosign")),
("btlog", _("Update the binary transparency log for a URL")),
("signatures", _("Extract signatures from APKs")),
])
def print_help():
print("usage: fdroid [-h|--help|--version] <command> [<args>]")
print(_("usage: fdroid [-h|--help|--version] <command> [<args>]"))
print("")
print("Valid commands are:")
print(_("Valid commands are:"))
for cmd, summary in commands.items():
print(" " + cmd + ' ' * (15 - len(cmd)) + summary)
print("")
@ -70,7 +72,7 @@ def main():
sys.exit(0)
elif command == '--version':
import os.path
output = 'no version info found!'
output = _('no version info found!')
cmddir = os.path.realpath(os.path.dirname(__file__))
moduledir = os.path.realpath(os.path.dirname(fdroidserver.common.__file__) + '/..')
if cmddir == moduledir:
@ -97,7 +99,7 @@ def main():
print(output),
sys.exit(0)
else:
print("Command '%s' not recognised.\n" % command)
print(_("Command '%s' not recognised.\n" % command))
print_help()
sys.exit(1)
@ -143,7 +145,7 @@ def main():
# These should only be unexpected crashes due to bugs in the code
# str(e) often doesn't contain a reason, so just show the backtrace
except Exception as e:
logging.critical("Unknown exception found!")
logging.critical(_("Unknown exception found!"))
raise
sys.exit(0)

View File

@ -0,0 +1,22 @@
import gettext
import glob
import os
import sys
# support running straight from git and standard installs
rootpaths = [
os.path.realpath(os.path.join(os.path.dirname(__file__), '..')),
sys.prefix + 'share',
]
localedir = None
for rootpath in rootpaths:
if len(glob.glob(os.path.join(rootpath, 'locale', '*', 'LC_MESSAGES', 'fdroidserver.mo'))) > 0:
localedir = os.path.join(rootpath, 'locale')
break
gettext.bindtextdomain('fdroidserver', localedir)
gettext.textdomain('fdroidserver')
_ = gettext.gettext

View File

@ -40,9 +40,10 @@ import xml.dom.minidom
import zipfile
from argparse import ArgumentParser
from .exception import FDroidException
from . import _
from . import common
from . import server
from .exception import FDroidException
options = None
@ -151,11 +152,11 @@ def main():
common.setup_global_opts(parser)
parser.add_argument("--git-repo",
default=os.path.join(os.getcwd(), 'binary_transparency'),
help="Path to the git repo to use as the log")
help=_("Path to the git repo to use as the log"))
parser.add_argument("-u", "--url", default='https://f-droid.org',
help="The base URL for the repo to log (default: https://f-droid.org)")
help=_("The base URL for the repo to log (default: https://f-droid.org)"))
parser.add_argument("--git-remote", default=None,
help="Push the log to this git remote repository")
help=_("Push the log to this git remote repository"))
options = parser.parse_args()
if options.verbose:

View File

@ -32,6 +32,7 @@ from configparser import ConfigParser
from argparse import ArgumentParser
import logging
from . import _
from . import common
from . import net
from . import metadata
@ -162,7 +163,7 @@ def build_server(app, build, vcs, build_dir, output_dir, log_dir, force):
ftp.mkdir(d)
ftp.chdir(d)
ftp.put(libsrc, lp[-1])
for _ in lp[:-1]:
for _ignored in lp[:-1]:
ftp.chdir('..')
# Copy any srclibs that are required...
srclibpaths = []
@ -995,33 +996,33 @@ def parse_commandline():
parser = ArgumentParser(usage="%(prog)s [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
common.setup_global_opts(parser)
parser.add_argument("appid", nargs='*', help="app-id with optional versionCode in the form APPID[:VERCODE]")
parser.add_argument("appid", nargs='*', help=_("app-id with optional versionCode in the form APPID[:VERCODE]"))
parser.add_argument("-l", "--latest", action="store_true", default=False,
help="Build only the latest version of each package")
help=_("Build only the latest version of each package"))
parser.add_argument("-s", "--stop", action="store_true", default=False,
help="Make the build stop on exceptions")
help=_("Make the build stop on exceptions"))
parser.add_argument("-t", "--test", action="store_true", default=False,
help="Test mode - put output in the tmp directory only, and always build, even if the output already exists.")
help=_("Test mode - put output in the tmp directory only, and always build, even if the output already exists."))
parser.add_argument("--server", action="store_true", default=False,
help="Use build server")
help=_("Use build server"))
parser.add_argument("--resetserver", action="store_true", default=False,
help="Reset and create a brand new build server, even if the existing one appears to be ok.")
help=_("Reset and create a brand new build server, even if the existing one appears to be ok."))
parser.add_argument("--on-server", dest="onserver", action="store_true", default=False,
help="Specify that we're running on the build server")
help=_("Specify that we're running on the build server"))
parser.add_argument("--skip-scan", dest="skipscan", action="store_true", default=False,
help="Skip scanning the source code for binaries and other problems")
help=_("Skip scanning the source code for binaries and other problems"))
parser.add_argument("--dscanner", action="store_true", default=False,
help="Setup an emulator, install the apk on it and perform a drozer scan")
help=_("Setup an emulator, install the apk on it and perform a drozer scan"))
parser.add_argument("--no-tarball", dest="notarball", action="store_true", default=False,
help="Don't create a source tarball, useful when testing a build")
help=_("Don't create a source tarball, useful when testing a build"))
parser.add_argument("--no-refresh", dest="refresh", action="store_false", default=True,
help="Don't refresh the repository, useful when testing a build with no internet connection")
help=_("Don't refresh the repository, useful when testing a build with no internet connection"))
parser.add_argument("-f", "--force", action="store_true", default=False,
help="Force build of disabled apps, and carries on regardless of scan problems. Only allowed in test mode.")
help=_("Force build of disabled apps, and carries on regardless of scan problems. Only allowed in test mode."))
parser.add_argument("-a", "--all", action="store_true", default=False,
help="Build all applications available")
help=_("Build all applications available"))
parser.add_argument("-w", "--wiki", default=False, action="store_true",
help="Update the wiki")
help=_("Update the wiki"))
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W
@ -1316,7 +1317,7 @@ def main():
logging.info("Cleaning up after ourselves.")
docker.clean()
logging.info("Finished.")
logging.info(_("Finished"))
if len(build_succeeded) > 0:
logging.info(str(len(build_succeeded)) + ' builds succeeded')
if len(failed_apps) > 0:

View File

@ -30,6 +30,7 @@ from distutils.version import LooseVersion
import logging
import copy
from . import _
from . import common
from . import metadata
from .exception import VCSException, FDroidException, MetaDataException
@ -509,15 +510,15 @@ def main():
# Parse command line...
parser = ArgumentParser(usage="%(prog)s [options] [APPID [APPID ...]]")
common.setup_global_opts(parser)
parser.add_argument("appid", nargs='*', help="app-id to check for updates")
parser.add_argument("appid", nargs='*', help=_("app-id to check for updates"))
parser.add_argument("--auto", action="store_true", default=False,
help="Process auto-updates")
help=_("Process auto-updates"))
parser.add_argument("--autoonly", action="store_true", default=False,
help="Only process apps with auto-updates")
help=_("Only process apps with auto-updates"))
parser.add_argument("--commit", action="store_true", default=False,
help="Commit changes")
help=_("Commit changes"))
parser.add_argument("--gplay", action="store_true", default=False,
help="Only print differences with the Play Store")
help=_("Only print differences with the Play Store"))
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W
@ -567,7 +568,7 @@ def main():
except Exception as e:
logging.error("...checkupdate failed for {0} : {1}".format(appid, e))
logging.info("Finished.")
logging.info(_("Finished"))
if __name__ == "__main__":

View File

@ -49,6 +49,7 @@ from pyasn1.error import PyAsn1Error
from distutils.util import strtobool
import fdroidserver.metadata
from fdroidserver import _
from fdroidserver.exception import FDroidException, VCSException, BuildException
from .asynchronousfilereader import AsynchronousFileReader
@ -123,9 +124,9 @@ default_config = {
def setup_global_opts(parser):
parser.add_argument("-v", "--verbose", action="store_true", default=False,
help="Spew out even more information than normal")
help=_("Spew out even more information than normal"))
parser.add_argument("-q", "--quiet", action="store_true", default=False,
help="Restrict output to warnings and errors")
help=_("Restrict output to warnings and errors"))
def fill_config_defaults(thisconfig):

View File

@ -24,7 +24,9 @@ from time import sleep
from argparse import ArgumentParser
from subprocess import CalledProcessError, check_output
from fdroidserver import common, metadata
from . import _
from . import common
from . import metadata
try:
from docker import Client
@ -407,25 +409,25 @@ def main():
parser.add_argument(
"app_id", nargs='*',
help="app-id with optional versioncode in the form APPID[:VERCODE]")
help=_("app-id with optional versioncode in the form APPID[:VERCODE]"))
parser.add_argument(
"-l", "--latest", action="store_true", default=False,
help="Scan only the latest version of each package")
help=_("Scan only the latest version of each package"))
parser.add_argument(
"--clean-after", default=False, action='store_true',
help="Clean after all scans have finished")
help=_("Clean after all scans have finished"))
parser.add_argument(
"--clean-before", default=False, action='store_true',
help="Clean before the scans start and rebuild the container")
help=_("Clean before the scans start and rebuild the container"))
parser.add_argument(
"--clean-only", default=False, action='store_true',
help="Clean up all containers and then exit")
help=_("Clean up all containers and then exit"))
parser.add_argument(
"--init-only", default=False, action='store_true',
help="Prepare drozer to run a scan")
help=_("Prepare drozer to run a scan"))
parser.add_argument(
"--repo-path", default="repo", action="store",
help="Override path for repo APKs (default: ./repo)")
help=_("Override path for repo APKs (default: ./repo)"))
options = parser.parse_args()
config = common.read_config(options)

View File

@ -21,6 +21,7 @@ import glob
from argparse import ArgumentParser
import logging
from . import _
from . import common
from .common import FDroidPopen
from .exception import FDroidException
@ -46,7 +47,7 @@ def main():
for output_dir in repodirs:
if not os.path.isdir(output_dir):
raise FDroidException("Missing output directory '" + output_dir + "'")
raise FDroidException(_("Missing output directory") + " '" + output_dir + "'")
# Process any apks that are waiting to be signed...
for f in sorted(glob.glob(os.path.join(output_dir, '*.*'))):

View File

@ -26,6 +26,7 @@ from argparse import ArgumentParser
from configparser import ConfigParser
import logging
from . import _
from . import common
from . import metadata
from .exception import FDroidException
@ -59,7 +60,7 @@ def getrepofrompage(url):
repo = page[index + 9:]
index = repo.find('<')
if index == -1:
return (None, "Error while getting repo address")
return (None, _("Error while getting repo address"))
repo = repo[:index]
repo = repo.split('"')[0]
return (repotype, repo)
@ -71,12 +72,12 @@ def getrepofrompage(url):
repo = page[index + 10:]
index = repo.find('<')
if index == -1:
return (None, "Error while getting repo address")
return (None, _("Error while getting repo address"))
repo = repo[:index]
repo = repo.split('"')[0]
return (repotype, repo)
return (None, "No information found." + page)
return (None, _("No information found.") + page)
config = None
@ -87,7 +88,7 @@ def get_metadata_from_url(app, url):
tmp_dir = 'tmp'
if not os.path.isdir(tmp_dir):
logging.info("Creating temporary directory")
logging.info(_("Creating temporary directory"))
os.makedirs(tmp_dir)
# Figure out what kind of project it is...
@ -190,15 +191,15 @@ def main():
parser = ArgumentParser()
common.setup_global_opts(parser)
parser.add_argument("-u", "--url", default=None,
help="Project URL to import from.")
help=_("Project URL to import from."))
parser.add_argument("-s", "--subdir", default=None,
help="Path to main android project subdirectory, if not in root.")
help=_("Path to main android project subdirectory, if not in root."))
parser.add_argument("-c", "--categories", default=None,
help="Comma separated list of categories.")
help=_("Comma separated list of categories."))
parser.add_argument("-l", "--license", default=None,
help="Overall license of the project.")
help=_("Overall license of the project."))
parser.add_argument("--rev", default=None,
help="Allows a different revision (or git branch) to be specified for the initial import")
help=_("Allows a different revision (or git branch) to be specified for the initial import"))
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W
@ -214,7 +215,7 @@ def main():
local_metadata_files = common.get_local_metadata_files()
if local_metadata_files != []:
raise FDroidException("This repo already has local metadata: %s" % local_metadata_files[0])
raise FDroidException(_("This repo already has local metadata: %s") % local_metadata_files[0])
if options.url is None and os.path.isdir('.git'):
app.AutoName = os.path.basename(os.getcwd())
@ -252,11 +253,11 @@ def main():
versionName, versionCode, package = common.parse_androidmanifests(paths, app)
if not package:
raise FDroidException("Couldn't find package ID")
raise FDroidException(_("Couldn't find package ID"))
if not versionName:
logging.warn("Couldn't find latest version name")
logging.warn(_("Couldn't find latest version name"))
if not versionCode:
logging.warn("Couldn't find latest version code")
logging.warn(_("Couldn't find latest version code"))
else:
spec = os.path.join(root_dir, 'buildozer.spec')
if os.path.exists(spec):
@ -268,7 +269,7 @@ def main():
versionName = bconfig.get('app', 'version')
versionCode = None
else:
raise FDroidException("No android or kivy project could be found. Specify --subdir?")
raise FDroidException(_("No android or kivy project could be found. Specify --subdir?"))
# Make sure it's actually new...
if package in apps:

View File

@ -34,7 +34,11 @@ from binascii import hexlify, unhexlify
from datetime import datetime
from xml.dom.minidom import Document
from fdroidserver import metadata, signindex, common, net
from . import _
from . import common
from . import metadata
from . import net
from . import signindex
from fdroidserver.common import FDroidPopen, FDroidPopenBytes
from fdroidserver.exception import FDroidException, VerificationException, MetaDataException
@ -62,16 +66,16 @@ def make(apps, sortedids, apks, repodir, archive):
if not common.options.nosign:
if 'repo_keyalias' not in common.config:
nosigningkey = True
logging.critical("'repo_keyalias' not found in config.py!")
logging.critical(_("'repo_keyalias' not found in config.py!"))
if 'keystore' not in common.config:
nosigningkey = True
logging.critical("'keystore' not found in config.py!")
logging.critical(_("'keystore' not found in config.py!"))
if 'keystorepass' not in common.config:
nosigningkey = True
logging.critical("'keystorepass' not found in config.py!")
logging.critical(_("'keystorepass' not found in config.py!"))
if 'keypass' not in common.config:
nosigningkey = True
logging.critical("'keypass' not found in config.py!")
logging.critical(_("'keypass' not found in config.py!"))
if not os.path.exists(common.config['keystore']):
nosigningkey = True
logging.critical("'" + common.config['keystore'] + "' does not exist!")
@ -104,7 +108,7 @@ def make(apps, sortedids, apks, repodir, archive):
for mirror in sorted(common.config.get('mirrors', [])):
base = os.path.basename(urllib.parse.urlparse(mirror).path.rstrip('/'))
if common.config.get('nonstandardwebroot') is not True and base != 'fdroid':
logging.error("mirror '" + mirror + "' does not end with 'fdroid'!")
logging.error(_("mirror '%s' does not end with 'fdroid'!") % mirror)
mirrorcheckfailed = True
# must end with / or urljoin strips a whole path segment
if mirror.endswith('/'):
@ -115,7 +119,7 @@ def make(apps, sortedids, apks, repodir, archive):
for url in get_mirror_service_urls(mirror):
mirrors.append(url + '/' + repodir)
if mirrorcheckfailed:
raise FDroidException("Malformed repository mirrors.")
raise FDroidException(_("Malformed repository mirrors."))
if mirrors:
repodict['mirrors'] = mirrors
@ -144,7 +148,7 @@ def make(apps, sortedids, apks, repodir, archive):
elif all(isinstance(item, str) for item in common.config[key]):
packageNames = common.config[key]
else:
raise TypeError('only accepts strings, lists, and tuples')
raise TypeError(_('only accepts strings, lists, and tuples'))
requestsdict[command] = packageNames
make_v0(appsWithPackages, apks, repodir, repodict, requestsdict)
@ -199,7 +203,7 @@ def make_v1(apps, packages, repodir, repodict, requestsdict):
for package in packages:
packageName = package['packageName']
if packageName not in apps:
logging.info('Ignoring package without metadata: ' + package['apkName'])
logging.info(_('Ignoring package without metadata: ') + package['apkName'])
continue
if packageName in output_packages:
packagelist = output_packages[packageName]
@ -224,7 +228,7 @@ def make_v1(apps, packages, repodir, repodict, requestsdict):
json.dump(output, fp, default=_index_encoder_default)
if common.options.nosign:
logging.debug('index-v1 must have a signature, use `fdroid signindex` to create it!')
logging.debug(_('index-v1 must have a signature, use `fdroid signindex` to create it!'))
else:
signindex.config = common.config
signindex.sign_index_v1(repodir, json_name)
@ -501,9 +505,9 @@ def make_v0(apps, apks, repodir, repodict, requestsdict):
if 'repo_keyalias' in common.config:
if common.options.nosign:
logging.info("Creating unsigned index in preparation for signing")
logging.info(_("Creating unsigned index in preparation for signing"))
else:
logging.info("Creating signed index with this key (SHA256):")
logging.info(_("Creating signed index with this key (SHA256):"))
logging.info("%s" % repo_pubkey_fingerprint)
# Create a jar of the index...
@ -613,7 +617,7 @@ def download_repo_index(url_str, etag=None, verify_fingerprint=True):
if verify_fingerprint:
query = urllib.parse.parse_qs(url.query)
if 'fingerprint' not in query:
raise VerificationException("No fingerprint in URL.")
raise VerificationException(_("No fingerprint in URL."))
fingerprint = query['fingerprint'][0]
url = urllib.parse.SplitResult(url.scheme, url.netloc, url.path + '/index-v1.jar', '', '')
@ -635,7 +639,7 @@ def download_repo_index(url_str, etag=None, verify_fingerprint=True):
# compare the fingerprint if verify_fingerprint is True
if verify_fingerprint and fingerprint.upper() != public_key_fingerprint:
raise VerificationException("The repository's fingerprint does not match.")
raise VerificationException(_("The repository's fingerprint does not match."))
# load repository index from JSON
index = json.loads(jar.read('index-v1.json').decode("utf-8"))
@ -655,7 +659,7 @@ def verify_jar_signature(file):
:raises: VerificationException() if the JAR's signature could not be verified
"""
if not common.verify_apk_signature(file, jar=True):
raise VerificationException("The repository's index could not be verified.")
raise VerificationException(_("The repository's index could not be verified."))
def get_public_key_from_jar(jar):
@ -670,9 +674,9 @@ def get_public_key_from_jar(jar):
# extract certificate from jar
certs = [n for n in jar.namelist() if common.CERT_PATH_REGEX.match(n)]
if len(certs) < 1:
raise VerificationException("Found no signing certificates for repository.")
raise VerificationException(_("Found no signing certificates for repository."))
if len(certs) > 1:
raise VerificationException("Found multiple signing certificates for repository.")
raise VerificationException(_("Found multiple signing certificates for repository."))
# extract public key from certificate
public_key = common.get_certificate(jar.read(certs[0]))

View File

@ -27,6 +27,7 @@ import sys
from argparse import ArgumentParser
import logging
from . import _
from . import common
from .exception import FDroidException
@ -53,15 +54,15 @@ def main():
parser = ArgumentParser()
common.setup_global_opts(parser)
parser.add_argument("-d", "--distinguished-name", default=None,
help="X.509 'Distiguished Name' used when generating keys")
help=_("X.509 'Distiguished Name' used when generating keys"))
parser.add_argument("--keystore", default=None,
help="Path to the keystore for the repo signing key")
help=_("Path to the keystore for the repo signing key"))
parser.add_argument("--repo-keyalias", default=None,
help="Alias of the repo signing key in the keystore")
help=_("Alias of the repo signing key in the keystore"))
parser.add_argument("--android-home", default=None,
help="Path to the Android SDK (sometimes set in ANDROID_HOME)")
help=_("Path to the Android SDK (sometimes set in ANDROID_HOME)"))
parser.add_argument("--no-prompt", action="store_true", default=False,
help="Do not prompt for Android SDK path, just fail")
help=_("Do not prompt for Android SDK path, just fail"))
options = parser.parse_args()
# find root install prefix
@ -106,8 +107,7 @@ def main():
'AppData', 'Local', 'Android', 'android-sdk')
while not options.no_prompt:
try:
s = input('Enter the path to the Android SDK ('
+ default_sdk_path + ') here:\n> ')
s = input(_('Enter the path to the Android SDK (%s) here:\n> ') % default_sdk_path)
except KeyboardInterrupt:
print('')
sys.exit(1)
@ -231,21 +231,20 @@ def main():
common.write_to_config(test_config, 'keydname', c['keydname'])
common.genkeystore(c)
logging.info('Built repo based in "' + fdroiddir + '"')
logging.info('with this config:')
logging.info(' Android SDK:\t\t\t' + config['sdk_path'])
msg = '\n'
msg += _('Built repo based in "%s" with this config:') % fdroiddir
msg += '\n\n Android SDK:\t\t\t' + config['sdk_path']
if aapt:
logging.info(' Android SDK Build Tools:\t' + os.path.dirname(aapt))
logging.info(' Android NDK r12b (optional):\t$ANDROID_NDK')
logging.info(' Keystore for signing key:\t' + keystore)
msg += '\n Android SDK Build Tools:\t' + os.path.dirname(aapt)
msg += '\n Android NDK r12b (optional):\t$ANDROID_NDK'
msg += '\n ' + _('Keystore for signing key:\t') + keystore
if repo_keyalias is not None:
logging.info(' Alias for key in store:\t' + repo_keyalias)
logging.info('\nTo complete the setup, add your APKs to "' +
os.path.join(fdroiddir, 'repo') + '"' + '''
msg += '\n Alias for key in store:\t' + repo_keyalias
msg += '\n\n' + '''To complete the setup, add your APKs to "%s"
then run "fdroid update -c; fdroid update". You might also want to edit
"config.py" to set the URL, repo name, and more. You should also set up
a signing key (a temporary one might have been automatically generated).
For more info: https://f-droid.org/docs/Setup_an_F-Droid_App_Repo
and https://f-droid.org/docs/Signing_Process
''')
and https://f-droid.org/docs/Signing_Process''' % os.path.join(fdroiddir, 'repo')
logging.info(msg)

View File

@ -23,6 +23,7 @@ import glob
from argparse import ArgumentParser
import logging
from . import _
from . import common
from .common import SdkToolsPopen
from .exception import FDroidException
@ -49,19 +50,19 @@ def main():
# Parse command line...
parser = ArgumentParser(usage="%(prog)s [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
common.setup_global_opts(parser)
parser.add_argument("appid", nargs='*', help="app-id with optional versionCode in the form APPID[:VERCODE]")
parser.add_argument("appid", nargs='*', help=_("app-id with optional versionCode in the form APPID[:VERCODE]"))
parser.add_argument("-a", "--all", action="store_true", default=False,
help="Install all signed applications available")
help=_("Install all signed applications available"))
options = parser.parse_args()
if not options.appid and not options.all:
parser.error("option %s: If you really want to install all the signed apps, use --all" % "all")
parser.error(_("option %s: If you really want to install all the signed apps, use --all") % "all")
config = common.read_config(options)
output_dir = 'repo'
if not os.path.isdir(output_dir):
logging.info("No signed output directory - nothing to do")
logging.info(_("No signed output directory - nothing to do"))
sys.exit(0)
if options.appid:
@ -84,7 +85,7 @@ def main():
for appid, apk in apks.items():
if not apk:
raise FDroidException("No signed apk available for %s" % appid)
raise FDroidException(_("No signed apk available for %s") % appid)
else:
@ -95,10 +96,10 @@ def main():
# Get device list each time to avoid device not found errors
devs = devices()
if not devs:
raise FDroidException("No attached devices found")
logging.info("Installing %s..." % apk)
raise FDroidException(_("No attached devices found"))
logging.info(_("Installing %s...") % apk)
for dev in devs:
logging.info("Installing %s on %s..." % (apk, dev))
logging.info(_("Installing %s on %s...") % (apk, dev))
p = SdkToolsPopen(['adb', "-s", dev, "install", apk])
fail = ""
for line in p.output.splitlines():
@ -108,12 +109,12 @@ def main():
continue
if fail == "INSTALL_FAILED_ALREADY_EXISTS":
logging.warn("%s is already installed on %s." % (apk, dev))
logging.warn(_("%s is already installed on %s.") % (apk, dev))
else:
raise FDroidException("Failed to install %s on %s: %s" % (
raise FDroidException(_("Failed to install %s on %s: %s") % (
apk, dev, fail))
logging.info("\nFinished")
logging.info('\n' + _('Finished'))
if __name__ == "__main__":

View File

@ -22,6 +22,7 @@ import os
import re
import sys
from . import _
from . import common
from . import metadata
from . import rewritemeta
@ -47,7 +48,7 @@ https_enforcings = [
def forbid_shortener(domain):
return (re.compile(r'https?://[^/]*' + re.escape(domain) + r'/.*'),
"URL shorteners should not be used")
_("URL shorteners should not be used"))
http_url_shorteners = [
@ -62,9 +63,9 @@ http_url_shorteners = [
http_checks = https_enforcings + http_url_shorteners + [
(re.compile(r'.*github\.com/[^/]+/[^/]+\.git'),
"Appending .git is not necessary"),
_("Appending .git is not necessary")),
(re.compile(r'.*://[^/]*(github|gitlab|bitbucket|rawgit)[^/]*/([^/]+/){1,3}master'),
"Use /HEAD instead of /master to point at a file in the default branch"),
_("Use /HEAD instead of /master to point at a file in the default branch")),
]
regex_checks = {
@ -73,44 +74,44 @@ regex_checks = {
'Repo': https_enforcings,
'IssueTracker': http_checks + [
(re.compile(r'.*github\.com/[^/]+/[^/]+/*$'),
"/issues is missing"),
_("/issues is missing")),
(re.compile(r'.*gitlab\.com/[^/]+/[^/]+/*$'),
"/issues is missing"),
_("/issues is missing")),
],
'Donate': http_checks + [
(re.compile(r'.*flattr\.com'),
"Flattr donation methods belong in the FlattrID flag"),
_("Flattr donation methods belong in the FlattrID flag")),
],
'Changelog': http_checks,
'Author Name': [
(re.compile(r'^\s'),
"Unnecessary leading space"),
_("Unnecessary leading space")),
(re.compile(r'.*\s$'),
"Unnecessary trailing space"),
_("Unnecessary trailing space")),
],
'Summary': [
(re.compile(r'.*\b(free software|open source)\b.*', re.IGNORECASE),
"No need to specify that the app is Free Software"),
_("No need to specify that the app is Free Software")),
(re.compile(r'.*((your|for).*android|android.*(app|device|client|port|version))', re.IGNORECASE),
"No need to specify that the app is for Android"),
_("No need to specify that the app is for Android")),
(re.compile(r'.*[a-z0-9][.!?]( |$)'),
"Punctuation should be avoided"),
_("Punctuation should be avoided")),
(re.compile(r'^\s'),
"Unnecessary leading space"),
_("Unnecessary leading space")),
(re.compile(r'.*\s$'),
"Unnecessary trailing space"),
_("Unnecessary trailing space")),
],
'Description': [
(re.compile(r'\s*[*#][^ .]'),
"Invalid bulleted list"),
_("Invalid bulleted list")),
(re.compile(r'^\s'),
"Unnecessary leading space"),
_("Unnecessary leading space")),
(re.compile(r'.*\s$'),
"Unnecessary trailing space"),
_("Unnecessary trailing space")),
(re.compile(r'.*([^[]|^)\[[^:[\]]+( |\]|$)'),
"Invalid link - use [http://foo.bar Link title] or [http://foo.bar]"),
_("Invalid link - use [http://foo.bar Link title] or [http://foo.bar]")),
(re.compile(r'(^|.* )https?://[^ ]+'),
"Unlinkified link - use [http://foo.bar Link title] or [http://foo.bar]"),
_("Unlinkified link - use [http://foo.bar Link title] or [http://foo.bar]")),
],
}
@ -155,7 +156,7 @@ def check_ucm_tags(app):
and lastbuild.versionCode == app.CurrentVersionCode
and not lastbuild.forcevercode
and any(s in lastbuild.commit for s in '.,_-/')):
yield "Last used commit '%s' looks like a tag, but Update Check Mode is '%s'" % (
yield _("Last used commit '%s' looks like a tag, but Update Check Mode is '%s'") % (
lastbuild.commit, app.UpdateCheckMode)
@ -163,11 +164,11 @@ def check_char_limits(app):
limits = config['char_limits']
if len(app.Summary) > limits['summary']:
yield "Summary of length %s is over the %i char limit" % (
yield _("Summary of length %s is over the %i char limit") % (
len(app.Summary), limits['summary'])
if len(app.Description) > limits['description']:
yield "Description of length %s is over the %i char limit" % (
yield _("Description of length %s is over the %i char limit") % (
len(app.Description), limits['description'])
@ -185,12 +186,12 @@ def check_old_links(app):
for f in ['WebSite', 'SourceCode', 'IssueTracker', 'Changelog']:
v = app.get(f)
if any(s in v for s in old_sites):
yield "App is in '%s' but has a link to '%s'" % (app.Repo, v)
yield _("App is in '%s' but has a link to '%s'") % (app.Repo, v)
def check_useless_fields(app):
if app.UpdateCheckName == app.id:
yield "Update Check Name is set to the known app id - it can be removed"
yield _("Update Check Name is set to the known app id - it can be removed")
filling_ucms = re.compile(r'^(Tags.*|RepoManifest.*)')
@ -199,12 +200,12 @@ filling_ucms = re.compile(r'^(Tags.*|RepoManifest.*)')
def check_checkupdates_ran(app):
if filling_ucms.match(app.UpdateCheckMode):
if not app.AutoName and not app.CurrentVersion and app.CurrentVersionCode == '0':
yield "UCM is set but it looks like checkupdates hasn't been run yet"
yield _("UCM is set but it looks like checkupdates hasn't been run yet")
def check_empty_fields(app):
if not app.Categories:
yield "Categories are not set"
yield _("Categories are not set")
all_categories = set([
@ -231,12 +232,12 @@ all_categories = set([
def check_categories(app):
for categ in app.Categories:
if categ not in all_categories:
yield "Category '%s' is not valid" % categ
yield _("Category '%s' is not valid" % categ)
def check_duplicates(app):
if app.Name and app.Name == app.AutoName:
yield "Name '%s' is just the auto name - remove it" % app.Name
yield _("Name '%s' is just the auto name - remove it") % app.Name
links_seen = set()
for f in ['Source Code', 'Web Site', 'Issue Tracker', 'Changelog']:
@ -245,25 +246,25 @@ def check_duplicates(app):
continue
v = v.lower()
if v in links_seen:
yield "Duplicate link in '%s': %s" % (f, v)
yield _("Duplicate link in '%s': %s") % (f, v)
else:
links_seen.add(v)
name = app.Name or app.AutoName
if app.Summary and name:
if app.Summary.lower() == name.lower():
yield "Summary '%s' is just the app's name" % app.Summary
yield _("Summary '%s' is just the app's name") % app.Summary
if app.Summary and app.Description and len(app.Description) == 1:
if app.Summary.lower() == app.Description[0].lower():
yield "Description '%s' is just the app's summary" % app.Summary
yield _("Description '%s' is just the app's summary") % app.Summary
seenlines = set()
for l in app.Description.splitlines():
if len(l) < 1:
continue
if l in seenlines:
yield "Description has a duplicate line"
yield _("Description has a duplicate line")
seenlines.add(l)
@ -276,7 +277,7 @@ def check_mediawiki_links(app):
url = um.group(1)
for m, r in http_checks:
if m.match(url):
yield "URL '%s' in Description: %s" % (url, r)
yield _("URL '%s' in Description: %s") % (url, r)
def check_bulleted_lists(app):
@ -291,7 +292,7 @@ def check_bulleted_lists(app):
if l[0] == lchar and l[1] == ' ':
lcount += 1
if lcount > 2 and lchar not in validchars:
yield "Description has a list (%s) but it isn't bulleted (*) nor numbered (#)" % lchar
yield _("Description has a list (%s) but it isn't bulleted (*) nor numbered (#)") % lchar
break
else:
lchar = l[0]
@ -304,18 +305,18 @@ def check_builds(app):
for build in app.builds:
if build.disable:
if build.disable.startswith('Generated by import.py'):
yield "Build generated by `fdroid import` - remove disable line once ready"
yield _("Build generated by `fdroid import` - remove disable line once ready")
continue
for s in ['master', 'origin', 'HEAD', 'default', 'trunk']:
if build.commit and build.commit.startswith(s):
yield "Branch '%s' used as commit in build '%s'" % (s, build.versionName)
yield _("Branch '%s' used as commit in build '%s'") % (s, build.versionName)
for srclib in build.srclibs:
ref = srclib.split('@')[1].split('/')[0]
if ref.startswith(s):
yield "Branch '%s' used as commit in srclib '%s'" % (s, srclib)
yield _("Branch '%s' used as commit in srclib '%s'") % (s, srclib)
for key in build.keys():
if key not in supported_flags:
yield key + ' is not an accepted build field'
yield _('%s is not an accepted build field') % key
def check_files_dir(app):
@ -326,7 +327,7 @@ def check_files_dir(app):
for name in os.listdir(dir_path):
path = os.path.join(dir_path, name)
if not (os.path.isfile(path) or name == 'signatures' or locale_pattern.match(name)):
yield "Found non-file at %s" % path
yield _("Found non-file at %s") % path
continue
files.add(name)
@ -334,25 +335,25 @@ def check_files_dir(app):
for build in app.builds:
for fname in build.patch:
if fname not in files:
yield "Unknown file %s in build '%s'" % (fname, build.versionName)
yield _("Unknown file %s in build '%s'") % (fname, build.versionName)
else:
used.add(fname)
for name in files.difference(used):
if locale_pattern.match(name):
continue
yield "Unused file at %s" % os.path.join(dir_path, name)
yield _("Unused file at %s") % os.path.join(dir_path, name)
def check_format(app):
if options.format and not rewritemeta.proper_format(app):
yield "Run rewritemeta to fix formatting"
yield _("Run rewritemeta to fix formatting")
def check_license_tag(app):
'''Ensure all license tags are in https://spdx.org/license-list'''
if app.License.rstrip('+') not in SPDX:
yield 'Invalid license tag "%s"! Use only tags from https://spdx.org/license-list' \
yield _('Invalid license tag "%s"! Use only tags from https://spdx.org/license-list') \
% (app.License)
@ -368,7 +369,7 @@ def check_extlib_dir(apps):
for build in app.builds:
for path in build.extlibs:
if path not in unused_extlib_files:
yield "%s: Unknown extlib %s in build '%s'" % (app.id, path, build.versionName)
yield _("%s: Unknown extlib %s in build '%s'") % (app.id, path, build.versionName)
else:
used.add(path)
@ -381,7 +382,7 @@ def check_extlib_dir(apps):
'NOTICE', 'NOTICE.txt',
]):
continue
yield "Unused extlib at %s" % os.path.join(dir_path, path)
yield _("Unused extlib at %s") % os.path.join(dir_path, path)
def check_for_unsupported_metadata_files(basedir=""):
@ -397,7 +398,7 @@ def check_for_unsupported_metadata_files(basedir=""):
for t in formats:
exists = exists or os.path.exists(f + '.' + t)
if not exists:
print('"' + f + '/" has no matching metadata file!')
print(_('"%s/" has no matching metadata file!') % f)
return_value = True
elif not os.path.splitext(f)[1][1:] in formats:
print('"' + f.replace(basedir, '')
@ -415,8 +416,8 @@ def main():
parser = ArgumentParser(usage="%(prog)s [options] [APPID [APPID ...]]")
common.setup_global_opts(parser)
parser.add_argument("-f", "--format", action="store_true", default=False,
help="Also warn about formatting issues, like rewritemeta -l")
parser.add_argument("appid", nargs='*', help="app-id in the form APPID")
help=_("Also warn about formatting issues, like rewritemeta -l"))
parser.add_argument("appid", nargs='*', help=_("app-id in the form APPID"))
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W

View File

@ -35,6 +35,7 @@ except ImportError:
YamlLoader = Loader
import fdroidserver.common
from fdroidserver import _
from fdroidserver.exception import MetaDataException, FDroidException
srclibs = None
@ -1519,4 +1520,4 @@ def write_metadata(metadatapath, app):
def add_metadata_arguments(parser):
'''add common command line flags related to metadata processing'''
parser.add_argument("-W", default='error',
help="force errors to be warnings, or ignore")
help=_("force errors to be warnings, or ignore"))

View File

@ -26,6 +26,7 @@ import hashlib
from argparse import ArgumentParser
import logging
from . import _
from . import common
from . import metadata
from .common import FDroidPopen, SdkToolsPopen
@ -43,7 +44,7 @@ def main():
parser = ArgumentParser(usage="%(prog)s [options] "
"[APPID[:VERCODE] [APPID[:VERCODE] ...]]")
common.setup_global_opts(parser)
parser.add_argument("appid", nargs='*', help="app-id with optional versionCode in the form APPID[:VERCODE]")
parser.add_argument("appid", nargs='*', help=_("app-id with optional versionCode in the form APPID[:VERCODE]"))
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W
@ -51,27 +52,27 @@ def main():
config = common.read_config(options)
if not ('jarsigner' in config and 'keytool' in config):
logging.critical('Java JDK not found! Install in standard location or set java_paths!')
logging.critical(_('Java JDK not found! Install in standard location or set java_paths!'))
sys.exit(1)
log_dir = 'logs'
if not os.path.isdir(log_dir):
logging.info("Creating log directory")
logging.info(_("Creating log directory"))
os.makedirs(log_dir)
tmp_dir = 'tmp'
if not os.path.isdir(tmp_dir):
logging.info("Creating temporary directory")
logging.info(_("Creating temporary directory"))
os.makedirs(tmp_dir)
output_dir = 'repo'
if not os.path.isdir(output_dir):
logging.info("Creating output directory")
logging.info(_("Creating output directory"))
os.makedirs(output_dir)
unsigned_dir = 'unsigned'
if not os.path.isdir(unsigned_dir):
logging.warning("No unsigned directory - nothing to do")
logging.warning(_("No unsigned directory - nothing to do"))
sys.exit(1)
if not os.path.exists(config['keystore']):
@ -95,7 +96,7 @@ def main():
m.update(appid.encode('utf-8'))
keyalias = m.hexdigest()[:8]
if keyalias in allaliases:
logging.error("There is a keyalias collision - publishing halted")
logging.error(_("There is a keyalias collision - publishing halted"))
sys.exit(1)
allaliases.append(keyalias)
logging.info("{0} apps, {0} key aliases".format(len(allapps),
@ -208,13 +209,13 @@ def main():
'SHA1withRSA', '-digestalg', 'SHA1',
apkfile, keyalias], envs=env_vars)
if p.returncode != 0:
raise BuildException("Failed to sign application")
raise BuildException(_("Failed to sign application"))
# Zipalign it...
p = SdkToolsPopen(['zipalign', '-v', '4', apkfile,
os.path.join(output_dir, apkfilename)])
if p.returncode != 0:
raise BuildException("Failed to align application")
raise BuildException(_("Failed to align application"))
os.remove(apkfile)
# Move the source tarball into the output directory...

View File

@ -22,6 +22,7 @@ import os
import logging
import io
from . import _
from . import common
from . import metadata
@ -51,10 +52,10 @@ def main():
parser = ArgumentParser(usage="%(prog)s [options] [APPID [APPID ...]]")
common.setup_global_opts(parser)
parser.add_argument("-l", "--list", action="store_true", default=False,
help="List files that would be reformatted")
help=_("List files that would be reformatted"))
parser.add_argument("-t", "--to", default=None,
help="Rewrite to a specific format: " + ', '.join(supported))
parser.add_argument("appid", nargs='*', help="app-id in the form APPID")
help=_("Rewrite to a specific format: ") + ', '.join(supported))
parser.add_argument("appid", nargs='*', help=_("app-id in the form APPID"))
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W
@ -66,21 +67,21 @@ def main():
apps = common.read_app_args(options.appid, allapps, False)
if options.list and options.to is not None:
parser.error("Cannot use --list and --to at the same time")
parser.error(_("Cannot use --list and --to at the same time"))
if options.to is not None and options.to not in supported:
parser.error("Unsupported metadata format, use: --to [" + ' '.join(supported) + "]")
parser.error(_("Unsupported metadata format, use: --to [%s]") % ' '.join(supported))
for appid, app in apps.items():
path = app.metadatapath
base, ext = common.get_extension(path)
if not options.to and ext not in supported:
logging.info("Ignoring %s file at '%s'" % (ext, path))
logging.info(_("Ignoring %s file at '%s'") % (ext, path))
continue
elif options.to is not None:
logging.info("rewriting '%s' to %s" % (appid, options.to))
logging.info(_("rewriting '%s' to %s") % (appid, options.to))
else:
logging.info("rewriting '%s'" % (appid))
logging.info(_("rewriting '%s'") % (appid))
to_ext = ext
if options.to is not None:
@ -107,7 +108,7 @@ def main():
if ext != to_ext:
os.remove(path)
logging.debug("Finished.")
logging.debug(_("Finished"))
if __name__ == "__main__":

View File

@ -22,6 +22,7 @@ import traceback
from argparse import ArgumentParser
import logging
from . import _
from . import common
from . import metadata
from .exception import BuildException, VCSException
@ -256,7 +257,7 @@ def main():
# Parse command line...
parser = ArgumentParser(usage="%(prog)s [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
common.setup_global_opts(parser)
parser.add_argument("appid", nargs='*', help="app-id with optional versionCode in the form APPID[:VERCODE]")
parser.add_argument("appid", nargs='*', help=_("app-id with optional versionCode in the form APPID[:VERCODE]"))
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W
@ -329,8 +330,8 @@ def main():
appid, traceback.format_exc()))
probcount += 1
logging.info("Finished:")
print("%d problems found" % probcount)
logging.info(_("Finished"))
print(_("%d problems found") % probcount)
if __name__ == "__main__":

View File

@ -29,6 +29,7 @@ from argparse import ArgumentParser
import logging
import shutil
from . import _
from . import common
from .exception import FDroidException
@ -577,19 +578,19 @@ def main():
# Parse command line...
parser = ArgumentParser()
common.setup_global_opts(parser)
parser.add_argument("command", help="command to execute, either 'init' or 'update'")
parser.add_argument("command", help=_("command to execute, either 'init' or 'update'"))
parser.add_argument("-i", "--identity-file", default=None,
help="Specify an identity file to provide to SSH for rsyncing")
help=_("Specify an identity file to provide to SSH for rsyncing"))
parser.add_argument("--local-copy-dir", default=None,
help="Specify a local folder to sync the repo to")
help=_("Specify a local folder to sync the repo to"))
parser.add_argument("--no-checksum", action="store_true", default=False,
help="Don't use rsync checksums")
help=_("Don't use rsync checksums"))
options = parser.parse_args()
config = common.read_config(options)
if options.command != 'init' and options.command != 'update':
logging.critical("The only commands currently supported are 'init' and 'update'")
logging.critical(_("The only commands currently supported are 'init' and 'update'"))
sys.exit(1)
if config.get('nonstandardwebroot') is True:
@ -605,7 +606,7 @@ def main():
elif len(s) == 2:
host, fdroiddir = s
else:
logging.error('Malformed serverwebroot line: ' + serverwebroot)
logging.error(_('Malformed serverwebroot line:') + ' ' + serverwebroot)
sys.exit(1)
repobase = os.path.basename(fdroiddir)
if standardwebroot and repobase != 'fdroid':
@ -624,7 +625,7 @@ def main():
if local_copy_dir is not None:
fdroiddir = local_copy_dir.rstrip('/')
if os.path.exists(fdroiddir) and not os.path.isdir(fdroiddir):
logging.error('local_copy_dir must be directory, not a file!')
logging.error(_('local_copy_dir must be directory, not a file!'))
sys.exit(1)
if not os.path.exists(os.path.dirname(fdroiddir)):
logging.error('The root dir for local_copy_dir "'
@ -632,7 +633,7 @@ def main():
+ '" does not exist!')
sys.exit(1)
if not os.path.isabs(fdroiddir):
logging.error('local_copy_dir must be an absolute path!')
logging.error(_('local_copy_dir must be an absolute path!'))
sys.exit(1)
repobase = os.path.basename(fdroiddir)
if standardwebroot and repobase != 'fdroid':
@ -652,8 +653,8 @@ def main():
and not config.get('binary_transparency_remote') \
and not config.get('virustotal_apikey') \
and local_copy_dir is None:
logging.warn('No option set! Edit your config.py to set at least one among:\n'
+ 'serverwebroot, servergitmirrors, local_copy_dir, awsbucket, virustotal_apikey, androidobservatory, or binary_transparency_remote')
logging.warn(_('No option set! Edit your config.py to set at least one of these:')
+ '\nserverwebroot, servergitmirrors, local_copy_dir, awsbucket, virustotal_apikey, androidobservatory, or binary_transparency_remote')
sys.exit(1)
repo_sections = ['repo']

View File

@ -22,6 +22,7 @@ import os
import sys
import logging
from . import _
from . import common
from . import net
from .exception import FDroidException
@ -52,7 +53,7 @@ def extract(config, options):
os.mkdir(tmp_dir)
if not options.APK or len(options.APK) <= 0:
logging.critical('no APK supplied')
logging.critical(_('no APK supplied'))
sys.exit(1)
# iterate over supplied APKs downlaod and extract them...
@ -61,21 +62,21 @@ def extract(config, options):
try:
if os.path.isfile(apk):
sigdir = extract_signature(apk)
logging.info('fetched singatures for %s -> %s', apk, sigdir)
logging.info(_('fetched signatures for %s -> %s'), apk, sigdir)
elif httpre.match(apk):
if apk.startswith('https') or options.no_check_https:
try:
tmp_apk = os.path.join(tmp_dir, 'signed.apk')
net.download_file(apk, tmp_apk)
sigdir = extract_signature(tmp_apk)
logging.info('fetched singatures for %s -> %s', apk, sigdir)
logging.info(_('fetched signatures for %s -> %s'), apk, sigdir)
finally:
if tmp_apk and os.path.exists(tmp_apk):
os.remove(tmp_apk)
else:
logging.warn('refuse downloading via insecure http connection (use https or specify --no-https-check): %s', apk)
logging.warn(_('refuse downloading via insecure http connection (use https or specify --no-https-check): %s'), apk)
except FDroidException as e:
logging.warning("failed fetching signatures for '%s': %s", apk, e)
logging.warning(_("failed fetching signatures for '%s': %s"), apk, e)
if e.detail:
logging.debug(e.detail)
@ -88,7 +89,7 @@ def main():
parser = ArgumentParser(usage="%(prog)s [options] APK [APK...]")
common.setup_global_opts(parser)
parser.add_argument("APK", nargs='*',
help="signed APK, either a file-path or Https-URL are fine here.")
help=_("signed APK, either a file-path or HTTPS URL."))
parser.add_argument("--no-check-https", action="store_true", default=False)
options = parser.parse_args()

View File

@ -21,6 +21,7 @@ import zipfile
from argparse import ArgumentParser
import logging
from . import _
from . import common
from .exception import FDroidException
@ -87,7 +88,7 @@ def main():
if 'jarsigner' not in config:
raise FDroidException(
'Java jarsigner not found! Install in standard location or set java_paths!')
_('Java jarsigner not found! Install in standard location or set java_paths!'))
repodirs = ['repo']
if config['archive_older'] != 0:
@ -114,7 +115,7 @@ def main():
signed += 1
if signed == 0:
logging.info("Nothing to do")
logging.info(_("Nothing to do"))
if __name__ == "__main__":

View File

@ -30,6 +30,7 @@ import logging
import subprocess
from collections import Counter
from . import _
from . import common
from . import metadata
@ -61,12 +62,12 @@ def main():
parser = ArgumentParser()
common.setup_global_opts(parser)
parser.add_argument("-d", "--download", action="store_true", default=False,
help="Download logs we don't have")
help=_("Download logs we don't have"))
parser.add_argument("--recalc", action="store_true", default=False,
help="Recalculate aggregate stats - use when changes "
"have been made that would invalidate old cached data.")
help=_("Recalculate aggregate stats - use when changes "
"have been made that would invalidate old cached data."))
parser.add_argument("--nologs", action="store_true", default=False,
help="Don't do anything logs-related")
help=_("Don't do anything logs-related"))
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W
@ -171,10 +172,10 @@ def main():
uri = match.group('uri')
if not uri.endswith('.apk'):
continue
_, apkname = os.path.split(uri)
_ignored, apkname = os.path.split(uri)
app = knownapks.getapp(apkname)
if app:
appid, _ = app
appid, _ignored = app
today['apps'][appid] += 1
# Strip the '.apk' from apkname
appver = apkname[:-4]
@ -298,7 +299,7 @@ def main():
for apk in unknownapks:
logging.info(apk)
logging.info("Finished.")
logging.info(_("Finished"))
if __name__ == "__main__":

View File

@ -37,6 +37,7 @@ from binascii import hexlify
from PIL import Image
import logging
from . import _
from . import common
from . import index
from . import metadata
@ -1697,34 +1698,34 @@ def main():
parser = ArgumentParser()
common.setup_global_opts(parser)
parser.add_argument("--create-key", action="store_true", default=False,
help="Create a repo signing key in a keystore")
help=_("Create a repo signing key in a keystore"))
parser.add_argument("-c", "--create-metadata", action="store_true", default=False,
help="Create skeleton metadata files that are missing")
help=_("Create skeleton metadata files that are missing"))
parser.add_argument("--delete-unknown", action="store_true", default=False,
help="Delete APKs and/or OBBs without metadata from the repo")
help=_("Delete APKs and/or OBBs without metadata from the repo"))
parser.add_argument("-b", "--buildreport", action="store_true", default=False,
help="Report on build data status")
help=_("Report on build data status"))
parser.add_argument("-i", "--interactive", default=False, action="store_true",
help="Interactively ask about things that need updating.")
help=_("Interactively ask about things that need updating."))
parser.add_argument("-I", "--icons", action="store_true", default=False,
help="Resize all the icons exceeding the max pixel size and exit")
help=_("Resize all the icons exceeding the max pixel size and exit"))
parser.add_argument("-e", "--editor", default="/etc/alternatives/editor",
help="Specify editor to use in interactive mode. Default " +
help=_("Specify editor to use in interactive mode. Default ") +
"is /etc/alternatives/editor")
parser.add_argument("-w", "--wiki", default=False, action="store_true",
help="Update the wiki")
help=_("Update the wiki"))
parser.add_argument("--pretty", action="store_true", default=False,
help="Produce human-readable index.xml")
help=_("Produce human-readable index.xml"))
parser.add_argument("--clean", action="store_true", default=False,
help="Clean update - don't uses caches, reprocess all apks")
help=_("Clean update - don't uses caches, reprocess all apks"))
parser.add_argument("--nosign", action="store_true", default=False,
help="When configured for signed indexes, create only unsigned indexes at this stage")
help=_("When configured for signed indexes, create only unsigned indexes at this stage"))
parser.add_argument("--use-date-from-apk", action="store_true", default=False,
help="Use date from apk instead of current time for newly added apks")
help=_("Use date from apk instead of current time for newly added apks"))
parser.add_argument("--rename-apks", action="store_true", default=False,
help="Rename APK files that do not match package.name_123.apk")
help=_("Rename APK files that do not match package.name_123.apk"))
parser.add_argument("--allow-disabled-algorithms", action="store_true", default=False,
help="Include APKs that are signed with disabled algorithms like MD5")
help=_("Include APKs that are signed with disabled algorithms like MD5"))
metadata.add_metadata_arguments(parser)
options = parser.parse_args()
metadata.warnings_action = options.W
@ -1899,7 +1900,7 @@ def main():
if options.wiki:
update_wiki(apps, sortedids, apks + archapks)
logging.info("Finished.")
logging.info(_("Finished"))
if __name__ == "__main__":

View File

@ -23,6 +23,7 @@ import requests
from argparse import ArgumentParser
import logging
from . import _
from . import common
from . import net
from .exception import FDroidException
@ -38,19 +39,19 @@ def main():
# Parse command line...
parser = ArgumentParser(usage="%(prog)s [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
common.setup_global_opts(parser)
parser.add_argument("appid", nargs='*', help="app-id with optional versionCode in the form APPID[:VERCODE]")
parser.add_argument("appid", nargs='*', help=_("app-id with optional versionCode in the form APPID[:VERCODE]"))
options = parser.parse_args()
config = common.read_config(options)
tmp_dir = 'tmp'
if not os.path.isdir(tmp_dir):
logging.info("Creating temporary directory")
logging.info(_("Creating temporary directory"))
os.makedirs(tmp_dir)
unsigned_dir = 'unsigned'
if not os.path.isdir(unsigned_dir):
logging.error("No unsigned directory - nothing to do")
logging.error(_("No unsigned directory - nothing to do"))
sys.exit(0)
verified = 0
@ -83,7 +84,7 @@ def main():
try:
net.download_file(url.replace('/repo', '/archive'), dldir=tmp_dir)
except requests.exceptions.HTTPError as e:
raise FDroidException('Downloading %s failed. %s', (url, e))
raise FDroidException(_('Downloading %s failed. %s'), (url, e))
compare_result = common.verify_apks(
remoteapk,
@ -99,7 +100,7 @@ def main():
logging.info("...NOT verified - {0}".format(e))
notverified += 1
logging.info("Finished")
logging.info(_("Finished"))
logging.info("{0} successfully verified".format(verified))
logging.info("{0} NOT verified".format(notverified))