ItEr21S04ArquitecturaServidorItEr20S04: I nternationalization suppòrt for .java and .zul files based on GNU gettext
This commit is contained in:
parent
2456db8408
commit
a965e7db8e
6 changed files with 352 additions and 6 deletions
|
|
@ -11,11 +11,34 @@
|
|||
<packaging>war</packaging>
|
||||
<name>Naval Planner Web Client Module</name>
|
||||
|
||||
<build>
|
||||
<build>
|
||||
<finalName>navalplanner-webapp</finalName>
|
||||
|
||||
<!--
|
||||
Gettext Commons plugin
|
||||
goals:
|
||||
merge: parses source code and generates keys.pot
|
||||
dist: generates binary Resoruce Bundle (Messages_XX.class)
|
||||
-->
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.xnap.commons</groupId>
|
||||
<artifactId>maven-gettext-plugin</artifactId>
|
||||
<configuration>
|
||||
<targetBundle>i18n.Messages</targetBundle>
|
||||
<poDirectory>${project.build.sourceDirectory}/../resources/i18n</poDirectory>
|
||||
<keywords>-k_</keywords>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<!-- Gettext commons -->
|
||||
<dependency>
|
||||
<groupId>org.xnap.commons</groupId>
|
||||
<artifactId>gettext-commons</artifactId>
|
||||
</dependency>
|
||||
<!-- JDBC driver -->
|
||||
<dependency>
|
||||
<groupId>${jdbcDriver.groupId}</groupId>
|
||||
|
|
@ -83,10 +106,9 @@
|
|||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -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<Locale, I18n> localesCache = new HashMap<Locale, I18n>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<taglib>
|
||||
<taglib-uri>http://org.navalplanner.web/i18n</taglib-uri>
|
||||
<taglib-location>webapp/WEB-INF/tld/i18n.tld</taglib-location>
|
||||
</taglib>
|
||||
15
navalplanner-webapp/src/main/webapp/WEB-INF/tld/i18n.tld
Normal file
15
navalplanner-webapp/src/main/webapp/WEB-INF/tld/i18n.tld
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<taglib>
|
||||
<uri>http://org.navalplanner.web/i18n</uri>
|
||||
<description>
|
||||
</description>
|
||||
<function>
|
||||
<name>_</name>
|
||||
<function-class>org.navalplanner.web.I18nHelper</function-class>
|
||||
<function-signature>
|
||||
java.lang.String _(java.lang.String name)
|
||||
</function-signature>
|
||||
<description>
|
||||
</description>
|
||||
</function>
|
||||
</taglib>
|
||||
247
navalplanner-webapp/src/scripts/gettext_zul.pl
Executable file
247
navalplanner-webapp/src/scripts/gettext_zul.pl
Executable file
|
|
@ -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 <dpino@igalia.com>
|
||||
#
|
||||
# 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 <EMAIL\@ADDRESS>, 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 <EMAIL\@ADDRESS>\\n"
|
||||
"Language-Team: LANGUAGE <LL\@li.org>\\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 = <FILE>) && !($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 (<FILE>) {
|
||||
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;
|
||||
}
|
||||
27
pom.xml
27
pom.xml
|
|
@ -159,9 +159,24 @@
|
|||
<!--
|
||||
===================================================================
|
||||
-->
|
||||
|
||||
<repositories>
|
||||
<!-- Getttext commons -->
|
||||
<repository>
|
||||
<id>gettext-commons-site</id>
|
||||
<url>http://gettext-commons.googlecode.com/svn/maven-repository</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<!-- Dependency management -->
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- Gettext commons -->
|
||||
<dependency>
|
||||
<groupId>org.xnap.commons</groupId>
|
||||
<artifactId>gettext-commons</artifactId>
|
||||
<version>0.9.6</version>
|
||||
</dependency>
|
||||
<!-- JDBC driver -->
|
||||
<dependency>
|
||||
<groupId>${jdbcDriver.groupId}</groupId>
|
||||
|
|
@ -384,6 +399,18 @@
|
|||
|
||||
<plugins>
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Gettext configuration -->
|
||||
<plugin>
|
||||
<!-- <groupId>org.xnap.commons</groupId> -->
|
||||
<groupId>org.xnap.commons</groupId>
|
||||
<artifactId>maven-gettext-plugin</artifactId>
|
||||
<version>1.2.0</version>
|
||||
<configuration>
|
||||
<targetBundle>i18n.Messages</targetBundle>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Compiler configuration -->
|
||||
<plugin>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue