From a965e7db8e32427175090f266c24dbdcf6fc4941 Mon Sep 17 00:00:00 2001 From: Diego Pino Garcia Date: Thu, 13 Aug 2009 14:13:27 +0200 Subject: [PATCH] =?UTF-8?q?=20ItEr21S04ArquitecturaServidorItEr20S04:=20I?= =?UTF-8?q?=20nternationalization=20supp=C3=B2rt=20for=20.java=20and=20.zu?= =?UTF-8?q?l=20files=20based=20on=20GNU=20gettext?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- navalplanner-webapp/pom.xml | 34 ++- .../java/org/navalplanner/web/I18nHelper.java | 31 +++ .../main/resources/metainfo/tld/config.xml | 4 + .../src/main/webapp/WEB-INF/tld/i18n.tld | 15 ++ .../src/scripts/gettext_zul.pl | 247 ++++++++++++++++++ pom.xml | 27 ++ 6 files changed, 352 insertions(+), 6 deletions(-) create mode 100644 navalplanner-webapp/src/main/java/org/navalplanner/web/I18nHelper.java create mode 100644 navalplanner-webapp/src/main/resources/metainfo/tld/config.xml create mode 100644 navalplanner-webapp/src/main/webapp/WEB-INF/tld/i18n.tld create mode 100755 navalplanner-webapp/src/scripts/gettext_zul.pl diff --git a/navalplanner-webapp/pom.xml b/navalplanner-webapp/pom.xml index 4f8eacbc8..320d62cb8 100644 --- a/navalplanner-webapp/pom.xml +++ b/navalplanner-webapp/pom.xml @@ -11,11 +11,34 @@ war Naval Planner Web Client Module - + navalplanner-webapp + + + + + org.xnap.commons + maven-gettext-plugin + + i18n.Messages + ${project.build.sourceDirectory}/../resources/i18n + -k_ + + + + + + org.xnap.commons + gettext-commons + ${jdbcDriver.groupId} @@ -83,10 +106,9 @@ org.hibernate hibernate-validator - - javax.servlet - servlet-api - + + javax.servlet + servlet-api + - diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/I18nHelper.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/I18nHelper.java new file mode 100644 index 000000000..0a9e2299c --- /dev/null +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/I18nHelper.java @@ -0,0 +1,31 @@ +package org.navalplanner.web; + +import java.util.HashMap; +import java.util.Locale; + +import org.xnap.commons.i18n.I18n; +import org.xnap.commons.i18n.I18nFactory; +import org.zkoss.util.Locales; + + +public class I18nHelper { + + private static HashMap localesCache = new HashMap(); + + public static I18n getI18n() { + if (localesCache.keySet().contains(Locales.getCurrent())) { + return localesCache.get(Locales.getCurrent()); + } + + I18n i18n = I18nFactory.getI18n(I18nHelper.class, Locales + .getCurrent(), + org.xnap.commons.i18n.I18nFactory.FALLBACK); + localesCache.put(Locales.getCurrent(), i18n); + + return i18n; + } + + public static String _(String str) { + return getI18n().tr(str); + } +} \ No newline at end of file diff --git a/navalplanner-webapp/src/main/resources/metainfo/tld/config.xml b/navalplanner-webapp/src/main/resources/metainfo/tld/config.xml new file mode 100644 index 000000000..9b1040e62 --- /dev/null +++ b/navalplanner-webapp/src/main/resources/metainfo/tld/config.xml @@ -0,0 +1,4 @@ + + http://org.navalplanner.web/i18n + webapp/WEB-INF/tld/i18n.tld + diff --git a/navalplanner-webapp/src/main/webapp/WEB-INF/tld/i18n.tld b/navalplanner-webapp/src/main/webapp/WEB-INF/tld/i18n.tld new file mode 100644 index 000000000..32d5b8173 --- /dev/null +++ b/navalplanner-webapp/src/main/webapp/WEB-INF/tld/i18n.tld @@ -0,0 +1,15 @@ + + + http://org.navalplanner.web/i18n + + + + _ + org.navalplanner.web.I18nHelper + + java.lang.String _(java.lang.String name) + + + + + diff --git a/navalplanner-webapp/src/scripts/gettext_zul.pl b/navalplanner-webapp/src/scripts/gettext_zul.pl new file mode 100755 index 000000000..3cbae220f --- /dev/null +++ b/navalplanner-webapp/src/scripts/gettext_zul.pl @@ -0,0 +1,247 @@ +#!/usr/bin/perl + +# Parses ZUL files for TOKEN and adds entries to a keys.pot file +# (respecting keys.pot format) +# +# If keys.pot exists, appends new elements to it +# +# If a msgid exists inside keys.pot file, updates its list of files +# pointing to that entry +# + +# Copyright (C) 2008 Diego Pino GarcĂ­a +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + +use File::Spec; +use Getopt::Long qw(:config gnu_getopt no_ignore_case); +use Date::Format; + +$DEBUG = 0; +$TOKEN = 'i18n:_'; +$DEFAULT_KEYS_FILE = "./keys.pot"; + +GetOptions('dir|d=s' => \$OPTS{'DIR'}, + 'help|h!' => \$OPTS{'HELP'}, + 'keys|k=s' => \$OPTS{'KEYS'}); + +if ($OPTS{'HELP'} || !$OPTS{'DIR'}) { + &help(); +} + +if (!$OPTS{'KEYS'}) { + $OPTS{'KEYS'} = $DEFAULT_KEYS_FILE; +} + +# keys.pot file exists +if (-s $OPTS{'KEYS'} != 0) { + &parse_KEYS($OPTS{'KEYS'}); + $header = &get_keys_header($OPTS{'KEYS'}); + &create_keys_file($OPTS{'KEYS'}, $header); +} else { + &create_keys_file($OPTS{'KEYS'}); +} + +# Open keys.pot file to append +open FILE, ">>$OPTS{'KEYS'}"; + +# Find all .zul files from dir +@filenames = split "\n", `find $OPTS{'DIR'} -name "*.zul" | grep -v target`; +# Parse all files and store parsed elements into %entries +map {&parse_ZUL($_)} @filenames; + +# Print entries to file +foreach $msgid (keys %entries) { + foreach $filename (@{$entries{$msgid}}) { + print FILE "\#: $filename\n"; + } + print FILE "msgid \"$msgid\"\n"; + print FILE "msgstr \"\"\n\n"; +} + +close FILE; + +########################################################## + +sub create_keys_file() +{ + my ($filename, $header) = @_; + + if ($filename eq "") { +# &debug("filename: $filename"); + $filename = $DEFAULT_KEYS_FILE; + } + if ($header eq "") { +# &debug("header: $header"); + $header = &get_default_keys_header(); + } + + open FILE, ">$filename"; + print FILE $header; + close FILE; +} + +sub get_default_keys_header() +{ + $creation_date = time2str("%Y-%m-%d %H:%M %z", time); + + # Create file + open FOUT, ">$OPTS{'KEYS'}"; +print FOUT qq#\# SOME DESCRIPTIVE TITLE. +\# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +\# This file is distributed under the same license as the PACKAGE package. +\# FIRST AUTHOR , YEAR. +\# +\#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\\n" +"Report-Msgid-Bugs-To: \\n" +"POT-Creation-Date: $creation_date\\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n" +"Last-Translator: FULL NAME \\n" +"Language-Team: LANGUAGE \\n" +"MIME-Version: 1.0\\n" +"Content-Type: text/plain; charset=CHARSET\\n" +"Content-Transfer-Encoding: 8bit\\n" +\n#; +} + +## +# Gets a keys.pot header from keys.pot file +# +# A keys.pot header happens at the beggining of the keys.pot file till the first occurrence +# of an entry (marked by the symbol #: +# +sub get_keys_header() +{ + my ($filename) = @_; + + open FILE, $filename; + while ( ($line = ) && !($line =~ /^#:\s+/) ) { + $header .= $line; + } + close FILE; + + return $header; +} + +## +# Parse a key.pot file. A keys.pot file has the following structure +# +# (#: filename:line)+ +# msgid "_msgid_" +# +sub parse_KEYS() +{ + my ($keys_filename) = @_; + my @filenames = (); + + open FILE, $keys_filename; + while () { + if (/^#:\s+(.*)/) { +# &debug("filenames: ".$1); + push @filenames, $1; + } + if (/^msgid "(\w+)"/) { +# &debug("msgid: $1"); + $entries{$1} = [@filenames]; + @filenames = (); + } + } + close FILE; +} + +## +# Parses ZUL file and stores elements successfully parsed into entries array +# +# %entries is an associative array storing: +# +# key, msgid (Message identifier, must be unique in a keys.pot file) +# value, array of filenames that references that entry +# +# Every element in array of filenames, is an entry of the following format: +# absolute_path_of_file:line_number +# +# @param filename ZUL file to parse +# +sub parse_ZUL() +{ + my($filename) = @_; + + @lines = split "\n",`grep -RHn "$TOKEN" $filename`; + foreach $line (@lines) { + &debug($line); + # relative_path_to_file:line_number match + ($filename, $matching) = ($line =~ /(^[a-zA-Z\.\/_]+:[0-9]+):\s+(.*)/); + ($msgid) = ($matching =~ /$TOKEN\('(\w+)'\)/); + + &debug("msgid: $msgid"); + &debug("filename: $filename"); + &debug("matching: $matching"); + + # Get absolute path of file (passing line number aswell is OK) + $filename = File::Spec->rel2abs(&trim($filename)); + if (!$entries{$msgid}) { + # Create new array with element filename + $entries{$msgid} = [($filename)]; + } else { + if (!&in_array($filename, @{$entries{$msgid}})) { + # Append filename to array of filenames in that entry + $entries{$msgid} = [(@{$entries{$msgid}}, $filename)]; + } + } + } +} + +sub in_array() +{ + my ($needle, @haystack) = @_; + + foreach (@haystack) { + if ($_ eq $needle) { + return 1; + } + } + return 0; +} + +sub debug() +{ + my($string) = @_; + + if ($DEBUG) { + print $string."\n"; + } +} + +sub help() +{ + print "Parses ZUL files searching for gettext entries and append to keys.pot file\n"; + print "\t--dir, -d\tMANDATORY\tBase directory\n"; + print "\t--keys, -k\tOPTIONAL\tPath to keys.pot file\n"; + print "\t--help, -h\tOPTIONAL\tShow this help\n"; + + exit(); +} + +sub trim($) +{ + my $string = shift; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; +} diff --git a/pom.xml b/pom.xml index 5e29ed872..1bf92034d 100644 --- a/pom.xml +++ b/pom.xml @@ -159,9 +159,24 @@ + + + + + gettext-commons-site + http://gettext-commons.googlecode.com/svn/maven-repository + + + + + + org.xnap.commons + gettext-commons + 0.9.6 + ${jdbcDriver.groupId} @@ -384,6 +399,18 @@ + + + + + org.xnap.commons + maven-gettext-plugin + 1.2.0 + + i18n.Messages + + +