#!/usr/bin/env bash
define() { IFS='\n' read -r -d '' ${1} || true ; }
myname="${0##*/}"
define pod <<"=cut"
=head1 NAME
xlate - Front-end CLI tool for App::Greple::xlate module
=head1 SYNOPSIS
xlate [ options ] file [ greple options ]
-h help
-d debug
-a use API
-c just check translation area
-r refresh cache
-s silent mode
-p# pattern to determine translation area
-w# wrap line by # width
-o# output format (xtxt, cm, ifdef)
-f# from lang (ignored)
-t# to lang
-m# max length per API call
-l# show library files (XLATE.mk, xlate.el)
-- terminate option parsing
Make options
-M run make
-n run make with -n dry-run option
Docker options
-G mount git top-level directory
-B run in non-interactive (batch) mode
-R mount read-only
-D run xlate on the container
-C run any command on the container
Control Files:
*.LANG translation languates
*.FORMAT translation foramt (xtxt, cm, ifdef)
=head1 VERSION
Version 0.21
=cut
git_topdir() {
[ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" == true ] || return
local dir="$(git rev-parse --show-superproject-working-tree)"
[ "$dir" ] || dir="$(git rev-parse --show-toplevel)"
echo -n $dir
}
env_pattern() {
set +x
local name
while (( $# > 0 )); do name+="${name:+\\|}$1"; shift; done
echo -n ${name:+"^\\($name\\)="}
}
get_ip() {
local ip=$(ifconfig 2>/dev/null | awk '/inet /{print $2}' | tail -1)
echo -n $ip
}
default_lang=EN-US
repository=tecolicom/xlate
hostname=xlate
interactive=yes
version=
workdir=/work
mount_mode=rw
read_only=
display=
[ -e ${localtime:=/etc/localtime} ] || localtime=
define DEFAULT_ENV <<EOF
LESSANSIENDCHARS=mK
LESS=-cR
EOF
while getopts :${EXOPT:=dBI:V:T:LRGCD} OPT
do
case $OPT in
d) debug=yes ; set -x ;;
B) interactive= ;;
I) container="$OPTARG" ;;
V) volume="$OPTARG" ;;
T) version=:"$OPTARG" ;;
L) version=:latest ;;
R) mount_mode=ro ;;
G)
if [ "${topdir:=$(git_topdir)}" ]
then
if [ "$topdir" != "${PWD:=$(pwd)}" ]
then
echo "Mount $topdir to $workdir" >&2
volume=$topdir
cd_path=${PWD#$topdir}
fi
fi
;;
C|D)
[ "$XLATE_RUNNING_DOCKER" ] && break
if [ "$DISPLAY" ] && [ "${ip:=$(get_ip)}" ]
then
display="$ip:0"
fi
if [ ! "$version" ]
then
this=$(awk '$1=="Version"{print $2}' <<< "$pod")
[[ "$this" =~ ^[0-9]+\.[0-9_]+$ ]] && version=":$this"
fi
declare -a command
case "$OPT" in
C) shift $((OPTIND - 1)) ;;
D) command=(xlate) ;;
esac
command+=(${1+"$@"})
ENV=(LANG TZ TERM_PROGRAM TERM_BGCOLOR COLORTERM)
ENV+=(DEEPL_AUTH_KEY)
ENV_PATTERN=$(env_pattern ${ENV[@]})
exec docker run --rm \
-e XLATE_RUNNING_DOCKER=1 \
${interactive:+-it} \
${read_only:+--read-only} \
${hostname:+--hostname "${hostname}"} \
${localtime:+-v ${localtime}:/etc/localtime:ro} \
-v "${volume:-$(pwd)}:${workdir}:${mount_mode}" \
-w "${workdir}${cd_path}" \
${display:+-e DISPLAY="$display"} \
${DEFAULT_ENV:+--env-file <(echo "$DEFAULT_ENV")} \
${ENV_PATTERN:+--env-file <(env | grep -e "$ENV_PATTERN")} \
${container:-${repository}${version}} \
"${command[@]}"
exit;
;;
esac
done
OPTIND=1
mod="App-Greple-xlate"
share=$(perl -MFile::Share=:all -E "say dist_dir '$mod'")
while getopts "${EXOPT}"'Macrsnp:w:o:f:t:m:l:h' OPT
do
case $OPT in
[$EXOPT]) : ignore ;;
M) run_make=yes ;;
a) use_api=yes ;;
c) check=yes ;;
r) refresh=yes ;;
s) silent=yes ;;
n) dryrun=yes ;;
p) pattern="$OPTARG" ;;
w) wrap="$OPTARG" ;;
o) format="$OPTARG" ;;
f) from_lang="$OPTARG" ;;
t) to_lang="$OPTARG" ;;
m) max="$OPTARG" ;;
l)
file="$share/$OPTARG"
if [ -f "$file" ]
then
cat $file
else
echo $share
ls -1 $share | sed 's/^/\t/'
fi
exit
;;
h)
help="$(sed -r -e 's/^=[a-z]+[0-9]* *//' <<< "$pod")"
exec echo "$help"
exit
;;
esac
done
shift $((OPTIND - 1))
: ${to_lang:="$default_lang"}
: run make
if [ "$run_make" == yes ]
then
declare -a opt
for m in "$@"
do
if [ -f "$m" ]
then
# GNU Make behaves differently in different versions with
# respect to double-quoted strings and spaces within them.
files="${files:+$files|||}$m"
else
opt+=("$m")
fi
done
unset MAKELEVEL
exec make -f $share/XLATE.mk \
${dryrun:+-n} \
XLATE_LANG=\""$to_lang"\" \
XLATE_DEBUG=$debug \
XLATE_MAXLEN=$max \
XLATE_USEAPI=$use_api \
${format:+XLATE_FORMAT=\""$format"\"} \
${files:+XLATE_FILES=\""$files"\"} \
${opt[@]}
exit 1
fi
: ${format:=xtxt}
if [[ "$format" =~ ^(.+)-fold$ ]]
then
format=${BASH_REMATCH[1]}
: ${wrap:=76}
fi
declare -a module option
module+=(-Mxlate::deepl)
option+=(--xlate-to="$to_lang" --xlate-format="$format" --xlate-cache=yes)
option+=(--all)
[ "$use_api" == yes ] || use_clipboard=yes
[ "$check" == yes ] || option+=(--xlate${use_clipboard:+-labor})
[ "$wrap" != "" ] && option+=(--xlate-fold-line --xlate-fold-width=$wrap)
[ "$debug" == yes ] && option+=(-dmo)
[ "$refresh" == yes ] && option+=(--cache-clear)
[ "$silent" == yes ] && option+=(--no-xlate-progress)
[ "$max" != "" ] && option+=(--xlate-maxlen="$max")
declare -a area
case $1 in
*.txt)
area=(--re '^(.+\n)+')
;;
*.md)
area=(--re '(?x) ^[-+#].*\n | ^(.+\n)+ ')
option+=(--exclude '^([ \t]+.*\n)+')
;;
*.pm|*.pod)
module+=(-Mperl)
option+=(--pod)
option+=(--exclude '^=head\d +(VERSION|AUTHOR|LICENSE).*\n(?s:.*?)(?=^=|\z)')
area=(--re '^(\w.+\n)+')
;;
*.docx|*.pptx)
module+=(-Mmsdoc)
option+=(--exclude '^\[.*\b(docx|pptx)\b.*\]\n')
area=(--re '^.+\n')
;;
*)
area=(--re '^.+\n')
;;
esac
if [ "$pattern" ]
then
option+=(--re "$pattern")
else
option+=("${area[@]}")
fi
greple "${module[@]}" "${option[@]}" ${1+"$@"}