You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

language-update.sh 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. #!/bin/bash
  2. # Postfix Admin
  3. #
  4. # LICENSE
  5. # This source file is subject to the GPL license that is bundled with
  6. # this package in the file LICENSE.TXT.
  7. #
  8. # Further details on the project are available at http://postfixadmin.sf.net
  9. #
  10. # @version $Id: language-update.sh 1686 2014-09-12 09:52:21Z christian_boltz $
  11. # @license GNU GPL v2 or later.
  12. #
  13. # File: language-update.sh
  14. # Lists missing translations in language files and optionally patches the
  15. # english texts into the language file.
  16. # Can also do several other things that help handling the language files - see --help.
  17. #
  18. # written by Christian Boltz
  19. function update_string_list() {
  20. for file in en.lang $filelist ; do
  21. echo "<?php include('$file'); print join(\"\\n\", array_keys(\$PALANG)) . \"\\n\"; ?>" | php > $file.strings
  22. done
  23. for file in $filelist ; do
  24. test "$file" = "en.lang" && continue
  25. LANG=C diff -U2 $file.strings en.lang.strings > $file.diff && echo "*** $file: no difference ***"
  26. test $notext = 1 && cat $file.diff && continue
  27. grep -v 'No newline at end of file' "$file.diff" | while read line ; do
  28. greptext="$(echo $line | sed 's/^[+ -]//')"
  29. grepresult=$(grep "'$greptext'" en.lang) || grepresult="***DEFAULT - $greptext dropped from en.lang? *** $line"
  30. grepresult2=$(grep "'$greptext'" $file) || grepresult2="$grepresult"
  31. case "$line" in
  32. ---*)
  33. echo "$line"
  34. ;;
  35. +++*)
  36. echo "$line"
  37. ;;
  38. @*)
  39. echo "$line"
  40. ;;
  41. -*)
  42. echo "-$grepresult"
  43. ;;
  44. +*)
  45. # needs translation
  46. # already added as comment?
  47. test "$grepresult" = "$grepresult2" && {
  48. echo "+$grepresult # XXX" # english
  49. } || {
  50. echo " $grepresult2" # translated
  51. echo "keeping line $grepresult2" >&2
  52. echo "This will result in a malformed patch." >&2
  53. }
  54. ;;
  55. *)
  56. echo " $grepresult2"
  57. ;;
  58. esac
  59. done > $file.patch
  60. test $patch = 0 && cat $file.patch
  61. test $patch = 1 && patch --fuzz=1 $file < $file.patch
  62. done
  63. } # end update_string_list()
  64. function forcepatch() {
  65. for i in `seq 1 5` ; do
  66. for file in $filelist ; do
  67. test "$file" = "en.lang" && { echo "*** skipping en.lang ***"; continue ; } >&2
  68. "$0" "$file" | sed -n '1,3 p ; 5 s/^./-/p ; 5s/^./+/p ; 6p' | recountdiff | patch "$file"
  69. done
  70. done
  71. } # end forcepatch
  72. function rename_string() {
  73. for file in $filelist ; do
  74. line="$(grep "PALANG\['$rename_old'\]" "$file")" || {
  75. echo "*** $file does not contain \$PALANG['$rename_old'] ***" >&2
  76. continue
  77. }
  78. newline="$(echo "$line" | sed "s/'$rename_old'/'$rename_new'/")"
  79. # create patch
  80. echo "
  81. --- $file.old
  82. +++ $file
  83. @@ -1,1 +1,1 @@
  84. -$line
  85. +$newline
  86. " > "$file.patch"
  87. test $patch = 0 && cat $file.patch
  88. test $patch = 1 && patch $file < $file.patch
  89. done
  90. } # end rename_string()
  91. function remove_string() {
  92. for file in $filelist ; do
  93. line="$(grep "PALANG\['$remove_string'\]" "$file")" || {
  94. echo "*** $file does not contain \$PALANG['$remove_string'] ***" >&2
  95. continue
  96. }
  97. # create patch
  98. echo "
  99. --- $file.old
  100. +++ $file
  101. @@ -1,1 +1,0 @@
  102. -$line
  103. " > "$file.patch"
  104. test $patch = 0 && cat $file.patch
  105. test $patch = 1 && patch $file < $file.patch
  106. done
  107. } # end remove_string()
  108. function addcomment() {
  109. for file in $filelist ; do
  110. test "$file" = "en.lang" && { echo "*** skipping en.lang ***"; continue ; } >&2
  111. line="$(grep "PALANG\['$text'\]" "$file")" || {
  112. echo "*** $file does not contain \$PALANG['$text'] ***" >&2
  113. continue
  114. }
  115. newline="$line # XXX $comment"
  116. # create patch
  117. echo "
  118. --- $file.old
  119. +++ $file
  120. @@ -1,1 +1,1 @@
  121. -$line
  122. +$newline
  123. " > "$file.patch"
  124. test $patch = 0 && cat $file.patch
  125. test $patch = 1 && patch $file < $file.patch
  126. done
  127. } # end add_comment
  128. function obsolete() {
  129. for file in $filelist ; do
  130. # do not skip en.lang
  131. line="$(grep "PALANG\['$text'\]" "$file")" || {
  132. echo "*** $file does not contain \$PALANG['$text'] ***" >&2
  133. continue
  134. }
  135. newline="$line # obsolete"
  136. # create patch
  137. echo "
  138. --- $file.old
  139. +++ $file
  140. @@ -1,1 +1,1 @@
  141. -$line
  142. +$newline
  143. " > "$file.patch"
  144. test $patch = 0 && cat $file.patch
  145. test $patch = 1 && patch $file < $file.patch
  146. done
  147. } # end add_comment
  148. function comparetext() {
  149. for file in $filelist ; do
  150. echo "<?php
  151. include('$file');
  152. if (\$PALANG['$text1'] != \$PALANG['$text2']) {
  153. echo '$file: ' . \$PALANG['$text1'] . ' -- $text1' . \"\\n\";
  154. echo '$file: ' . \$PALANG['$text2'] . ' -- $text2' . \"\\n\";
  155. }
  156. " | php
  157. done
  158. }
  159. function cleanup() {
  160. # check for duplicated strings
  161. for file in $filelist ; do
  162. sed -n "/PALANG/ s/[ ]*\$PALANG\['// ; s/'.*//p" $file |sort |uniq -c |grep -v " *1 " >&2 && \
  163. echo "*** duplicated string in $file, see above for details ***" >&2
  164. done
  165. # cleanup tempfiles
  166. test $nocleanup = 0 && for file in $filelist ; do
  167. rm -f $file.patch $file.strings $file.diff $file.orig
  168. done
  169. } # end cleanup()
  170. statistics() {
  171. (
  172. cat << 'EOF'
  173. Postfixadmin - translation statistics
  174. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  175. Translating is easy:
  176. - download your language file from SVN
  177. http://postfixadmin.svn.sourceforge.net/viewvc/postfixadmin/trunk/languages/
  178. - search for lines with '# XXX' comments and
  179. - translate the line
  180. - remove the '# XXX'
  181. Note: The file is utf-8 encoded.
  182. - post your translation to the tracker
  183. http://sourceforge.net/p/postfixadmin/patches/
  184. Number of missing translations:
  185. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  186. EOF
  187. grep -c XXX *.lang |sed 's/:/: /'
  188. cat << 'EOF'
  189. Statistics based on:
  190. EOF
  191. LANG=C svn info |grep 'Revision:\|Last Changed Date:'
  192. ) > postfixadmin-languages.txt
  193. echo "Translation statistics have been saved as postfixadmin-languages.txt"
  194. } # end statistics()
  195. usage() {
  196. echo '
  197. Usage:
  198. ~~~~~~
  199. '"$0"' [--notext | --patch] [--nocleanup] [foo.lang [bar.lang [...] ] ]
  200. List missing translations in language files and optionally patch the
  201. english texts into the language file
  202. --notext
  203. only list the translation keys (useful for a quick overview)
  204. Note for translators: untranslated entries have a comment
  205. # XXX
  206. attached.
  207. '"$0"' --rename old_string new_string [--patch] [--nocleanup] [foo.lang [bar.lang [...] ] ]
  208. Rename $PALANG['"'"'old_string'"'"'] to $PALANG['"'"'new_string'"'"']
  209. '"$0"' --remove string [--patch] [--nocleanup] [foo.lang [bar.lang [...] ] ]
  210. Remove $PALANG['"'"'string'"'"'] from language files
  211. '"$0"' --addcomment string comment [--patch] [--nocleanup] [foo.lang [bar.lang [...] ] ]
  212. Add a comment to $PALANG['"'"'string'"'"']
  213. Useful if a string needs to be translated again.
  214. '"$0"' --obsolete string [--patch] [--nocleanup] [foo.lang [bar.lang [...] ] ]
  215. Mark $PALANG['"'"'string'"'"'] as obsolete / no longer used
  216. '"$0"' --forcepatch [foo.lang [bar.lang [...] ] ]
  217. Similar to --patch, but applies the patch line by line. Useful if --patch
  218. fails because of empty lines etc., but much slower.
  219. --forcepatch patches 10 lines per run. When you only see messages like
  220. "patch: **** Only garbage was found in the patch input.", take it as
  221. success message :-) (no difference remaining)
  222. '"$0"' --comparetext string1 string2 [foo.lang [bar.lang [...] ] ]
  223. Compare two texts in $PALANG.
  224. This can be useful to find out if two equel texts in $PALANG are the
  225. same in all languages. No output means no difference.
  226. '"$0"' --stats
  227. Print translation statistics to postfixadmin-languages.txt
  228. Common parameters:
  229. --patch
  230. patch the language file directly (instead of displaying the patch)
  231. (use --forcepatch if --patch fails with rejections)
  232. --nocleanup
  233. keep all temp files (for debugging)
  234. You can give any number of langugage files as parameter.
  235. If no files are given, all *.lang files will be used.
  236. '
  237. } # end usage()
  238. # main script
  239. notext=0 # output full lines by default
  240. patch=0 # do not patch by default
  241. forcepatch=0 # no forcepatch by default
  242. nocleanup=0 # don't delete tempfiles
  243. rename=0 # rename a string
  244. remove=0 # remove a string
  245. stats=0 # create translation statistics
  246. addcomment=0 # add translation comment
  247. obsolete=0 # add obsolete note
  248. comparetext=0 # compare two PALANG texts
  249. text=''
  250. comment=''
  251. rename_old=''
  252. renane_new=''
  253. filelist=''
  254. while [ -n "$1" ] ; do
  255. case "$1" in
  256. --help)
  257. usage
  258. exit 0;
  259. ;;
  260. --comparetext)
  261. comparetext=1
  262. shift; text1="$1"
  263. shift; text2="$1"
  264. test -z "$text2" && { echo '--comparetext needs two parameters' >&2 ; exit 1; }
  265. ;;
  266. --notext)
  267. notext=1
  268. ;;
  269. --patch)
  270. patch=1
  271. ;;
  272. --nocleanup)
  273. nocleanup=1
  274. ;;
  275. --rename)
  276. rename=1
  277. shift ; rename_old="$1"
  278. shift ; rename_new="$1"
  279. echo "$rename_old" | grep '^[a-z_-]*\.lang$' && rename_new='' # error out on *.lang - probably a filename
  280. echo "$rename_new" | grep '^[a-z_-]*\.lang$' && rename_new='' # error out on *.lang - probably a filename
  281. test -z "$rename_new" && { echo '--rename needs two parameters' >&2 ; exit 1 ; }
  282. ;;
  283. --remove)
  284. remove=1
  285. shift ; remove_string="$1"
  286. test -z "$remove-string" && { echo '--remove needs a parameter' >&2 ; exit 1 ; }
  287. ;;
  288. --addcomment)
  289. addcomment=1
  290. shift ; text="$1"
  291. shift ; comment="$1"
  292. echo "$text" | grep '^[a-z_-]*\.lang$' && comment='' # error out on *.lang - probably a filename
  293. echo "$comment" | grep '^[a-z_-]*\.lang$' && comment='' # error out on *.lang - probably a filename
  294. test -z "$comment" && { echo '--addcomment needs two parameters' >&2 ; exit 1 ; }
  295. ;;
  296. --obsolete)
  297. obsolete=1
  298. shift ; text="$1"
  299. echo "$text" | grep '^[a-z_-]*\.lang$' && comment='' # error out on *.lang - probably a filename
  300. test -z "$text" && { echo '--addcomment needs a parameter' >&2 ; exit 1 ; }
  301. ;;
  302. --forcepatch)
  303. forcepatch=1
  304. ;;
  305. --stats)
  306. stats=1
  307. ;;
  308. -*)
  309. echo 'unknown option. Try --help ;-)' >&2
  310. exit 1
  311. ;;
  312. *)
  313. filelist="$filelist $1"
  314. ;;
  315. esac
  316. shift
  317. done # end $@ loop
  318. test $notext = 1 && test $patch = 1 && echo "ERROR: You can't use --notext AND --patch at the same time." >&2 && exit 2
  319. test $notext = 1 && test $rename = 1 && echo "ERROR: You can't use --notext AND --rename at the same time." >&2 && exit 2
  320. test "$filelist" = "" && filelist="`ls -1 *.lang`"
  321. test "$addcomment" = 1 && { addcomment ; cleanup ; exit 0 ; }
  322. test "$rename" = 1 && { rename_string ; cleanup ; exit 0 ; }
  323. test "$remove" = 1 && { remove_string ; cleanup ; exit 0 ; }
  324. test "$obsolete" = 1 && { obsolete ; cleanup ; exit 0 ; }
  325. test "$forcepatch" = 1 && { forcepatch ; cleanup ; exit 0 ; }
  326. test "$comparetext" = 1 && { comparetext ; cleanup ; exit 0 ; }
  327. test "$stats" = 1 && { statistics ; exit 0 ; }
  328. update_string_list ; cleanup # default operation