123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- #!/bin/sh
- # translate using t12s (technosaurus) method
- # 2011-11-14 L18L
- #
- # developer: never ever change a message, use a blank ID instead
- # example: if you want to change
- # _M5_:-...failed
- # then use
- # _M_:-...oops this failed
- # that is because original translation is stored nowhere
- # note, simple quote (') inside message is not allowed, use (´) instead
- # translate to dummy language xxx thus you can test completeness and design
- #
- #20111115 enabling variables in message, example: '${1}' not found
- # not yet tested!!!!!!!!! but anyhow: without variables it is OK
- #20111116 bugfix for empty language in 'Select code of language' dialog
- version='0.4.1' # bug fix for breaking script in automatic numbering
- version='0.4.2' # added check for selected script
- version='0.4.3' # bugfix and code clean up
- version='0.4.4' # bugfix slash inside message, delimiter for sed is backtick
- version='0.4.5' # bugfixes:utf8, enabled using \"
- version='0.4.5.1' # bugfix:xxx
-
- RESTART=$0
- myfile=$1
- OUTPUT_CHARSET=UTF-8 # needed?
- T=/usr/share/locales # TEXTDOMAINDIR
- title="t12s -v $version "
- [ "`whoami`" != "root" ] && exec sudo -A ${0} ${@} # write to TEXTDOMAINDIR
- delim='`' # delimiter for sed, no backtick in messages !
- # make sure UTF-8 is enabled
- if [ "${LANG#*.}" = "$LANG" ]; then
- yad --text=" <big>Enable <span color='red'>UTF-8</span> in the following dialog
- then restart X server and start again please</big>"
- [[ $? -eq 1 || $? -eq 252 ]] && exit 0
- /usr/sbin/chooselocale
- ln -s "`pwd`/$RESTART" ${HOME}/Startup/t12s
- exit 0
- else
- rm ${HOME}/Startup/t12s 2>/dev/null
- fi
- # the following texts will hopefully give you the idea of this script
- text0="script is not yet
- internationalized by method t12s, sorry."
- text1=" Select a script which uses t12s method for internationalisation.
- Translatable text strings are marked by <span color='red'>_M_</span> in such scripts.
- (Developers: klick ´Developer´ button for info how to Internationalize shell scripts using this method)"
- text2=" Select code of language
- which you want to translate to.
-
- Choose from <span color='darkgreen'>existing</span> translations
- or
- enter <span color='red'>new</span> language code
- Inofficial languages (example: slv for Slavio) possible.
- Regional variants (dialect) appreciated!
- examples: pt_BR or en_AUS
- "
- text3=" Select <span color='red'>one message</span> which you want to translate.
- The original English message will be shown
- after klicking <span color='darkgreen'>OK</span> button.
-
- Or <span color='red'>Undo</span> translation of last message!"
- available_lang_list=/dev/shm/available_languages # temporary list
- my_LANG=${LANG%_*} # wild guess: user wants to translate to his language
- # select shell script which has this method of i18n
- [ -z $myfile ] && while [ 1=1 ]; do # main window ===========================
- ### some docu added here !
- # select shell script myfile which has this method of i18n
- myfile=$(yad --title="$title Select 1 Script" --text="$text1" \
- --width="500" --height="400" \
- --file-selection --filename=/usr/sbin/ \
- --button="Developer:4" \
- --button="Translator:3" \
- --button="gtk-about:2" \
- --button="gtk-quit:1" \
- --button="gtk-ok:0" \
- )
- choice=$?
- case $choice in
- 0) this_LANG=${this_LANG%|*} # cut -d '|' -f 1 `
- [ "`grep _M_ $myfile`" ] && [ -x "$myfile" ] && break # this_LANG preselected for translation
- text=" $myfile $text0"
- [ ! -x "$myfile" ] && text="Sorry, $myfile is not executable"
- read LINE < $myfile ; [ ${LINE:0:3} != "#!/" ] && text="Sorry, $myfile is no script"
- yad --text="$text" ; [[ $? -eq 1 || $? -eq 252 ]] && exit 0
- ;;
- 1|252) exit 0 ;;
- 2) yad --width="450" --title="About t12s : translate 1 script to several languages" \
- --text=" GUI for fast and easy l10n (localization) of shell scripts
-
- There is just a language file containing translations
- from original messages created from source at run time.
-
- core algorithm by Technosaurus
- <small>http://bashismal.blogspot.com/2011/10/
- localizing-shell-scripts-without.html</small>
-
- written by L18L 2011, licence is GPL v3" \
- --button="gtk-ok"
- ;;
- 3) yad --title="t12s: some Notes for Translators" \
- --text="
-
- You can translate to <span color='darkgreen'>any</span> language
- without needing their locale (though it might be better).
-
- Your will find your translation of <span color='darkred'>script</span> in this file:
- ${T}/<your language code>/<span color='darkgreen'>script</span>
- Just <b>select a script that is internationalized using this method</b>.
- " --button="gtk-ok"
- ;;
- 4) yad --title="t12s: some Notes for Developpers" \
- --text=" Some simple rules for i18n (internationalization) of shell script:
- ###################### copy this block into any other script that... ##########
- app=\`basename \$0\`
- T=/usr/share/locales # TEXTDOMAINDIR
- # a one-liner to find existing translation file LOCALES allowing 'dialects'
- [ ! -f \${T}/\${LANG%.*}/\${app} ] && LOCALES=\${T}/\${LANG%_*}/\${app} || LOCALES=\${T}/\${LANG%.*}/\${app}
- [ -f \$LOCALES ] && . \$LOCALES # (re)load translation file (when using variables)
- ###################### ... uses this _ M _ method of internationalization #####
-
- - mark messages by _M_, no { } for variables, example
- change:
- echo \"Hello \${myOS} world\"
- to:
- [ -f \$LOCALES ] && . \$LOCALES
- echo \"<span color='darkgreen'>\${_M_:-</span>Hello \$myOS world<span color='darkgreen'>}</span>\"
- - using square or round brackets [ ( then
- alway 1 space after and 1 space before: ) ]
-
- - use \" only if really needed. Try instead ' or ´ (single quote or apostrophe)
- - 1 message per code line only
-
- You can start preparing just some messages and after having chosen the script in the main window
- if you are asked for the language to translate to you can type in Language code <b>xxx</b>.
- Then your internationalized script will run in a dummy language, that is just your original messages
- embedded in +++ (Other languages tend to be larger than English messages)
- This way you can check completeness of i18n and possible (hopefully not) break of your screen design." \
- --button="gtk-ok"
- ;;
- esac
- done # /main window ==========================================================
- app="`basename $myfile`"
- echo app=$app
- if [ "`grep -E '^[^#].*_M_:-' $myfile`" ]; then # id numbering of messages
- # find last highest number i to skip
- echo find last highest number i to skip
- sed -e "s${delim}.*{_M_${delim}${delim};s${delim}:-}.*${delim}${delim}" $myfile | grep -E '^[0-9]' | sort -unr > /dev/shm/t12s_i
- read LINE < /dev/shm/t12s_i # head -n 1
- i=${LINE%%:*} # cut -d ':' -f 1
- [ $i ] || i=0 # found last highest number i to skip
- echo i=$i is highest existing number
- #sort uniq just the (new added) message text
- grep -E '^[^#].*_M_:' $myfile | cut -d "{" -f 2- | rev | cut -d "}" -f 2- | rev \
- | sed -r "s${delim}_M_:-${delim}${delim}g" | sort -u > /dev/shm/t12s_${app}_u
- #echo "last one dummy" >> /dev/shm/t12s_${app}_u # without this last one is missing
- echo "
- new unique numbered messages will be line numbers in /dev/shm/t12s_${app}_u added to $i
- press ENTER to continue
- automatic addition of identifiers to _M_ in
- $myfile
- a backup of $myfile
- will be made as
- ${myfile}_bak."
- #read x
- cp ${myfile} ${myfile}_bak
- # put id numbers into myfile
- while read LINE ; do # just 1 second, sed ///g needed for multiple use, example: please wait...
- i=$(($i + 1))
- [[ $LINE =~ "[" ]] && LINE=`echo $LINE | sed -e 's/\[/\\\[/g;s/\]/\\\]/g'` # escape square [brackets]
- [[ $LINE =~ "(" ]] && LINE=`echo $LINE | sed -e 's/\(/\\\[/g;s/\)/\\\)/g'` # escape square [brackets]
- [[ $LINE =~ "<" ]] && LINE=`echo $LINE | sed -e 's/</\</g;s/>/\>/g'` # escape <brackets>
- [[ $LINE =~ "\'" ]] && LINE=`echo $LINE | sed -e "s/\'/\\\'/g;"` # escape single quote
- [[ $LINE =~ '\"' ]] && LINE=`echo $LINE | sed -e 's/\"/\\\"/g;'` # escape double quote
- # not working for \"
- sed -e "s${delim}_M_:-${LINE}${delim}_M_${i}:-${LINE}${delim}g" ${myfile} > ${myfile}_$i
- # need to test file sizes, success if different
- if [[ `ls -l ${myfile}_$i | cut -d ' ' -f 5` -gt `ls -l ${myfile} | cut -d ' ' -f 5` ]]; then
- mv ${myfile}_$i ${myfile}
- else #always if \" was used
- chmod +x ${myfile}
- yad --text="Sorry, could not write number $i for
- $LINE
- You have to add unique number $i manually to _M_ in
- $myfile
- now then press OK button to restart t12s" --button="gtk-ok:0"
- sync; $RESTART $myfile && exit 1
- fi
- done < /dev/shm/t12s_${app}_u
- chmod +x ${myfile}
- sync
-
- fi # /id numbering of messages
- # start with user's language, English have to type in
- [ "${LANG%_*}" != "en" ] || this_LANG=${LANG%_*}
- # endless loop for translating myfile to several languages ##############
- while [ 1=1 ]; do
- # existing_translations for app in TEXTDOMAINDIR, one of them could be new
- cd ${T}
- existing_translations="`ls */${app} 2>/dev/null | tr -s ' ' | cut -d '/' -f 1 `"
- echo -n > $available_lang_list
- for x in $existing_translations; do echo $x >> $available_lang_list; done
- cd - 1>/dev/null
- sync # ? needed
- # choose language $this_LANG
- this_LANG=''
- while [ "`echo $this_LANG | sed -r 's/[a-z]{2,3}(_[A-Z]{2,3}){0,1}/OK/'`" != "OK" ]; do #20111116
- this_LANG=$(yad --title="$title translate $app" --text="$text2" \
- --width="80" --height="240" \
- --form \
- --item-separator="\n" \
- --field="Language code:CBE" "`echo ${my_LANG} ; cat $available_lang_list`" \
- --item-separator="\n" \
- --button="gtk-quit:1" \
- --button="gtk-ok:0" \
- )
- choice=$?
- case $choice in
- 0) this_LANG=${this_LANG%|*};; # cut -d '|' -f 1 `
- 1|252) exit 0 ;;
- esac
- done
- echo $this_LANG
- [ ! -d "${T}/${this_LANG}" ] && mkdir ${T}/${this_LANG}
- # extract English messages from script: create temporary English language file
- grep _M_ $myfile | cut -d "{" -f 2- | rev | cut -d "}" -f 2- | rev \
- | sed -r "s${delim}:-${delim}=\"${delim}g;s${delim}\$${delim}\"${delim}g" | sort -u > /dev/shm/t12s_${app}_en
- # dialect starts with copy of base language, ex: fr_CA copied from fr
- if [ ${#this_LANG} -gt 4 -a ! -f ${T}/${this_LANG}/${app} ]; then
- cp ${T}/${this_LANG%_*}/${app} ${T}/${this_LANG}
- [ $! ] || existing_translations="$existing_translations ${this_LANG}"
- fi
- # merge existing translation
- if [[ `grep -E "^${this_LANG}$" $available_lang_list` ]]; then # merge
- mv ${T}/${this_LANG}/${app} ${T}/${this_LANG}/${app}_tmp
- while read LINE; do #comment for no more existing ones, but once only
- [ "`grep -E ${LINE%=*} /dev/shm/t12s_${app}_en`" ] && comment="" || comment="#"
- [[ "${LINE:0:1}" = "#" ]] && comment=""
- echo ${comment}${LINE} >> ${T}/${this_LANG}/${app}
- done < ${T}/${this_LANG}/${app}_tmp
- rm ${T}/${this_LANG}/${app}_tmp
- while read LINE; do #append new ones
- [ "`grep -E ${LINE%=*} ${T}/${this_LANG}/${app}`" ] \
- || echo $LINE >> ${T}/${this_LANG}/${app}
- done < /dev/shm/t12s_${app}_en
- else
- if [ "$this_LANG" = "xxx" ]; then # dummy language
- # emulating translation (messages just embedded in +++)
- sed -e "s${delim}=\"${delim}=\"+++${delim}g;s${delim}\"${delim}+++\"${delim}g" /dev/shm/t12s_${app}_en > ${T}/xxx/${app}
- LANG=xxx
- exec $myfile &
- break
- elif [ 1 = 2 ] ; then #automated translation available...
-
- FROM=/C/
- [ ! -d /usr/share/locales/C/ ] && mkdir /usr/share/locales/C/
- for x in $myfile ; do
- TEMPLATE=/usr/share/locales/C/${app}.txt
- while read -d$ A || [ "$A" ]; do
- case "$A" in
- *{_M_*)B=_M${A##*_M};B=${B%%\}*};echo ${B//:-/=};;
- esac
- done < $x >${TEMPLATE}
- mv ${TEMPLATE} ${TEMPLATE}m; sort -u ${TEMPLATE}m>${TEMPLATE}; rm ${TEMPLATE}m
- for x in $this_LANG ; do
- TO=/${x//-/_}/
- [ ! -d ${TEMPLATE%%/C/*}/${x//-/_} ] && mkdir ${TEMPLATE%%/C/*}/${x//-/_}
- curl -A firefox \
- -F "file=@$TEMPLATE;type=text/plain" \
- -F "sl=en" \
- -F "tl=$x" \
- http://translate.googleusercontent.com/translate_f | \
- while read A || [ "$A" ]; do
- case $A in
- "<meta"*)A="";;
- *"<pre>"*)A=${A##*"<pre>"};;
- *"</pre>"*)A=${A%%"</pre>"*};;
- esac
- [ "$A" ] && echo ${A// = /=\"}\"
- done > ${TEMPLATE//$FROM/$TO}
- mv ${T}/${x}/${app}.txt ${T}/${x}/${app}
- #
- #curl: (6) Couldn't resolve host 'translate.googleusercontent.com' : empty file
- #
- # file is not utf-8 but iso-8859
- #
- done
- rm $TEMPLATE
- done #automated translation available...
-
- else # copy English to this_LANG
- cp /dev/shm/t12s_${app}_en ${T}/${this_LANG}/${app}
- fi
- fi
-
- # loop translate 1 item -------------------------------------------------------
- # while [ 2=2 ]; do
- [ "$this_LANG" = "xxx" ] && $myfile || while [ 2=2 ]; do
- sed -r "s${delim}=\"${delim}\n${delim}g;s${delim}\"\$${delim}${delim}g" ${T}/${this_LANG}/${app} > /dev/shm/t # just for inspection
- message=$(cat /dev/shm/t \
- | yad --title="$title translate $app to $this_LANG" \
- --height="400" --text="$text3" \
- --list \
- --column="ID" \
- --column="Actual Message Translated To ${this_LANG//_/_ }:TEXT" \
- --button="Change Language:3" \
- --button="gtk-execute:2" \
- --button="gtk-quit:1" \
- --button="gtk-undo:9" \
- --button="gtk-ok:0" \
- )
- choice=$?
- case $choice in
- 1|252) exit 0 ;;
- 3) break ;;
- 2)
- LANG="${this_LANG}" # Gtk-WARNING **: Locale not supported by C library.
- # but sufficient for just language
- [ -x $myfile ] || yad --text="sorry, chosen $myfile is not executable" \
- && exec $myfile & ;;
- 0) if [ "$message" ]; then
- msgID="`echo $message | cut -d '|' -f 1`" # ${message%|*} no go
- msgtr="`echo $message | cut -d '|' -f 2`"
- msgEN="`grep -F ${msgID}= /dev/shm/t12s_${app}_en | cut -d '\"' -f 2`"
- if [ -z "$msgEN" ];then
- yad --text="not in use any more"
- else
- msgEN="$msgEN"
- new_msgtr=$(yad --title="translate" --width="600" --text="$msgEN" \
- --entry --entry-text="$msgtr" \
- --button="gtk-ok:0" )
- [ "$new_msgtr" = "$msgtr" ] && continue
- # update translation file
- mv ${T}/${this_LANG}/${app} ${T}/${this_LANG}/${app}_old
- while read LINE; do
- [ "${LINE%=*}" != "$msgID" ] && out="$LINE" || out="${msgID}=\"${new_msgtr}\""
- echo $out >> ${T}/${this_LANG}/${app}
- done < ${T}/${this_LANG}/${app}_old
- fi
- else
- yad --title="translate" \
- --text="Select a line before OK button please" \
- --button="gtk-ok:0"
- fi ;;
- 9) cp ${T}/${this_LANG}/${app}_old ${T}/${this_LANG}/${app} ;;
- esac
- done # /loop translate item --------------------------------------------------
- done # /endless loop for translating myfile to several languages ##############
- #end of script
|