Index: lutinutil/src/java/org/codelutin/i18n/I18n.java diff -u /dev/null lutinutil/src/java/org/codelutin/i18n/I18n.java:1.1 --- /dev/null Wed Oct 4 14:52:00 2006 +++ lutinutil/src/java/org/codelutin/i18n/I18n.java Wed Oct 4 14:51:55 2006 @@ -0,0 +1,185 @@ +/* *##% + * Copyright (C) 2002, 2003 Code Lutin + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +/* * + * I18n.java + * + * Created: 2 d?c. 2003 + * + * @author Benjamin Poussin + * Copyright Code Lutin + * @version $Revision: 1.1 $ + * + * Mise a jour: $Date: 2006/10/04 14:51:55 $ + * par : $Author: bpoussin $ + */ + +package org.codelutin.i18n; + +import java.text.MessageFormat; +import java.util.Locale; +import java.util.logging.Logger; + +/** + * This class is a facility for internationalization. To use it in your soft, + * you can either : + * + * + * + *@author poussin + *@created 2 d?cembre 2003 + */ +public class I18n { + + /** Filtre a appliquer avant de retourner les chaines */ + protected static I18nFilter filter = null; + + /** l'objet langue ? utiliser */ + protected static Language language = null; + + /** Indique le chamin du fichier dans lequel ecrire les entrees non trouvees */ + protected static String recordFilePath = null; + + /** + * Retourne la chaine traduite si possible. + * + *@param message la chaine ? traduire + *@return la traduction si possible ou la chaine pass?e en param?tre + * sinon. + */ + public static String _(String message) { + if (language == null) { + return applyFilter(message); + } + return applyFilter(I18n.language.translate(message)); + } + + /** + * Retourne la chaine traduite si possible. + * + *@param message message format? avec la m?me syntaxe que {@link + * java.text.MessageFormat} + *@param args les param?tres pour le message. + *@return la traduction si possible ou la chaine pass?e en param?tre + * sinon. + */ + public static String _(String message, Object ... args) { + String result = message; + if (language != null) { + result = I18n.language.translate(message); + } + try { + return applyFilter(MessageFormat.format(result, args)); + } catch (Exception eee) { + try { + return applyFilter(MessageFormat.format(message, args)); + } catch (Exception zzz) { + Logger.getLogger("org.codelutin.i18n.I18n").warning( + "Message can't be translated: '" + message + "'"); + return applyFilter(message); + } + } + } + + /** + * Retourne la chaine passé en argument + * + *@param message la chaine à traduire + *@return la chaine passée en argument + * sinon. + */ + public static String n_(String message) { + return message; + } + + /** + * Retourne la chaine passée en argument. + * + *@param message message formaté avec la même syntaxe que {@link + * java.text.MessageFormat} + *@param args les paramètres pour le message. + *@return le message passé en argument mais formatté + * avec les paramètres + */ + public static String n_(String message, Object ... args) { + try{ + return MessageFormat.format(message, args); + } catch (Exception eee) { + Logger.getLogger("org.codelutin.i18n.I18n").warning( + "Message can't be formated: '" + message + "'"); + return message; + } + } + + /** + * Applique le filtre s'il y en a un + * + *@param message le message qui devrait ?tre retourn? avant application du + * filtre. + *@return TODO Description of the Return Value + */ + protected static String applyFilter(String message) { + if (filter != null) { + return filter.applyFilter(message); + } + return message; + } + + /** + * Initialise la librairie. + * + *@param language une cha?ne repr?sentant la langue ? utiliser fr, en, ... + */ + public static void init(String language) { + I18n.language = new Language(new Locale(language)); + } + + /** + * Initialise la librairie + * + *@param language une cha?ne repr?sentant la langue ? utiliser fr, en, ... + *@param country une cha?ne repr?sentant le pays ? utiliser FR, GB, ... + */ + public static void init(String language, String country) { + I18n.language = new Language(new Locale(language, country)); + } + + /** + * Change le filtre des cha?nes traduites + * + *@param filter l'objet filtre ? utiliser + */ + public static void setFilter(I18nFilter filter) { + I18n.filter = filter; + } + + public static void setRecordFilePath(String recordFilePath) { + I18n.recordFilePath = recordFilePath; + } + +} //I18n Index: lutinutil/src/java/org/codelutin/i18n/I18nBundleBridge.java diff -u /dev/null lutinutil/src/java/org/codelutin/i18n/I18nBundleBridge.java:1.1 --- /dev/null Wed Oct 4 14:52:00 2006 +++ lutinutil/src/java/org/codelutin/i18n/I18nBundleBridge.java Wed Oct 4 14:51:55 2006 @@ -0,0 +1,51 @@ +/* *##% +* Copyright (C) 2002, 2003, 2004, 2005, 2006 Code Lutin, +* Cedric Pineau, Benjamin Poussin, Arnaud Thimel +* +* +* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*##%*/ + +/* * +* BundleBridge.java +* +* Created: 6 sept. 06 +* +* @author Arnaud Thimel +* @version $Revision: 1.1 $ +* +* Mise a jour: $Date: 2006/10/04 14:51:55 $ +* par : $Author: bpoussin $ +*/ + +package org.codelutin.i18n; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.ResourceBundle; + +public class I18nBundleBridge extends ResourceBundle { + + @Override + public Enumeration getKeys() { + throw new UnsupportedOperationException(); + } + + @Override + public Object handleGetObject(String key) { + return I18n._(key); + } + +} Index: lutinutil/src/java/org/codelutin/i18n/I18nDefaultTooltipFilter.java diff -u /dev/null lutinutil/src/java/org/codelutin/i18n/I18nDefaultTooltipFilter.java:1.1 --- /dev/null Wed Oct 4 14:52:01 2006 +++ lutinutil/src/java/org/codelutin/i18n/I18nDefaultTooltipFilter.java Wed Oct 4 14:51:55 2006 @@ -0,0 +1,41 @@ +/* *##% + * Copyright (C) 2002, 2003 Code Lutin + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +/* * + * i18nDefaultTooltipFilter.java + * + * Created: 2 déc. 2003 + * + * @author Benjamin Poussin + * Copyright Code Lutin + * @version $Revision: 1.1 $ + * + * Mise a jour: $Date: 2006/10/04 14:51:55 $ + * par : $Author: bpoussin $ + */ + +package org.codelutin.i18n; + +public class I18nDefaultTooltipFilter implements I18nFilter { // I18nDefaultTooltipFilter + public String applyFilter(String message){ + if(message != null && message.startsWith("defaultToolTip-")) + return null; + return message; + } +} // I18nDefaultTooltipFilter + Index: lutinutil/src/java/org/codelutin/i18n/I18nFileReader.java diff -u /dev/null lutinutil/src/java/org/codelutin/i18n/I18nFileReader.java:1.1 --- /dev/null Wed Oct 4 14:52:01 2006 +++ lutinutil/src/java/org/codelutin/i18n/I18nFileReader.java Wed Oct 4 14:51:55 2006 @@ -0,0 +1,160 @@ +/* *##% + * Copyright (C) 2002, 2003, 2004 + * Code Lutin, Cédric Pineau, Benjamin Poussin + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +/* * + * I18nFileReader.java + * + * Created: Nov 22, 2004 + * + * @author Cédric Pineau + * @version $Revision: 1.1 $ + * + * Last update : $Date: 2006/10/04 14:51:55 $ + * by : $Author: bpoussin $ + */ + +package org.codelutin.i18n; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.spi.CharsetProvider; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Pattern; + +import sun.nio.cs.AbstractCharsetProvider; +import sun.nio.cs.StandardCharsets; +import sun.nio.cs.ext.ExtendedCharsets; + +/** + * Classe assurant la lecture et les possibles traitement nécessaires à I18n. + */ +public class I18nFileReader extends Properties { + + private static Pattern commentPattern = Pattern.compile("[^\\\\]#"); + + private static Pattern splitPattern = Pattern.compile("[^\\\\]="); + + public void load(InputStream inStream, String encoding) throws IOException { + int available = inStream.available(); + byte[] bytes = new byte[available]; + inStream.read(bytes); + ByteBuffer buf = ByteBuffer.wrap(bytes); + Charset charset = new StandardCharsets().charsetForName(encoding); + CharBuffer charBuf = charset.decode(buf); + Charset utf8Charset = new StandardCharsets().charsetForName("ISO8859-1"); + ByteBuffer byteBuf = utf8Charset.encode(charBuf); + super.load(new ByteArrayInputStream(byteBuf.array())); + } + + private String interpretBackslashes(String message) { + int backslashIndex = -1; + while ((backslashIndex = message.indexOf("\\", backslashIndex+1)) != -1) { + if (message.length() >= backslashIndex + 1) { + char charNextToBackslash = message.charAt(backslashIndex + 1); + char replacementChar; + switch (charNextToBackslash) { + case '\\': + replacementChar = '\\'; + break; + case 't': + replacementChar = '\t'; + break; + case 'n': + replacementChar = '\n'; + break; + case ' ': + replacementChar = ' '; + break; + case '=': + replacementChar = '='; + break; + case ':': + replacementChar = ':'; + break; + default: + replacementChar = '\\'; + break; + } + message = message.substring(0, backslashIndex) + replacementChar + message.substring(backslashIndex + 2); + } + } + return message; + } + +// public void store(OutputStream outStream, String header) throws IOException { +// BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outStream, "UTF-8")); +// StringTokenizer tokens = new StringTokenizer(header, "\n"); +// while (tokens.hasMoreTokens()) { +// String line = tokens.nextToken(); +// if (!line.trim().startsWith("#")) { +// writer.write("#"); +// } +// writer.write(line + "\n"); +// } +// +// for (Iterator iter = super.keySet().iterator(); iter.hasNext();) { +// String key = (String) iter.next(); +// String value = super.getProperty(key); +// key = serializeBackslashes(key); +// value = serializeBackslashes(value); +// writer.write(key+"="+value+"\n"); +// } +// writer.close(); +// } + + private static char[] chars = {'\\', '\n', '\t', ' ', '=', ':'}; + + private String serializeBackslashes(String message) { + for (char c : chars) { + int charIndex = -1; + while ((charIndex = message.indexOf(c, charIndex+2)) != -1) { + String replacementString = "" + c; + switch(c) { + case '\\': + replacementString = "\\\\"; + break; + case '\t': + replacementString = "\\t"; + break; + case '\n': + replacementString = "\\n"; + break; + case ' ': + replacementString = "\\ "; + break; + case '=': + replacementString = "\\="; + break; + case ':': + replacementString = "\\:"; + break; + } + message = message.substring(0, charIndex) + replacementString + message.substring(charIndex + 1); + } + } + return message; + } + +} //I18nFileReader Index: lutinutil/src/java/org/codelutin/i18n/I18nFilter.java diff -u /dev/null lutinutil/src/java/org/codelutin/i18n/I18nFilter.java:1.1 --- /dev/null Wed Oct 4 14:52:01 2006 +++ lutinutil/src/java/org/codelutin/i18n/I18nFilter.java Wed Oct 4 14:51:55 2006 @@ -0,0 +1,37 @@ +/* *##% + * Copyright (C) 2002, 2003 Code Lutin + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%*/ + +/* * + * i18nFilter.java + * + * Created: 2 déc. 2003 + * + * @author Benjamin Poussin + * Copyright Code Lutin + * @version $Revision: 1.1 $ + * + * Mise a jour: $Date: 2006/10/04 14:51:55 $ + * par : $Author: bpoussin $ + */ + +package org.codelutin.i18n; + +public interface I18nFilter { // I18nFilter + public String applyFilter(String message); +} // I18nFilter + Index: lutinutil/src/java/org/codelutin/i18n/Language.java diff -u /dev/null lutinutil/src/java/org/codelutin/i18n/Language.java:1.1 --- /dev/null Wed Oct 4 14:52:01 2006 +++ lutinutil/src/java/org/codelutin/i18n/Language.java Wed Oct 4 14:51:55 2006 @@ -0,0 +1,164 @@ +/**##%% + * Copyright (C) 2002, 2003 Code Lutin + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *##%%**/ + +/** + * Language.java + */ + +package org.codelutin.i18n; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.Properties; +import java.util.logging.Logger; + +import org.codelutin.util.Resource; + +/** + * This class is used byte the i18n class. It encapsulates the translation + * resource for one language + */ +public class Language { + + protected Properties resource; + + public Language(Locale l) { + String[] filenames = getFilenames(l); + for (int i = 0; i < filenames.length; i++) { + try { + URL url = Resource.getURL(filenames[i]); + Logger.getLogger("org.codelutin.i18n.Language.Language").info( + "Langue file URL:" + url); + resource = new I18nFileReader(); + ((I18nFileReader)resource).load(url.openStream(), "UTF-8"); + } catch (Exception eee) { + Logger + .getLogger("org.codelutin.i18n.Language.Language") + .warning( + "Unable to load language file: " + filenames[i]); + resource = null; + continue; + } + break; + } + } + + /** + * Retourne le nom des fichiers à rechercher pour la traduction dans le + * bonne ordre de recherche. + * + * @param l + * la locale a utilise pour trouver le nom des fichiers + * @return un tableau de nom de fichier + */ + String[] getFilenames(Locale l) { + String prefix = "language"; + String postfix = ".properties"; + ArrayList result = new ArrayList(); + if (!"".equals(l.getLanguage())) { + if (!"".equals(l.getCountry())) { + result.add(prefix + "-" + l.getLanguage() + "_" + + l.getCountry() + postfix); + } + result.add(prefix + "-" + l.getLanguage() + postfix); + } + result.add(prefix + postfix); + return (String[]) result.toArray(new String[result.size()]); + } + + /** + * translate takes a sentence and returns its translation if found, the very + * same string otherwise. + */ + public String translate(String sentence) { + if (resource == null) { + recordNotFound(sentence); + return sentence; + } + try { + String result = resource.getProperty(sentence); + if (null != result && !"".equals(result)) + return result; + recordNotFound(sentence); + return sentence; + } catch (MissingResourceException eee) { + Logger.getLogger("org.codelutin.i18n.Language.translate").info( + "Resource " + sentence + " unavailable"); + return sentence; + } catch (Exception eee) { + Logger.getLogger("org.codelutin.i18n.Language.translate").severe( + "Unexpected error while translating : " + eee); + return sentence; + } + } + + private void recordNotFound(String key) { + if (I18n.recordFilePath != null && key != null && !"".equals(key)) { + File f = new File(I18n.recordFilePath); + Properties recordProps = new Properties(); + try { + if (f.exists()) { + FileInputStream fis = new FileInputStream(f); + recordProps.load(fis); + fis.close(); + } + recordProps.put(key, ""); + FileOutputStream fos = new FileOutputStream(f); + recordProps.store(fos, "Adding the key : " + key); + fos.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * untranslate takes a translated sentence and returns the original one if + * found, the very same string otherwise. + */ + public String untranslate(String sentence) { + if (resource == null) + return sentence; + try { + Enumeration e = resource.propertyNames(); + // Look for the given sentence through all translations + while (e.hasMoreElements()) { + String key = (String) e.nextElement(); + String translation = resource.getProperty(key); + // If found returns the corresponding key + if (sentence.equals(translation)) + return key; + } + } catch (MissingResourceException eee) { + // Well, this can't happen... + } + // No such translated sentence in our resourceBundle + return sentence; + } + +} \ No newline at end of file