0
0
Fork 0
mirror of https://github.com/boltgolt/howdy.git synced 2024-09-12 09:41:18 +02:00

Added getext translating function

This commit is contained in:
boltgolt 2020-12-31 14:15:17 +01:00
parent 473aa9807e
commit 55f3753260
No known key found for this signature in database
GPG key ID: BECEC9937E1AAE26
15 changed files with 152 additions and 115 deletions

View file

@ -8,6 +8,8 @@ import getpass
import argparse
import builtins
from i18n import _
# Try to get the original username (not "root") from shell
try:
user = os.getlogin()
@ -20,48 +22,48 @@ if user == "root" or user is None:
# If even that fails, error out
if env_user == "":
print("Could not determine user, please use the --user flag")
print(_("Could not determine user, please use the --user flag"))
sys.exit(1)
else:
user = env_user
# Basic command setup
parser = argparse.ArgumentParser(
description="Command line interface for Howdy face authentication.",
description=_("Command line interface for Howdy face authentication."),
formatter_class=argparse.RawDescriptionHelpFormatter,
add_help=False,
prog="howdy",
epilog="For support please visit\nhttps://github.com/boltgolt/howdy")
epilog=_("For support please visit\nhttps://github.com/boltgolt/howdy"))
# Add an argument for the command
parser.add_argument(
"command",
help="The command option to execute, can be one of the following: add, clear, config, disable, list, remove, snapshot, set, test or version.",
_("command"),
help=_("The command option to execute, can be one of the following: add, clear, config, disable, list, remove, snapshot, set, test or version."),
metavar="command",
choices=["add", "clear", "config", "disable", "list", "remove", "set", "snapshot", "test", "version"])
# Add an argument for the extra arguments of diable and remove
parser.add_argument(
"arguments",
help="Optional arguments for the add, disable, remove and set commands.",
_("arguments"),
help=_("Optional arguments for the add, disable, remove and set commands."),
nargs="*")
# Add the user flag
parser.add_argument(
"-U", "--user",
default=user,
help="Set the user account to use.")
help=_("Set the user account to use."))
# Add the -y flag
parser.add_argument(
"-y",
help="Skip all questions.",
help=_("Skip all questions."),
action="store_true")
# Add the --plain flag
parser.add_argument(
"--plain",
help="Print machine-friendly output.",
help=_("Print machine-friendly output."),
action="store_true")
# Overwrite the default help message so we can use a uppercase S
@ -69,11 +71,11 @@ parser.add_argument(
"-h", "--help",
action="help",
default=argparse.SUPPRESS,
help="Show this help message and exit.")
help=_("Show this help message and exit."))
# If we only have 1 argument we print the help text
if len(sys.argv) < 2:
print("current active user: " + user + "\n")
print(_("current active user: ") + user + "\n")
parser.print_help()
sys.exit(0)
@ -87,13 +89,13 @@ builtins.howdy_user = args.user
# Check if we have rootish rights
# This is this far down the file so running the command for help is always possible
if os.geteuid() != 0:
print("Please run this command as root:\n")
print(_("Please run this command as root:\n"))
print("\tsudo howdy " + " ".join(sys.argv[1:]))
sys.exit(1)
# Beond this point the user can't change anymore, if we still have root as user we need to abort
if args.user == "root":
print("Can't run howdy commands as root, please run this command with the --user flag")
print(_("Can't run howdy commands as root, please run this command with the --user flag"))
sys.exit(1)
# Execute the right command

View file

@ -8,7 +8,9 @@ import json
import configparser
import builtins
import numpy as np
from recorders.video_capture import VideoCapture
from i18n import _
# Try to import dlib and give a nice error if we can't
# Add should be the first point where import issues show up
@ -17,7 +19,7 @@ try:
except ImportError as err:
print(err)
print("\nCan't import the dlib module, check the output of")
print(_("\nCan't import the dlib module, check the output of"))
print("pip3 show dlib")
sys.exit(1)
@ -29,7 +31,7 @@ path = os.path.abspath(__file__ + "/..")
# Test if at lest 1 of the data files is there and abort if it's not
if not os.path.isfile(path + "/../dlib-data/shape_predictor_5_face_landmarks.dat"):
print("Data files have not been downloaded, please run the following commands:")
print(_("Data files have not been downloaded, please run the following commands:"))
print("\n\tcd " + os.path.realpath(path + "/../dlib-data"))
print("\tsudo ./install.sh\n")
sys.exit(1)
@ -55,7 +57,7 @@ encodings = []
# Make the ./models folder if it doesn't already exist
if not os.path.exists(path + "/../models"):
print("No face model folder found, creating one")
print(_("No face model folder found, creating one"))
os.makedirs(path + "/../models")
# To try read a premade encodings file if it exists
@ -66,30 +68,30 @@ except FileNotFoundError:
# Print a warning if too many encodings are being added
if len(encodings) > 3:
print("NOTICE: Each additional model slows down the face recognition engine slightly")
print("Press Ctrl+C to cancel\n")
print(_("NOTICE: Each additional model slows down the face recognition engine slightly"))
print(_("Press Ctrl+C to cancel\n"))
# Make clear what we are doing if not human
if not builtins.howdy_args.plain:
print("Adding face model for the user " + user)
print(_("Adding face model for the user " + user))
# Set the default label
label = "Initial model"
# Get the label from the cli arguments if provided
if builtins.howdy_args.arguments:
label = builtins.howdy_args.arguments[0]
label = builtins.howdy_args.arguments[0]
# If models already exist, set that default label
elif encodings:
label = "Model #" + str(len(encodings) + 1)
label = _("Model #") + str(len(encodings) + 1)
# Keep de default name if we can't ask questions
if builtins.howdy_args.y:
print('Using default label "%s" because of -y flag' % (label, ))
print(_('Using default label "%s" because of -y flag') % (label, ))
else:
# Ask the user for a custom label
label_in = input("Enter a label for this new model [" + label + "]: ")
label_in = input(_("Enter a label for this new model [{}]: ").format(label))
# Set the custom label (if any) and limit it to 24 characters
if label_in != "":
@ -97,7 +99,7 @@ else:
# Remove illegal characters
if "," in label:
print("NOTICE: Removing illegal character \",\" from model name")
print(_("NOTICE: Removing illegal character \",\" from model name"))
label = label.replace(",", "")
# Prepare the metadata for insertion
@ -111,7 +113,7 @@ insert_model = {
# Set up video_capture
video_capture = VideoCapture(config)
print("\nPlease look straight into the camera")
print(_("\nPlease look straight into the camera"))
# Give the user time to read
time.sleep(2)
@ -176,17 +178,17 @@ video_capture.release()
# If we've found no faces, try to determine why
if face_locations is None or not face_locations:
if valid_frames == 0:
print("Camera saw only black frames - is IR emitter working?")
print(_("Camera saw only black frames - is IR emitter working?"))
elif valid_frames == dark_tries:
print("All frames were too dark, please check dark_threshold in config")
print("Average darkness: " + str(dark_running_total / valid_frames) + ", Threshold: " + str(dark_threshold))
print(_("All frames were too dark, please check dark_threshold in config"))
print(_("Average darkness: {avg}, Threshold: {threshold}").format(avg=str(dark_running_total / valid_frames), threshold=str(dark_threshold)))
else:
print("No face detected, aborting")
print(_("No face detected, aborting"))
sys.exit(1)
# If more than 1 faces are detected we can't know wich one belongs to the user
elif len(face_locations) > 1:
print("Multiple faces detected, aborting")
print(_("Multiple faces detected, aborting"))
sys.exit(1)
face_location = face_locations[0]
@ -207,6 +209,5 @@ with open(enc_file, "w") as datafile:
json.dump(encodings, datafile)
# Give let the user know how it went
print("""Scan complete
Added a new model to """ + user)
print(_("""\nScan complete
Added a new model to """) + user)

View file

@ -5,6 +5,8 @@ import os
import sys
import builtins
from i18n import _
# Get the full path to this file
path = os.path.dirname(os.path.abspath(__file__))
# Get the passed user
@ -12,25 +14,25 @@ user = builtins.howdy_user
# Check if the models folder is there
if not os.path.exists(path + "/../models"):
print("No models created yet, can't clear them if they don't exist")
print(_("No models created yet, can't clear them if they don't exist"))
sys.exit(1)
# Check if the user has a models file to delete
if not os.path.isfile(path + "/../models/" + user + ".dat"):
print(user + " has no models or they have been cleared already")
print(_("{} has no models or they have been cleared already").format(user))
sys.exit(1)
# Only ask the user if there's no -y flag
if not builtins.howdy_args.y:
# Double check with the user
print("This will clear all models for " + user)
ans = input("Do you want to continue [y/N]: ")
print(_("This will clear all models for ") + user)
ans = input(_("Do you want to continue [y/N]: "))
# Abort if they don't answer y or Y
if (ans.lower() != "y"):
print('\nInerpeting as a "NO"')
print(_('\nInerpeting as a "NO", aborting'))
sys.exit(1)
# Delete otherwise
os.remove(path + "/../models/" + user + ".dat")
print("\nModels cleared")
print(_("\nModels cleared"))

View file

@ -4,8 +4,10 @@
import os
import subprocess
from i18n import _
# Let the user know what we're doing
print("Opening config.ini in the default editor")
print(_("Opening config.ini in the default editor"))
# Default to the nano editor
editor = "/bin/nano"

View file

@ -7,6 +7,8 @@ import builtins
import fileinput
import configparser
from i18n import _
# Get the absolute filepath
config_path = os.path.dirname(os.path.abspath(__file__)) + "/../config.ini"
@ -16,7 +18,7 @@ config.read(config_path)
# Check if enough arguments have been passed
if not builtins.howdy_args.arguments:
print("Please add a 0 (enable) or a 1 (disable) as an argument")
print(_("Please add a 0 (enable) or a 1 (disable) as an argument"))
sys.exit(1)
# Get the cli argument
@ -29,12 +31,12 @@ elif argument == "0" or argument.lower() == "false":
out_value = "false"
else:
# Of it's not a 0 or a 1, it's invalid
print("Please only use 0 (enable) or 1 (disable) as an argument")
print(_("Please only use 0 (enable) or 1 (disable) as an argument"))
sys.exit(1)
# Don't do anything when the state is already the requested one
if out_value == config.get("core", "disabled"):
print("The disable option has already been set to " + out_value)
print(_("The disable option has already been set to ") + out_value)
sys.exit(1)
# Loop though the config file and only replace the line containing the disable config
@ -43,6 +45,6 @@ for line in fileinput.input([config_path], inplace=1):
# Print what we just did
if out_value == "true":
print("Howdy has been disabled")
print(_("Howdy has been disabled"))
else:
print("Howdy has been enabled")
print(_("Howdy has been enabled"))

View file

@ -7,13 +7,15 @@ import json
import time
import builtins
from i18n import _
# Get the absolute path and the username
path = os.path.dirname(os.path.realpath(__file__)) + "/.."
user = builtins.howdy_user
# Check if the models file has been created yet
if not os.path.exists(path + "/models"):
print("Face models have not been initialized yet, please run:")
print(_("Face models have not been initialized yet, please run:"))
print("\n\tsudo howdy -U " + user + " add\n")
sys.exit(1)
@ -24,14 +26,14 @@ enc_file = path + "/models/" + user + ".dat"
try:
encodings = json.load(open(enc_file))
except FileNotFoundError:
print("No face model known for the user " + user + ", please run:")
print(_("No face model known for the user {}, please run:").format(user))
print("\n\tsudo howdy -U " + user + " add\n")
sys.exit(1)
# Print a header if we're not in plain mode
if not builtins.howdy_args.plain:
print("Known face models for " + user + ":")
print("\n\033[1;29mID Date Label\033[0m")
print(_("Known face models for {}:").format(user))
print("\n\033[1;29m" + _("ID Date Label\033[0m"))
# Loop through all encodings and print info about them
for enc in encodings:

View file

@ -6,22 +6,24 @@ import os
import json
import builtins
from i18n import _
# Get the absolute path and the username
path = os.path.dirname(os.path.realpath(__file__)) + "/.."
user = builtins.howdy_user
# Check if enough arguments have been passed
if not builtins.howdy_args.arguments:
print("Please add the ID of the model you want to remove as an argument")
print("For example:")
print(_("Please add the ID of the model you want to remove as an argument"))
print(_("For example:"))
print("\n\thowdy remove 0\n")
print("You can find the IDs by running:")
print(_("You can find the IDs by running:"))
print("\n\thowdy list\n")
sys.exit(1)
# Check if the models file has been created yet
if not os.path.exists(path + "/models"):
print("Face models have not been initialized yet, please run:")
print(_("Face models have not been initialized yet, please run:"))
print("\n\thowdy add\n")
sys.exit(1)
@ -32,7 +34,7 @@ enc_file = path + "/models/" + user + ".dat"
try:
encodings = json.load(open(enc_file))
except FileNotFoundError:
print("No face model known for the user " + user + ", please run:")
print(_("No face model known for the user " + user + ", please run:"))
print("\n\thowdy add\n")
sys.exit(1)
@ -48,12 +50,12 @@ for enc in encodings:
# Only ask the user if there's no -y flag
if not builtins.howdy_args.y:
# Double check with the user
print('This will remove the model called "' + enc["label"] + '" for ' + user)
ans = input("Do you want to continue [y/N]: ")
print(_('This will remove the model called "{label}" for {user}').format(label=enc["label"], user=user))
ans = input(_("Do you want to continue [y/N]: "))
# Abort if the answer isn't yes
if (ans.lower() != "y"):
print('\nInterpreting as a "NO", aborting')
print(_('\nInterpreting as a "NO", aborting'))
sys.exit(1)
# Add a padding empty line
@ -65,13 +67,13 @@ for enc in encodings:
# Abort if no matching id was found
if not found:
print("No model with ID " + id + " exists for " + user)
print(_("No model with ID {id} exists for {user}").format(id=id, user=user))
sys.exit(1)
# Remove the entire file if this encoding is the only one
if len(encodings) == 1:
os.remove(path + "/models/" + user + ".dat")
print("Removed last model, howdy disabled for user")
print(_("Removed last model, howdy disabled for user"))
else:
# A place holder to contain the encodings that will remain
new_encodings = []
@ -85,4 +87,4 @@ else:
with open(enc_file, "w") as datafile:
json.dump(new_encodings, datafile)
print("Removed model " + id)
print(_("Removed model {}").format(id))

View file

@ -6,13 +6,15 @@ import os
import builtins
import fileinput
from i18n import _
# Get the absolute filepath
config_path = os.path.dirname(os.path.abspath(__file__)) + "/../config.ini"
# Check if enough arguments have been passed
if len(builtins.howdy_args.arguments) < 2:
print("Please add a setting you would like to change and the value to set it to")
print("For example:")
print(_("Please add a setting you would like to change and the value to set it to"))
print(_("For example:"))
print("\n\thowdy set certainty 3\n")
sys.exit(1)
@ -31,11 +33,11 @@ for line in fileinput.input([config_path]):
# If we don't have the line it is not in the config file
if not found_line:
print('Could not find a "' + set_name + '" config option to set')
print(_('Could not find a "{}" config option to set').format(set_name))
sys.exit(1)
# Go through the file again and update the correct line
for line in fileinput.input([config_path], inplace=1):
print(line.replace(found_line, set_name + " = " + set_value + "\n"), end="")
print("Config option updated")
print(_("Config option updated"))

View file

@ -7,6 +7,8 @@ import datetime
import snapshot
from recorders.video_capture import VideoCapture
from i18n import _
# Get the absolute path to the current directory
path = os.path.abspath(__file__ + "/..")
@ -40,12 +42,12 @@ while True:
# Generate a snapshot image from the frames
file = snapshot.generate(frames, [
"GENERATED SNAPSHOT",
"Date: " + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
"Dark threshold config: " + str(config.getfloat("video", "dark_threshold", fallback=50.0)),
"Certainty config: " + str(config.getfloat("video", "certainty", fallback=3.5))
_("GENERATED SNAPSHOT"),
_("Date: ") + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
_("Dark threshold config: ") + str(config.getfloat("video", "dark_threshold", fallback=50.0)),
_("Certainty config: ") + str(config.getfloat("video", "certainty", fallback=3.5))
])
# Show the file location in console
print("Generated snapshot saved as")
print(_("Generated snapshot saved as"))
print(file)

View file

@ -9,6 +9,8 @@ import dlib
import cv2
from recorders.video_capture import VideoCapture
from i18n import _
# Get the absolute path to the current file
path = os.path.dirname(os.path.abspath(__file__))
@ -17,8 +19,7 @@ config = configparser.ConfigParser()
config.read(path + "/../config.ini")
if config.get("video", "recording_plugin") != "opencv":
print("Howdy has been configured to use a recorder which doesn't support the test command yet")
print("Aborting")
print(_("Howdy has been configured to use a recorder which doesn't support the test command yet, aborting"))
sys.exit(12)
video_capture = VideoCapture(config)
@ -28,12 +29,12 @@ exposure = config.getint("video", "exposure", fallback=-1)
dark_threshold = config.getfloat("video", "dark_threshold")
# Let the user know what's up
print("""
print(_("""
Opening a window with a test feed
Press ctrl+C in this terminal to quit
Click on the image to enable or disable slow mode
""")
"""))
def mouse(event, x, y, flags, param):
@ -97,7 +98,7 @@ try:
sec_frames = 0
# Grab a single frame of video
_, frame = video_capture.read_frame()
ret, frame = video_capture.read_frame()
frame = clahe.apply(frame)
# Make a frame to put overlays in
@ -127,22 +128,22 @@ try:
cv2.rectangle(overlay, p1, p2, (0, 200, 0), thickness=cv2.FILLED)
# Print the statis in the bottom left
print_text(0, "RESOLUTION: %dx%d" % (height, width))
print_text(1, "FPS: %d" % (fps, ))
print_text(2, "FRAMES: %d" % (total_frames, ))
print_text(3, "RECOGNITION: %dms" % (round(rec_tm * 1000), ))
print_text(0, _("RESOLUTION: %dx%d") % (height, width))
print_text(1, _("FPS: %d") % (fps, ))
print_text(2, _("FRAMES: %d") % (total_frames, ))
print_text(3, _("RECOGNITION: %dms") % (round(rec_tm * 1000), ))
# Show that slow mode is on, if it's on
if slow_mode:
cv2.putText(overlay, "SLOW MODE", (width - 66, height - 10), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 0, 255), 0, cv2.LINE_AA)
cv2.putText(overlay, _("SLOW MODE"), (width - 66, height - 10), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 0, 255), 0, cv2.LINE_AA)
# Ignore dark frames
if hist_perc[0] > dark_threshold:
# Show that this is an ignored frame in the top right
cv2.putText(overlay, "DARK FRAME", (width - 68, 16), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 0, 255), 0, cv2.LINE_AA)
cv2.putText(overlay, _("DARK FRAME"), (width - 68, 16), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 0, 255), 0, cv2.LINE_AA)
else:
# SHow that this is an active frame
cv2.putText(overlay, "SCAN FRAME", (width - 68, 16), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 255, 0), 0, cv2.LINE_AA)
cv2.putText(overlay, _("SCAN FRAME"), (width - 68, 16), cv2.FONT_HERSHEY_SIMPLEX, .3, (0, 255, 0), 0, cv2.LINE_AA)
rec_tm = time.time()
# Get the locations of all faces and their locations
@ -197,7 +198,7 @@ try:
# On ctrl+C
except KeyboardInterrupt:
# Let the user know we're stopping
print("\nClosing window")
print(_("\nClosing window"))
# Release handle to the webcam
cv2.destroyAllWindows()

View file

@ -20,7 +20,9 @@ import datetime
import snapshot
import numpy as np
import _thread as thread
from recorders.video_capture import VideoCapture
from i18n import _
def init_detector(lock):
@ -29,7 +31,7 @@ def init_detector(lock):
# Test if at lest 1 of the data files is there and abort if it's not
if not os.path.isfile(PATH + "/dlib-data/shape_predictor_5_face_landmarks.dat"):
print("Data files have not been downloaded, please run the following commands:")
print(_("Data files have not been downloaded, please run the following commands:"))
print("\n\tcd " + PATH + "/dlib-data")
print("\tsudo ./install.sh\n")
lock.release()
@ -53,12 +55,12 @@ def init_detector(lock):
def make_snapshot(type):
"""Generate snapshot after detection"""
snapshot.generate(snapframes, [
type + " LOGIN",
"Date: " + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
"Scan time: " + str(round(time.time() - timings["fr"], 2)) + "s",
"Frames: " + str(frames) + " (" + str(round(frames / (time.time() - timings["fr"]), 2)) + "FPS)",
"Hostname: " + os.uname().nodename,
"Best certainty value: " + str(round(lowest_certainty * 10, 1))
type + _(" LOGIN"),
_("Date: ") + datetime.datetime.utcnow().strftime("%Y/%m/%d %H:%M:%S UTC"),
_("Scan time: ") + str(round(time.time() - timings["fr"], 2)) + "s",
_("Frames: ") + str(frames) + " (" + str(round(frames / (time.time() - timings["fr"]), 2)) + "FPS)",
_("Hostname: ") + os.uname().nodename,
_("Best certainty value: ") + str(round(lowest_certainty * 10, 1))
])
@ -172,11 +174,11 @@ while True:
if time.time() - timings["fr"] > timeout:
# Create a timeout snapshot if enabled
if capture_failed:
make_snapshot("FAILED")
make_snapshot(_("FAILED"))
if dark_tries == valid_frames:
print("All frames were too dark, please check dark_threshold in config")
print("Average darkness: " + str(dark_running_total / max(1, valid_frames)) + ", Threshold: " + str(dark_threshold))
print(_("All frames were too dark, please check dark_threshold in config"))
print(_("Average darkness: {avg}, Threshold: {threshold}").format(avg=str(dark_running_total / max(1, valid_frames)), threshold=str(dark_threshold)))
sys.exit(13)
else:
sys.exit(11)
@ -255,32 +257,32 @@ while True:
print(" %s: %dms" % (label, round(timings[k] * 1000)))
# Print a nice timing report
print("Time spent")
print_timing("Starting up", "in")
print(" Open cam + load libs: %dms" % (round(max(timings["ll"], timings["ic"]) * 1000, )))
print_timing(" Opening the camera", "ic")
print_timing(" Importing recognition libs", "ll")
print_timing("Searching for known face", "fl")
print_timing("Total time", "tt")
print(_("Time spent"))
print_timing(_("Starting up"), "in")
print(_(" Open cam + load libs: %dms") % (round(max(timings["ll"], timings["ic"]) * 1000, )))
print_timing(_(" Opening the camera"), "ic")
print_timing(_(" Importing recognition libs"), "ll")
print_timing(_("Searching for known face"), "fl")
print_timing(_("Total time"), "tt")
print("\nResolution")
print(_("\nResolution"))
width = video_capture.fw or 1
print(" Native: %dx%d" % (height, width))
print(_(" Native: %dx%d") % (height, width))
# Save the new size for diagnostics
scale_height, scale_width = frame.shape[:2]
print(" Used: %dx%d" % (scale_height, scale_width))
print(_(" Used: %dx%d") % (scale_height, scale_width))
# Show the total number of frames and calculate the FPS by deviding it by the total scan time
print("\nFrames searched: %d (%.2f fps)" % (frames, frames / timings["fl"]))
print("Black frames ignored: %d " % (black_tries, ))
print("Dark frames ignored: %d " % (dark_tries, ))
print("Certainty of winning frame: %.3f" % (match * 10, ))
print(_("\nFrames searched: %d (%.2f fps)") % (frames, frames / timings["fl"]))
print(_("Black frames ignored: %d ") % (black_tries, ))
print(_("Dark frames ignored: %d ") % (dark_tries, ))
print(_("Certainty of winning frame: %.3f") % (match * 10, ))
print("Winning model: %d (\"%s\")" % (match_index, models[match_index]["label"]))
print(_("Winning model: %d (\"%s\")") % (match_index, models[match_index]["label"]))
# Make snapshot if enabled
if capture_successful:
make_snapshot("SUCCESSFUL")
make_snapshot(_("SUCCESSFUL"))
# Run rubberstamps if enabled
if config.getboolean("rubberstamps", "enabled", fallback=False):

12
src/i18n.py Normal file
View file

@ -0,0 +1,12 @@
# Support file for translations
# Import modules
import gettext
import os
# Get the right translation based on locale, falling back to base if none found
translation = gettext.translation("core", localedir=os.path.join(os.path.dirname(__file__), 'locales'), fallback=True)
translation.install()
# Export translation function as _
_ = translation.gettext

View file

@ -4,14 +4,16 @@
import numpy
import sys
import re
from subprocess import Popen, PIPE
from cv2 import CAP_PROP_FRAME_WIDTH
from cv2 import CAP_PROP_FRAME_HEIGHT
from i18n import _
try:
import ffmpeg
except ImportError:
print("Missing ffmpeg module, please run:")
print(_("Missing ffmpeg module, please run:"))
print(" pip3 install ffmpeg-python\n")
sys.exit(12)

View file

@ -1,16 +1,18 @@
# Class that simulates the functionality of opencv so howdy can use v4l2 devices seamlessly
# Import required modules. lib4l-dev package is also required.
from recorders import v4l2
import fcntl
import numpy
import sys
from recorders import v4l2
from cv2 import cvtColor, COLOR_GRAY2BGR, CAP_PROP_FRAME_WIDTH, CAP_PROP_FRAME_HEIGHT
from i18n import _
try:
from pyv4l2.frame import Frame
except ImportError:
print("Missing pyv4l2 module, please run:")
print(_("Missing pyv4l2 module, please run:"))
print(" pip3 install pyv4l2\n")
sys.exit(13)

View file

@ -7,6 +7,7 @@ import cv2
import os
import sys
from i18n import _
# Class to provide boilerplate code to build a video recorder with the
# correct settings from the config file.
@ -33,8 +34,8 @@ class VideoCapture:
# Check device path
if not os.path.exists(self.config.get("video", "device_path")):
if self.config.getboolean("video", "warn_no_device"):
print("Howdy could not find a camera device at the path specified in the config file.")
print("It is very likely that the path is not configured correctly, please edit the 'device_path' config value by running:")
print(_("Howdy could not find a camera device at the path specified in the config file."))
print(_("It is very likely that the path is not configured correctly, please edit the 'device_path' config value by running:"))
print("\n\tsudo howdy config\n")
sys.exit(1)
@ -81,7 +82,7 @@ class VideoCapture:
# Don't remove ret, it doesn't work without it
ret, frame = self.internal.read()
if not ret:
print("Failed to read camera specified in your 'device_path', aborting")
print(_("Failed to read camera specified in the 'device_path' config option, aborting"))
sys.exit(1)
try: