лёгкий переводчик

Вопросы о переводах документации, вики, man страниц. Разработки.
Ответить
Arhei
Сообщения: 10
Зарегистрирован: 04.07.2025

#

создано по мотивам данной темы

сам скрипт:
#!/usr/bin/env bash

# описание:     перевод выделенного текста и отображение его через терминал foot в sway
# зависимости:  sway foot wl-clipboard curl jq ttf-jetbrains-mono

NAME="${0##*/}"
DIR="/tmp/$NAME" && mkdir -p "$DIR"
FileIn="$DIR/in.txt"
FileOut="$DIR/out.txt"


COLUMNSxLINES=33x17
POSITION="center"	# or "X Y"
FONT="JetBrainsMono:size=15"

# ColorBackground="000000"
# ColorForeground="826b58"
# ColorIn="\e[1;34m"
# ColorOut="\e[1;37m"
ColorIn="\e[1;34;40m"
ColorOut="\e[1;30;44m"
ColorError="\e[1;37;41m"
ColorReset="\e[0m"
LangDetect=true
LangIn=eng
LangOut=rus
PrimaryClipboard=true

# shellcheck source=/dev/null
touch "$DIR/conf" && source "$DIR/conf"

tput civis	# убрать курсор
tput bold	# текст жирным



if [[ ! $z ]]; then
	export z=1
	# sway: правило для отображения окна по его app_id
	swaymsg for_window [app_id="$NAME"] floating enable
	swaymsg for_window [app_id="$NAME"] sticky   enable
	swaymsg for_window [app_id="$NAME"] move position "$POSITION"
	
	# закрыть открытое окно при повторном запуске программы
	WindowID=$(swaymsg -t get_tree | jq --arg name "$NAME" --raw-output '..|select(.app_id == $name)? | .pid')
	[[ -n "$WindowID" ]] && kill "$WindowID" && exit
	
	rm -rf "$FileIn.old"
	
	[[ $PrimaryClipboard == true ]] && BUFFER_TYPE="--primary"

	exec foot 	--hold \
				-t foot-direct \
			  	--app-id="$NAME" \
				--font="$FONT" \
				--window-size-chars="$COLUMNSxLINES" \
				--override=pad="10x10 center" \
				--override="mouse.hide-when-typing=true" \
				--override="colors.alpha=1" \
			  	-e wl-paste "$BUFFER_TYPE" --type "text/plain;charset=utf-8" --watch "$NAME"

				# --override="colors.background=$ColorBackground" \
				# --override="colors.foreground=$ColorForeground" \
fi

# читаем буфер и пишем в файл
cat - > "$FileIn"

TextIn=$(cat "$FileIn")
[[ "$TextIn" == "" ]] && exit
[[ "$TextIn" =~ [[:alpha:]] ]] || exit

# если выделенный текст идентичен предыдущему то не переводить
cmp --quiet "$FileIn" "$FileIn.old" && exit
cp "$FileIn" "$FileIn.old"


# фильтры для входящего текста
sed -i -e '/./,$!d' -e :a -e '/^\n*$/{$d;N;ba' -e '}' "$FileIn"    	# удалить начальные и конечные пустые строки
awk 'NF{c=1} (c++)<3' "$FileIn" | sponge "$FileIn"               	# удалить больше одной пустой строки
awk 'NF>0{printf "%s ",$0;next} {printf "\n\n"}' "$FileIn" | sponge "$FileIn" 
tr -s ' ' < "$FileIn" | sponge "$FileIn"                         	# удаляем больше одного пробела


JsonOut="$(
curl -s 'https://api.reverso.net/translate/v1/translation' \
  --compressed \
  -X POST \
  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0' \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3' \
  -H 'Accept-Encoding: gzip, deflate, br, zstd' \
  -H 'Content-Type: application/json' \
  -H 'X-Reverso-Origin: translation.web' \
  -H 'Origin: https://www.reverso.net' \
  -H 'DNT: 1' \
  -H 'Sec-GPC: 1' \
  -H 'Connection: keep-alive' \
  -H 'Referer: https://www.reverso.net/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-site' \
  -H 'TE: trailers' \
  --data-raw "$(
  jq --null-input \
     --arg languageDetection "$LangDetect" \
     --arg from  "$LangIn" \
     --arg to    "$LangOut" \
     --arg input "$TextIn" \
  '{"format":"text","from":$from,"to":$to,"input":$input,"options":{"sentenceSplitter":true,"origin":"translation.web","contextResults":false,"languageDetection":$languageDetection}}')"
)"
printf "%s" "$JsonOut" | jq --raw-output0 '.translation[]' > "$FileOut"


error=$(printf "%s" "$JsonOut" | jq --raw-output '.error')
if [[ "$error" != "null" ]]; then
	echo -en "$ColorError"
	StatusBarError="-- [err]"
	dashes=""
	while ((--COLUMNS - 8)) ; do dashes="${dashes}-" ; done
	echo -n "$StatusBarError $dashes"
	echo "$error"
	echo -e "$ColorReset"
	exit
fi

LangIn2=$LangIn
LangOut2=$LangOut
LangIn2=$(printf "%s" "$JsonOut" | jq --raw-output '.languageDetection.detectedLanguage')
reversed=$(printf "%s" "$JsonOut" | jq --raw-output '.languageDetection.isDirectionChanged')
[[ $reversed == "true" ]] && LangOut2=$LangIn || LangOut2=$LangOut


# вывод статус бара
StatusBar="-- [$LangIn2:$LangOut2(reverso)]"
StatusBarChars=$(echo -n "$StatusBar" |wc -m)
dashes=""
while ((--COLUMNS - StatusBarChars)) ; do dashes="${dashes}-" ;done
echo "$StatusBar $dashes"

# вывод переводимого и переведённого текста 
echo -en "$ColorIn"
cat 	"$FileIn"
echo -e "\n$ColorOut"
cat 	"$FileOut"
echo -e "\n$ColorReset"

# запоминаем(до перезагрузки) размер консоли
echo "COLUMNSxLINES=${COLUMNS}x${LINES}" > "$DIR/conf"

# запоминаем(до перезагрузки) положения окна в sway
SwayBarInfo=$(swaymsg -t get_bar_config "$(swaymsg -t get_bar_config | jq -r '.[]')")
BAR_MODE=$(echo "$SwayBarInfo" | jq -r '.mode')
BAR_POSITION=$(echo "$SwayBarInfo" | jq -r '.position')
BAR_HEIGHT=$(echo "$SwayBarInfo" | jq -r '.bar_height')
[[ "$BAR_MODE" == "dock" && "$BAR_POSITION" == "top" ]] || BAR_HEIGHT=0
echo "POSITION=$(swaymsg -t get_tree | jq --arg name "$NAME" --arg bar_height "$BAR_HEIGHT" '.. | select(.app_id == $name )? | .rect | "\(.x) \(.y - ($bar_height|tonumber))"')" >> "$DIR/conf"

exit
вешаем вызов скрипта на кнопку и радуемся
у сябя повесил на одну из боковых кнопок мыши
~/.config/sway/
bindsym --whole-window BTN_SIDE exec lalang.sh
вариант пока довольно ограниченный но будем дорабатывать
что он уже может
- перевод с помощью онлайн сервиса reverso.net (будут и другие)
- выбор буфера для перевода, параметр PrimaryClipboard (true - первичный буффер, когда достаточно просто выделить текст; false - стандартный буффер, тот же Ctrl-C который отправляет в буфер)
- запоминает(до перезагрузки) где было расположенно окно(sway) и его(foot) размер; в принципе можно будет сделать его более универсальным(без привязки к WM), но пока так.
- запускаеться в слушающем(выбранный буффер) режиме, то есть переводит по мере поступления; закрываеться так же как и запускаеться

если будут конструктивные предложение то добро пожаловать
vall
Аватара пользователя
Администрация
Сообщения: 899
Зарегистрирован: 09.08.2022

#

Коллега Arhei, Вас с почином на этом ресурсе. Форум с "разморозкой" данного раздела.

Приглашаю заинтересованных пользователей пробовать и высказываться по вопросу.
Ответить