#!/bin/sh # # review - proof-read GNOME translations before you commit them. # Copyright (C) 2008 Leonardo Ferreira Fontenelle # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ### User settings # # # run 'review --help' to see if you need to change this. # # lang=pt_BR # Don't choose an ncurses/slang text editor here, because we need the terminal # window free to show the diff. You don't need to append '&' to the end of # the command, because the script will do it for you latter. Default: "gedit". # # editor=gvim # This is the list of tests to be performed on the second pass of pofilter, if # it is installed. The critical tests will be automatically excluded, because # they were already performed at the first time. # # Leave this variable commented to make pofilter perform its standard GNOME # tests. If you uncomment the variable, but leave it empty, there will be no # second pass. For more information on the pofilter tests, run # 'pofilter --listfilters' or read: # http://translate.sourceforge.net/wiki/toolkit/pofilter_tests # # pofilter_tests="acronyms blank emails filepaths functions numbers options purepunc urls endpunc endwhitespace startwhitespace" # These are additional, non-test arguments for pofilter. Run 'pofilter --help' # for more information. You don't need to set '--language=$lang' or # '--progress=none' here, because the script already includes them. # # If you kept the 'pofilter_tests' commented, you may want to exclude one or two # tests. You could uncomment 'pofilter_tests' and set all the tests you want # pofilter to run. But you can also use 'pofilter_args' to exclude those # unwanted tests, with '--excludefilter=FILTER'. # # Please notice that this 'pofilter_args' will be used in both pofilter passes! # # pofilter_args="--nofuzzy --excludefilter=untranslated" # Uncomment, i. e. erase the "#" before the following option to avoid the # instructions given at the end of the script execution: # # avoid_tips="yes" ### Helper functions # # die() { echo "$1" exit 1 } download() { [ -d "$my_dir" ] || mkdir -p "$my_dir" [ $? -eq 0 ] || die "Error! mkdir $my_dir failed" wget "$1" --timestamping --directory-prefix="$my_dir" --quiet [ $? -eq 0 ] || die "Error! Could not download $1" } exists(){ # Doesn't return error if "which" doesn't exist. [ ! -z "$(which $1 2> /dev/null)" ] } help() { echo "Usage: review [FILENAME | -h | --help] FILENAME is, obviously, the message catalog to be reviewed. If it is specified, it should be something like at-spi.HEAD.pt_BR.po, help.gnome-2-24.pt_BR.po, weather-locations.HEAD.pt_BR.po, or user-guide.HEAD.pt_BR.po. This is most useful for regular translators to review their own translations, or someone elses translations. This mode doesn't require Subversion to be installed. If the script is run without any arguments, it will guess the file name based on the language configuration (see below). The guess will be something like 'pt_BR.po', and it will be presumed that the file is in the current location and under version control with Subversion. This is a good option if you commit translations! This script automatically guesses your language based on \$LANG. If you prefer a different language, please edit this script or provide a \$lang environment variable. Right now the value of \$lang is $lang. The script will download a new message catalog from l10n.gnome.org and save it with the same name as the message catalog being reviewed, plus a trailing '.dl'. Then it will fix long lines from the message catalog being reviewed (e. g. if translator used poEdit) and update it with the version downloaded from Damned Lies. This way you can use 'diff' much more efficiently to proof-read the translation. Before you have the change to edit the message catalog being reviewed, the script will back it up with a 'pre' extension. Then gedit or other text editor will open the message catalog, while at the the terminal you can read a paged diff between the message catalog from Damned Lies and the one being reviewed. Press 'h' if you need any help to jump between highlighted changes, or to exit. If you don't like the default text editor, launch your favorite editor and edit this script. You can set something like poEdit instead of a text editor, if you want. But you really should try reviewing with a text editor, because of the usually better search and replace tools. After reading the output of diff, and fixing any errors, save the file in the text editor, but don't close it. When you quit the paged diff at the terminal, the script will run 'pofilter' (from the 'translate-toolkit' package) if it is installed. In fact, it will run it twice. First it will make only the critical tests, and then the others. Besides being less important, the last ones provide false-positives more frequently, so you don't have to fix everything they find. You can customize the second set of tests by editing this script. (It's easy,I swear!) After running this script, you'll have a proof-read message catalog, as well as the .pre version (which is prior to the review) and the .dl version (which is the same as in Damned Lies). You can still make any change to the message catalog being reviewed. Then, run diff between the message catalog and the .pre version to get a list of changes. If you commit translations, now you can update the ChangeLog and commit the message catalog ;) To avoid the 'If you need instructions ...' message at the end, please edit this script. " } ### Code execution starts here # # lang=${lang:-${LANG%.*}} editor=${editor:-"gedit"} my_dir="$HOME/.damned-lies" dl_server="${dl_server:-"http://l10n.gnome.org"}" dependencies="less xmlstarlet wget" releases_file="releases.xml" modules_file="gnome-modules.xml.in" case $# in "0") catalog=$lang.po [ -f "$catalog" ] || die "Error! Couldn't find $catalog" use_svn="yes" ;; "1") # TODO: if $1 is a SVN-controled $lang.po, set use_svn="yes" if [ -f "$1" ]; then catalog="$1" elif [ $1 = "--help" -o $1 = "-h" ]; then { help; exit; } else die "Error! Couldn't find $1" fi use_svn="" ;; "*") help exit 1 ;; esac [ "$use_svn" ] && dependencies="$dependencies svn" if [ -z "$(which --version)" ]; then echo "Warning! 'which' not found. Can't check for dependencies." else for dep in $dependencies; do exists "$dep" || die "Error! $dep not found." done fi echo -n "Downloading the message catalog from Damned Lies... " if [ "$use_svn" ]; then [ -z "$(ssh-add -l)" ] && ssh-add [ -z "$(svn diff)" ] && die "No local changes... leaving." svninfo_url="$(svn info --xml "$catalog" | xmlstarlet sel -t -v //url)" svninfo_root="$(svn info --xml "$catalog" | xmlstarlet sel -t -v //root)" module="$(basename $svninfo_root)" svnpath="$(dirname $module/${svninfo_url##$svninfo_root/})" case $svnpath in $module/trunk* ) release_xpath="//release[.//module[@id='$module' and not(@branch)]][last()]/@id" ;; $module/branches* ) branch=$(echo $svnpath | cut -d / -f 3) release_xpath="//release[.//module[@id='$module' and @branch='$branch']][last()]/@id" ;; * ) die "Error! Can't find branch name in $svnpath" ;; esac download "$dl_server/po/$lang/$releases_file" release=$(xmlstarlet sel -t -v "$release_xpath" "$my_dir/$releases_file") download "$dl_server/languages/$lang/$release.xml" pofile_xpath="//domain[svnpath='$svnpath'] | //document[svnpath='$svnpath']" pofile="$( xmlstarlet sel -t -m "$pofile_xpath" -v "pofile" "$my_dir/$release.xml")" else for i in 1 2 3 4; do eval part$i=$(echo $(basename "$catalog") | cut -d . -f $i) [ $? -eq 0 ] || die "Error! Invalid filename: $catalog" done [ $part4 = "po" ] || die "Error! Invalid filename: $catalog" lang=$part3 branch=$part2 # e. g. "HEAD", "gnome-2-24" download "http://svn.gnome.org/svn/damned-lies/trunk/$modules_file" f="$my_dir/$modules_file" # Some of the possible values for $part1: # - "libgweather": the domain name is the same as the module name # - "libgweather-locations": ops, this module has another translation domain! # - "user-guide": document from the gnome-user-docs module # - "help": nice. Now which module is this from? # if [ ! -z "$(xmlstarlet sel -t -c "//module[@id='$part1']" "$f")" ]; then module=$part1 module_type="domain" elif [ "$(xmlstarlet sel -t -c "count(//domain[@potbase='$part1'])" "$f")" -eq 1 ]; then module=$(xmlstarlet sel -t -v "//module[.//domain[@potbase='$part1']]/@id" "$f") module_type="domain" elif [ "$(xmlstarlet sel -t -c "count(//document[@id='$part1'])" "$f")" -eq 1 ]; then module=$(xmlstarlet sel -t -v "//module[.//document[@id='$part1']]/@id" "$f") module_type="document" elif [ "$(xmlstarlet sel -t -c "count(//document[@id='$part1'])" "$f")" -gt 1 ]; then module_list="$(xmlstarlet sel -t -m "//module[.//document[@id='$part1']]" -v "@id" -n "$f" | tr ' ' '\n' | sort)" module_count=$(echo $module_list | wc -w) echo echo echo "There are $module_count modules for this file name:" for m in $module_list; do # The dash builtin accepts escape sequences by default. # The bash posix mode doesn't. echo " $m" done # TODO: default value from Project-Id-Version echo -n "Please enter the desired module name: " read module module_is_valid="" for m in $module_list; do [ "$m" = "$module" ] && module_is_valid="yes" done [ "$module_is_valid" ] || die "Error! Invalid module name: $module" module_type="document" else die "Error! Couldn't find out the module name for file $catalog" fi if [ $module_type = "domain" ]; then pofile=POT/$module.$branch/$part1.$part2.$part3.$part4 elif [ $module_type = "document" ]; then pofile=POT/$module.$branch/docs/$part1.$part2.$part3.$part4 else die "Error! Invalid \$module_type: $module_type" fi fi catalog_dl="$catalog.dl" # The version downloaded from Damned Lies catalog_pre="$catalog.pre" # Same translations as before the script was run wget -q -O "$catalog_dl" "$dl_server/$pofile" [ $? -eq 0 ] || wget -q -O "$catalog_dl" \ "$dl_server/$(dirname $pofile)/$(basename $pofile .$lang.po).pot" [ $? -eq 0 ] || die "Error! Couldn't download $dl_server/$pofile" echo "done!" echo # Tidy up for better diffs msgmerge --update "$catalog" "$catalog_dl" --quiet || exit 1 msgcat "$catalog" --output="$catalog" || exit 1 cp "$catalog" "$catalog_pre" for file in "$catalog" "$catalog_dl"; do echo -n "$(basename "$file"): " msgfmt -cvo /dev/null "$file" done echo $editor "$catalog" & # Let the user see the ouput of msgfmt echo -n "Differences from the version in Damned Lies version... " sleep 3 diff --unified "$catalog_dl" "$catalog_pre" | less -p "^\+[^#]" [ $? -eq 0 ] && echo "done!" # http://translate.sourceforge.net/wiki/toolkit/pofilter exists pofilter && { # http://translate.sourceforge.net/wiki/toolkit/pofilter_tests critical_tests="accelerators escapes newlines nplurals \ printf tabs variables xmltags" include_critical="" for test in $critical_tests; do include_critical="$include_critical -t $test" done include_others="" for test in $pofilter_tests; do include_others="$include_others -t $test" done exclude_critical="" for test in $critical_tests; do exclude_critical="$exclude_critical --excludefilter=$test" done echo -n "Running critical pofilter tests... " sleep 2 pofilter "$catalog" \ --language=$lang --progress=none \ $pofilter_args \ $include_critical \ | less [ $? -eq 0 ] && echo "done!" # Results false if 'pofilter_tests' is set but empty. [ "${pofilter_tests-"--gnome"}" ] && { echo -n "Running other pofilter tests... " sleep 2 pofilter "$catalog" \ --language=$lang --progress=none \ $pofilter_args \ ${include_others:-"--gnome"} \ $exclude_critical \ | less [ $? -eq 0 ] && echo "done!" } } [ $avoid_tips ] || echo " If you need instructions on what to do from now on, run 'review --help' "