├── src ├── examples │ ├── Messages.properties │ ├── en.properties │ ├── de.properties │ └── I18nExample.java ├── test-resources │ ├── DefaultMessages.properties │ └── org │ │ └── xnap │ │ └── commons │ │ └── i18n │ │ ├── testpackage │ │ ├── TestMessages_fr.properties │ │ ├── TestMessages_de.properties │ │ ├── resources │ │ │ ├── OwnMessages_de.properties │ │ │ └── i18n.properties │ │ ├── TestMessages.properties │ │ └── i18n.properties │ │ └── i18n.properties ├── java │ └── org │ │ └── xnap │ │ └── commons │ │ └── i18n │ │ ├── package.html │ │ ├── LocaleChangeListener.java │ │ ├── LocaleChangeEvent.java │ │ ├── EmptyResourceBundle.java │ │ ├── I18nCache.java │ │ ├── I18nManager.java │ │ ├── I18nFactory.java │ │ └── I18n.java ├── assembly │ ├── bin.xml │ └── src.xml └── test │ └── org │ └── xnap │ └── commons │ └── i18n │ ├── testpackage │ ├── noresources │ │ └── HasNoOwnResources.java │ ├── resources │ │ └── HasItsOwnResources.java │ └── MockResourceBundle.java │ ├── EmptyResourceBundleTest.java │ ├── I18nCacheTest.java │ ├── I18nManagerTest.java │ ├── I18nFactoryTest.java │ └── I18nTest.java ├── xdocs ├── gettext-structure.odg ├── gettext-structure.png ├── index.xml ├── navigation.xml ├── maven.xml ├── changes.xml └── tutorial.xml ├── .settings ├── org.eclipse.mylyn.tasks.ui.prefs ├── org.eclipse.jdt.ui.prefs └── org.eclipse.jdt.core.prefs ├── .classpath ├── .project ├── README ├── ChangeLog ├── po ├── keys.pot └── de.po ├── pom.xml └── LICENSE.txt /src/examples/Messages.properties: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test-resources/DefaultMessages.properties: -------------------------------------------------------------------------------- 1 | source=DefaultBundle 2 | -------------------------------------------------------------------------------- /src/test-resources/org/xnap/commons/i18n/testpackage/TestMessages_fr.properties: -------------------------------------------------------------------------------- 1 | value=valeur -------------------------------------------------------------------------------- /src/test-resources/org/xnap/commons/i18n/testpackage/TestMessages_de.properties: -------------------------------------------------------------------------------- 1 | value=Wert 2 | -------------------------------------------------------------------------------- /src/test-resources/org/xnap/commons/i18n/testpackage/resources/OwnMessages_de.properties: -------------------------------------------------------------------------------- 1 | own=yes -------------------------------------------------------------------------------- /src/test-resources/org/xnap/commons/i18n/i18n.properties: -------------------------------------------------------------------------------- 1 | basename=org.xnap.commons.i18n.Messages 2 | -------------------------------------------------------------------------------- /src/test-resources/org/xnap/commons/i18n/testpackage/TestMessages.properties: -------------------------------------------------------------------------------- 1 | #this file should stay empty -------------------------------------------------------------------------------- /xdocs/gettext-structure.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgettext/gettext-commons/HEAD/xdocs/gettext-structure.odg -------------------------------------------------------------------------------- /xdocs/gettext-structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgettext/gettext-commons/HEAD/xdocs/gettext-structure.png -------------------------------------------------------------------------------- /src/test-resources/org/xnap/commons/i18n/testpackage/i18n.properties: -------------------------------------------------------------------------------- 1 | basename=org.xnap.commons.i18n.testpackage.TestMessages -------------------------------------------------------------------------------- /src/test-resources/org/xnap/commons/i18n/testpackage/resources/i18n.properties: -------------------------------------------------------------------------------- 1 | basename=org.xnap.commons.i18n.testpackage.resources.OwnMessages -------------------------------------------------------------------------------- /.settings/org.eclipse.mylyn.tasks.ui.prefs: -------------------------------------------------------------------------------- 1 | #Mon Aug 06 15:59:00 EDT 2007 2 | eclipse.preferences.version=1 3 | project.repository.kind=web 4 | project.repository.url=http\://code.google.com/p/gettext-commons/issues 5 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.ui.prefs: -------------------------------------------------------------------------------- 1 | #Mon Aug 06 16:07:09 EDT 2007 2 | eclipse.preferences.version=1 3 | formatter_profile=_Gettext Commons 4 | formatter_settings_version=11 5 | org.eclipse.jdt.ui.text.custom_code_templates= 6 | -------------------------------------------------------------------------------- /src/java/org/xnap/commons/i18n/package.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Provides classes for internationalization (i18n).

7 | 8 |

To learn how to make use of the Gettext Commons internationalization, 9 | please have a look at this tutorial.

10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | gettext-commons 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.maven.ide.eclipse.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.maven.ide.eclipse.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /xdocs/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gettext Commons 6 | 7 | 8 |
9 |

The Gettext Commons project provides Java classes for 10 | internationalization (i18n) through GNU gettext.

12 | 13 |

See 14 | the project 15 | page for more information and downloads.

16 |
17 | 18 |
19 | 20 | 25 | -------------------------------------------------------------------------------- /src/assembly/bin.xml: -------------------------------------------------------------------------------- 1 | 2 | bin 3 | 4 | tar.gz 5 | tar.bz2 6 | zip 7 | 8 | 9 | 10 | 11 | README* 12 | LICENSE* 13 | NOTICE* 14 | ChangeLog* 15 | 16 | 17 | 18 | target 19 | 20 | 21 | *.jar 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/assembly/src.xml: -------------------------------------------------------------------------------- 1 | 2 | src 3 | 4 | tar.gz 5 | tar.bz2 6 | zip 7 | 8 | 9 | 10 | 11 | README* 12 | LICENSE* 13 | NOTICE* 14 | ChangeLog* 15 | pom.xml 16 | 17 | true 18 | 19 | 20 | src 21 | true 22 | 23 | 24 | -------------------------------------------------------------------------------- /xdocs/navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Gettext Commons 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/examples/en.properties: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | !=Project-Id-Version\: PACKAGE VERSION\nReport-Msgid-Bugs-To\: \nPOT-Creation-Date\: 2004-10-17 19\:24+0200\nPO-Revision-Date\: YEAR-MO-DA HO\:MI+ZONE\nLast-Translator\: FULL NAME \nLanguage-Team\: LANGUAGE \nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\n 8 | 9 | #: I18nExample.java:21 10 | !This\ text\ is\ marked\ for\ translation\ and\ is\ translated= 11 | 12 | #: I18nExample.java:23 13 | !This\ text\ is\ tranlated\ and\ padded= 14 | 15 | #: I18nExample.java:25 16 | !This\ text\ is\ marked\ for\ translation\ but\ not\ translated= 17 | 18 | #: I18nExample.java:27 19 | #, java-format 20 | !This\ is\ the\ {0}.\ text\ to\ be\ translated= 21 | 22 | #: I18nExample.java:29 23 | !chat\ (verb)= 24 | 25 | #: I18nExample.java:31 26 | !chat\ (noun)= 27 | -------------------------------------------------------------------------------- /src/test/org/xnap/commons/i18n/testpackage/noresources/HasNoOwnResources.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Felix Berger 5 | * Copyright (C) 2005 Steffen Pingel 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | package org.xnap.commons.i18n.testpackage.noresources; 22 | 23 | public class HasNoOwnResources 24 | { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/test/org/xnap/commons/i18n/testpackage/resources/HasItsOwnResources.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Felix Berger 5 | * Copyright (C) 2005 Steffen Pingel 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | package org.xnap.commons.i18n.testpackage.resources; 22 | 23 | public class HasItsOwnResources 24 | { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/examples/de.properties: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | !=Project-Id-Version\: PACKAGE VERSION\nReport-Msgid-Bugs-To\: \nPOT-Creation-Date\: 2004-10-17 19\:24+0200\nPO-Revision-Date\: 2004-10-17 19\:28+0200\nLast-Translator\: FULL NAME \nLanguage-Team\: LANGUAGE \nMIME-Version\: 1.0\nContent-Type\: text/plain; charset\=UTF-8\nContent-Transfer-Encoding\: 8bit\n 8 | 9 | #: I18nExample.java:21 10 | This\ text\ is\ marked\ for\ translation\ and\ is\ translated=Dieser Text ist f\u00fcr die \u00dcbersetzung markiert und wird auch \u00fcbersetzt 11 | 12 | #: I18nExample.java:23 13 | This\ text\ is\ tranlated\ and\ padded=Dieser Text wird \u00fcbersetzt und am Rand mit Leerzeichen aufgef\u00fcllt 14 | 15 | #: I18nExample.java:25 16 | This\ text\ is\ marked\ for\ translation\ but\ not\ translated=Dieser Text ist f\u00fcr die \u00dcbersetzung markiert wird aber nicht \u00fcbersetzt 17 | 18 | #: I18nExample.java:27 19 | #, java-format 20 | This\ is\ the\ {0}.\ text\ to\ be\ translated=Dies ist der {0}. Text der \u00fcbersetzt wird 21 | 22 | #: I18nExample.java:29 23 | chat\ (verb)=Chatten 24 | 25 | #: I18nExample.java:31 26 | chat\ (noun)=Chat 27 | -------------------------------------------------------------------------------- /src/test/org/xnap/commons/i18n/EmptyResourceBundleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Steffen Pingel 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | package org.xnap.commons.i18n; 21 | 22 | import junit.framework.TestCase; 23 | 24 | /** 25 | * @author Steffen Pingel 26 | */ 27 | public class EmptyResourceBundleTest extends TestCase { 28 | 29 | public void test() 30 | { 31 | EmptyResourceBundle bundle = new EmptyResourceBundle(null); 32 | assertEquals("Foo", bundle.getObject("Foo")); 33 | assertFalse(bundle.getKeys().hasMoreElements()); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/java/org/xnap/commons/i18n/LocaleChangeListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Steffen Pingel 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | package org.xnap.commons.i18n; 21 | 22 | import java.util.Locale; 23 | 24 | /** 25 | * Defines the requirements for classes that get notified when the locale 26 | * is changed. 27 | * 28 | *

A component that implements this interface may dynamically change the 29 | * language of all user visible strings. 30 | * 31 | * @see org.xnap.commons.i18n.I18nManager#setDefaultLocale(Locale) 32 | * @author Steffen Pingel 33 | * @since 0.9 34 | */ 35 | public interface LocaleChangeListener { 36 | 37 | /** 38 | * Invoked when the local has changed. 39 | * 40 | * @param event provides information about the new locale 41 | * @since 0.9 42 | */ 43 | void localeChanged(LocaleChangeEvent event); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | INTRODUCTION 2 | 3 | The Gettext Commons project provides Java classes for 4 | internationalization (i18n) through GNU gettext and Java 5 | ResourceBundles. This makes it possible to use the original text 6 | instead of arbitrary property keys, which is less cumbersome and 7 | makes programs easier to read. Gettext supports the easy extraction 8 | of user visible strings, marks strings as fuzzy when the original 9 | text changes to allow translators to check translations, powerful 10 | plural handling, and build process integration through Maven. 11 | 12 | A tutorial that describes how to use the Gettext Commons is available 13 | at http://code.google.com/p/gettext-commons/wiki/Tutorial . 14 | 15 | 16 | REQUIREMENTS 17 | 18 | * Java 1.3 (or higher) 19 | 20 | 21 | DEVELOPMENT 22 | 23 | Apache Maven 2.0 can be used to build the Gettext Commons. 24 | 25 | 26 | COPYRIGHT 27 | 28 | XNap Commons is distributed under the terms of the GNU Lesser General 29 | Public License, see LICENSE.txt for details. The icons directory 30 | contains images from the KDE project, see LICENSE.icons for terms of 31 | use. 32 | 33 | Copyright (C) 2005 Felix Berger 34 | Copyright (C) 2005 Steffen Pingel 35 | Copyright (C) 2005 Tammo van Lessen 36 | 37 | This library is free software; you can redistribute it and/or 38 | modify it under the terms of the GNU Lesser General Public 39 | License as published by the Free Software Foundation; either 40 | version 2.1 of the License, or (at your option) any later version. 41 | 42 | This library is distributed in the hope that it will be useful, 43 | but WITHOUT ANY WARRANTY; without even the implied warranty of 44 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 45 | Lesser General Public License for more details. 46 | -------------------------------------------------------------------------------- /src/java/org/xnap/commons/i18n/LocaleChangeEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Steffen Pingel 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | package org.xnap.commons.i18n; 21 | 22 | import java.util.EventObject; 23 | import java.util.Locale; 24 | 25 | /** 26 | * Provides information about a locale change. 27 | * 28 | * @author Steffen Pingel 29 | * @since 0.9 30 | */ 31 | public class LocaleChangeEvent extends EventObject { 32 | 33 | private static final long serialVersionUID = 7640942181212009222L; 34 | 35 | private Locale newLocale; 36 | 37 | /** 38 | * Constructs the event. 39 | * @param source the source of the event 40 | * @param newLocale the new locale 41 | * @since 0.9 42 | */ 43 | public LocaleChangeEvent(Object source, Locale newLocale) 44 | { 45 | super(source); 46 | 47 | this.newLocale = newLocale; 48 | } 49 | 50 | /** 51 | * Returns the new locale. 52 | * 53 | * @return the new locale 54 | * @since 0.9 55 | */ 56 | public Locale getNewLocale() 57 | { 58 | return newLocale; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/test/org/xnap/commons/i18n/testpackage/MockResourceBundle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Felix Berger 5 | * Copyright (C) 2005 Steffen Pingel 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | package org.xnap.commons.i18n.testpackage; 22 | 23 | import java.util.Enumeration; 24 | import java.util.Locale; 25 | import java.util.ResourceBundle; 26 | 27 | public class MockResourceBundle extends ResourceBundle 28 | { 29 | 30 | private Locale locale; 31 | 32 | public MockResourceBundle() 33 | { 34 | } 35 | 36 | public Locale getLocale() 37 | { 38 | return locale; 39 | } 40 | 41 | public void setLocale(Locale locale) 42 | { 43 | this.locale = locale; 44 | } 45 | 46 | protected Object handleGetObject(String key) 47 | { 48 | return "value"; 49 | } 50 | 51 | public Enumeration getKeys() 52 | { 53 | return new Enumeration() { 54 | boolean gotten = false; 55 | 56 | public boolean hasMoreElements() 57 | { 58 | return !gotten; 59 | } 60 | 61 | public Object nextElement() 62 | { 63 | gotten = true; 64 | return "value"; 65 | } 66 | }; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /xdocs/maven.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Gettext Commons 6 | 7 | 8 |

9 |

We maintain a repository that can be used for automated 10 | dependency downloading with Maven.

11 |
12 | 13 |
14 |

If you are using Maven 2.x add the following sections to your 16 | pom.xml:

17 | 18 | 19 | ... 20 | <dependencies> 21 | <dependency> 22 | <groupId>org.xnap.commons</groupId> 23 | <artifactId>gettext-commons</artifactId> 24 | <version>0.9.6</version> 25 | </dependency> 26 | </dependencies> 27 | ... 28 | <repositories> 29 | <repository> 30 | <id>gettext-commons-site</id> 31 | <url>http://gettext-commons.googlecode.com/svn/maven-repository/</url> 32 | </repository> 33 | </repositories> 34 | ... 35 | 36 |
37 | 38 |
39 |

If you are using Maven 1.x add the following dependencies to 41 | your project.xml:

42 | 43 | 44 | ... 45 | <dependencies> 46 | <dependency> 47 | <groupId>xnap-commons</groupId> 48 | <artifactId>gettext-commons</artifactId> 49 | <version>0.9.1</version> 50 | <url>http://xnap-commons.sf.net/gettext-commons/</url> 51 | </dependency> 52 | </dependencies> 53 | ... 54 | 55 | 56 |

And add the XNap Commons repository to your 57 | project.properties:

58 | 59 | 60 | maven.repo.remote = http://www.ibiblio.org/maven,http://xnap-commons.sf.net/repository 61 | 62 | 63 |
64 | 65 | 66 | 67 | 72 | -------------------------------------------------------------------------------- /xdocs/changes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Changes 5 | 6 | 7 | 8 | 9 | The project has been separated from the XNap Commons project 10 | and moved to a new location: 11 | http://code.google.com/p/gettext-commons/ 12 | 13 | 14 | A locale parameter has been added to I18nFactory.getI18n() 15 | (#1). 16 | 17 | 18 | A flags parameter has been added to I18nFactory.getI18n() that 19 | allows to fallback to a default resource bundle (#3) or to 20 | disable caching. 21 | 22 | 23 | The resource bundle lookup has been enhanced to also look in 24 | the default package when a class is passed to 25 | I18nFactory.getI18n() that is not in the default package (#2). 26 | 27 | 28 | If a basename is passed to I18nFactory.getI18n() the classpath 29 | is not searched for i18n.properties files anymore (#7) 30 | 31 | 32 | I18nManager.setDefaultLocale() does not invoke 33 | Locale.setDefault() anymore (#6). 34 | 35 | 36 | A NullPointerException has been fixed classes that were loaded 37 | through the boot strap classloader were passed to 38 | I18nFactory.getI18n() (#4). 39 | 40 | 41 | 42 | 43 | Initial release. The project was formerly part of the XNap 44 | Commons and is now distributed separately. The changes 45 | described for this release were made since XNap Commons 46 | 0.9.3 which was the last XNap Commons release that contained 47 | gettext classes. 48 | 49 | 50 | 51 | 52 | 53 | 58 | -------------------------------------------------------------------------------- /src/java/org/xnap/commons/i18n/EmptyResourceBundle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Felix Berger 5 | * Copyright (C) 2005 Steffen Pingel 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | package org.xnap.commons.i18n; 22 | 23 | import java.util.Enumeration; 24 | import java.util.Locale; 25 | import java.util.ResourceBundle; 26 | 27 | /** 28 | * A ResourceBundle that returns the key as a value. 29 | * 30 | * FIXME needs to implement proper plural handling 31 | * FIXME the bundle needs to have a valid locale for proper sourceCodeLocale handling 32 | */ 33 | class EmptyResourceBundle extends ResourceBundle 34 | { 35 | private Locale locale; 36 | 37 | public EmptyResourceBundle(Locale locale) 38 | { 39 | this.locale = locale; 40 | } 41 | 42 | /** 43 | * Returns the key as value. 44 | */ 45 | protected Object handleGetObject(String key) 46 | { 47 | return key; 48 | } 49 | 50 | public Enumeration getKeys() 51 | { 52 | return new EmptyStringEnumeration(); 53 | } 54 | 55 | public Locale getLocale() 56 | { 57 | return locale; 58 | } 59 | 60 | private static class EmptyStringEnumeration implements Enumeration 61 | { 62 | 63 | public boolean hasMoreElements() 64 | { 65 | return false; 66 | } 67 | 68 | public Object nextElement() 69 | { 70 | throw new IllegalStateException("nextElement must not be " + 71 | "called on empty enumeration"); 72 | } 73 | 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /src/test/org/xnap/commons/i18n/I18nCacheTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Steffen Pingel 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | package org.xnap.commons.i18n; 21 | 22 | import java.util.Locale; 23 | 24 | import junit.framework.TestCase; 25 | 26 | import org.xnap.commons.i18n.testpackage.MockResourceBundle; 27 | 28 | /** 29 | * @author Steffen Pingel 30 | */ 31 | public class I18nCacheTest extends TestCase { 32 | 33 | public void testGet() 34 | { 35 | I18nCache cache = new I18nCache(); 36 | I18n i18n = new I18n(new MockResourceBundle()); 37 | cache.put("foo", i18n); 38 | assertNull(cache.get("foo", Locale.getDefault())); 39 | try { 40 | cache.get("foo", null); 41 | fail("Expected NullPointerException"); 42 | } 43 | catch (NullPointerException expected) {} 44 | i18n.setLocale(Locale.ENGLISH); 45 | assertSame(i18n, cache.get("foo", Locale.ENGLISH)); 46 | } 47 | 48 | public void testClear() 49 | { 50 | I18nCache cache = new I18nCache(); 51 | I18n i18n = new I18n(new MockResourceBundle()); 52 | i18n.setLocale(Locale.ENGLISH); 53 | cache.put("foo", i18n); 54 | assertNotNull(cache.get("foo", Locale.ENGLISH)); 55 | cache.clear(); 56 | assertNull(cache.get("foo", Locale.ENGLISH)); 57 | } 58 | 59 | public void testVisit() 60 | { 61 | I18nCache cache = new I18nCache(); 62 | final I18n i18n = new I18n(new MockResourceBundle()); 63 | cache.put("foo", i18n); 64 | final int[] count = new int[1]; 65 | cache.visit(new I18nCache.Visitor() { 66 | 67 | public void visit(I18n visited) 68 | { 69 | assertSame(i18n, visited); 70 | count[0]++; 71 | } 72 | }); 73 | assertEquals(1, count[0]); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2013-03-21 Nicolas Fortin 2 | 3 | * pom.xml: Use maven bundle plugin in order to generate META-INF/MANIFEST.MF OSGi file. 4 | * Gettext Commons 0.9.7 released 5 | 6 | 2008-04-12 Felix Berger 7 | 8 | * src/java/org/xnap/commons/i18n/I18nCache.java: Fixed 9 | synchronization and improved visitor traversal by moving it out of 10 | the synchronized block. 11 | 12 | 2008-04-10 Felix Berger 13 | 14 | * src/java/org/xnap/commons/i18n/I18n.java: Made thread-safe. 15 | 16 | * src/java/org/xnap/commons/i18n/I18nCache.java: Made thread-safe. 17 | 18 | 2006-08-22 Steffen Pingel 19 | 20 | * Gettext Commons 0.9.1 released 21 | 22 | 2007-08-22 Steffen Pingel 23 | 24 | * src/java/org/xnap/commons/i18n/I18nFactory.java: Modified lookup strategy to 25 | only check for property files when no bundle name is provided. 26 | 27 | 2007-08-21 Steffen Pingel 28 | 29 | * src/java/org/xnap/commons/i18n/I18nManager.java: Do not set default locale anymore. 30 | 31 | * src/java/org/xnap/commons/i18n/EmptyResourceBundle.java: Added locale parameter. 32 | 33 | * src/java/org/xnap/commons/i18n/I18n.java: Store only a single bundle and also store locale. 34 | 35 | * src/java/org/xnap/commons/i18n/I18nFactory.java: Added NO_CACHE flag, extracted caching to 36 | I18nCache. 37 | 38 | * src/java/org/xnap/commons/i18n/I18nCache.java: Cache by package and locale. 39 | 40 | 2007-08-06 Steffen Pingel 41 | 42 | * src/java/org/xnap/commons/i18n/I18nFactory.java: Added private 43 | constructor. 44 | 45 | * src/java/org/xnap/commons/i18n/I18nFactory.java: Added getI18n() 46 | method that accepts configuration flags. If I18nFactory.FALLBACK is 47 | passed the lookup will fall-back to a default resource bundle 48 | instead of throwing an exception (#3). Lookup of the basename in 49 | properties can now be omitted when I18nFactory.READ_PROPERTIES 50 | is not passed as a configuration flag. 51 | 52 | 2006-01-05 Steffen Pingel 53 | 54 | * Gettext Commons 0.9 released 55 | 56 | 2006-01-03 Steffen Pingel 57 | 58 | * src/java/org/xnap/commons/i18n/I18nManager.java: Moved 59 | non-factory related methods to this class. 60 | 61 | * src/java/org/xnap/commons/i18n/I18nFactory.java: Implemented 62 | weak listener. 63 | 64 | 2005-12-24 Steffen Pingel 65 | 66 | * src/java/org/xnap/commons/i18n/: Created project: Moved i18n 67 | package from XNap Commons to this project. 68 | -------------------------------------------------------------------------------- /src/java/org/xnap/commons/i18n/I18nCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Felix Berger 5 | * Copyright (C) 2005 Steffen Pingel 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | package org.xnap.commons.i18n; 22 | 23 | import java.util.ArrayList; 24 | import java.util.Collections; 25 | import java.util.HashMap; 26 | import java.util.Iterator; 27 | import java.util.List; 28 | import java.util.Locale; 29 | import java.util.Map; 30 | 31 | /** 32 | * Stores a list of {@link I18n} objects by a String key. 33 | * 34 | * @author Steffen Pingel 35 | */ 36 | class I18nCache { 37 | 38 | /** 39 | * Map>, list is synchronized too. 40 | */ 41 | private final Map i18nByPackage = Collections.synchronizedMap(new HashMap()); 42 | 43 | I18nCache() 44 | { 45 | } 46 | 47 | public void clear() 48 | { 49 | i18nByPackage.clear(); 50 | } 51 | 52 | public I18n get(final String packageName, final Locale locale) 53 | { 54 | if (locale == null) { 55 | throw new NullPointerException("locale is null"); 56 | } 57 | 58 | List list = (List)i18nByPackage.get(packageName); 59 | if (list != null) { 60 | synchronized (list) { 61 | for (Iterator it = list.iterator(); it.hasNext();) { 62 | I18n i18n = (I18n)it.next(); 63 | if (locale.equals(i18n.getLocale())) { 64 | return i18n; 65 | } 66 | } 67 | } 68 | } 69 | return null; 70 | } 71 | 72 | public void put(String packageName, I18n i18n) 73 | { 74 | List list; 75 | synchronized (i18nByPackage) { 76 | list = (List)i18nByPackage.get(packageName); 77 | if (list == null) { 78 | list = Collections.synchronizedList(new ArrayList(2)); 79 | i18nByPackage.put(packageName, list); 80 | } 81 | } 82 | list.add(i18n); 83 | } 84 | 85 | public void visit(final Visitor visitor) 86 | { 87 | List[] lists; 88 | synchronized (i18nByPackage) { 89 | lists = (List[])i18nByPackage.values().toArray(new List[0]); 90 | } 91 | for (int i = 0; i < lists.length; i++) { 92 | List list = lists[i]; 93 | synchronized (list) { 94 | for (Iterator it2 = list.iterator(); it2.hasNext();) { 95 | I18n i18n = (I18n)it2.next(); 96 | visitor.visit(i18n); 97 | } 98 | } 99 | } 100 | } 101 | 102 | public static interface Visitor { 103 | 104 | void visit(I18n i18n); 105 | 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/test/org/xnap/commons/i18n/I18nManagerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Steffen Pingel 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | package org.xnap.commons.i18n; 21 | 22 | import java.util.Locale; 23 | import junit.framework.TestCase; 24 | import org.xnap.commons.i18n.testpackage.MockResourceBundle; 25 | 26 | /** 27 | * @author Felix Berger 28 | */ 29 | public class I18nManagerTest extends TestCase 30 | { 31 | private Locale savedDefault; 32 | 33 | protected void setUp() throws Exception 34 | { 35 | I18nFactory.clearCache(); 36 | 37 | savedDefault = Locale.getDefault(); 38 | Locale.setDefault(Locale.GERMAN); 39 | } 40 | 41 | protected void tearDown() throws Exception 42 | { 43 | Locale.setDefault(savedDefault); 44 | } 45 | 46 | public void testSetLocale() 47 | { 48 | I18n i18n = I18nFactory.getI18n(MockResourceBundle.class); 49 | assertEquals(Locale.GERMAN, i18n.getResources().getLocale()); 50 | I18nManager.getInstance().setDefaultLocale(Locale.FRENCH); 51 | assertEquals(Locale.FRENCH, i18n.getResources().getLocale()); 52 | I18nManager.getInstance().setDefaultLocale(Locale.GERMAN); 53 | assertEquals(Locale.GERMAN, i18n.getResources().getLocale()); 54 | } 55 | 56 | public void testListener() 57 | { 58 | MyLocaleChangeListener listener = new MyLocaleChangeListener(); 59 | I18nManager.getInstance().addLocaleChangeListener(listener ); 60 | assertEquals(0, listener.count); 61 | I18nManager.getInstance().setDefaultLocale(Locale.GERMAN); 62 | assertEquals(1, listener.count); 63 | assertEquals(Locale.GERMAN, listener.newLocale); 64 | I18nManager.getInstance().removeLocaleChangeListener(listener); 65 | I18nManager.getInstance().setDefaultLocale(Locale.FRENCH); 66 | assertEquals(1, listener.count); 67 | assertEquals(Locale.GERMAN, listener.newLocale); 68 | } 69 | 70 | public void testWeakListener() 71 | { 72 | int listenerCount = I18nManager.getInstance().localeChangeListeners.size(); 73 | MyLocaleChangeListener listener = new MyLocaleChangeListener(); 74 | I18nManager.getInstance().addWeakLocaleChangeListener(listener ); 75 | assertEquals(0, listener.count); 76 | assertEquals(listenerCount + 1, I18nManager.getInstance().localeChangeListeners.size()); 77 | I18nManager.getInstance().setDefaultLocale(Locale.GERMAN); 78 | assertEquals(1, listener.count); 79 | listener = null; 80 | System.gc(); 81 | I18nManager.getInstance().setDefaultLocale(Locale.FRENCH); 82 | assertEquals(listenerCount, I18nManager.getInstance().localeChangeListeners.size()); 83 | } 84 | 85 | private class MyLocaleChangeListener implements LocaleChangeListener { 86 | int count; 87 | Locale newLocale; 88 | public void localeChanged(LocaleChangeEvent event) 89 | { 90 | count++; 91 | newLocale = event.getNewLocale(); 92 | } 93 | }; 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/examples/I18nExample.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Felix Berger 5 | * Copyright (C) 2005 Steffen Pingel 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | import java.util.Locale; 22 | import org.xnap.commons.i18n.I18n; 23 | import org.xnap.commons.i18n.I18nFactory; 24 | 25 | /** 26 | * This example class illustrates how the methods provided by {@link i18n} 27 | * can be used to localize text messages. 28 | * 29 | * Nota bene: Contrary to this example changing the resources during 30 | * run-time is usually not a good idea, since most strings are saved in the 31 | * swing components and not reread from resource bundles. 32 | * 33 | * @author Felix Berger 34 | */ 35 | public class I18nExample 36 | { 37 | public static void main(String[] args) 38 | { 39 | I18n i18n = I18nFactory.getI18n(I18nExample.class, "Messages"); 40 | /* 41 | * We do two runs, the first with the orginal locale the second one 42 | * with the German locale, to see which messages are translated and 43 | * how. 44 | */ 45 | for (int i = 0; i < 2; i++) { 46 | 47 | if (i == 0) { 48 | print("First run"); 49 | 50 | } 51 | else { 52 | print("Second run"); 53 | i18n.setLocale(Locale.GERMAN); 54 | } 55 | 56 | /* 57 | * This is the method you will be using most of the time. 58 | */ 59 | print(i18n.tr("This text is marked for translation and is translated")); 60 | 61 | /* 62 | * This method marks the text for translation, but doesn't 63 | * translate. This can be used for keys which should be stored 64 | * untranslated but should be translated in the user interface. 65 | */ 66 | String mark = i18n.marktr("This text is marked for translation but not translated"); 67 | 68 | /* 69 | * See in the second run, it's never translated. 70 | */ 71 | print(mark); 72 | 73 | /* 74 | * Now you can use the text in a variable and it is correctly 75 | * translated. 76 | */ 77 | print(i18n.tr(mark)); 78 | 79 | /* 80 | * A convenience wrapper for MessageFormat.format(String, Object[]). 81 | */ 82 | print(i18n.tr("Four: {0}", new Integer(4))); 83 | 84 | /* 85 | * This method disambiguates a word which has to be translated 86 | * differently depending on how it is used. In our example the 87 | * word "chat" is translated differently to German when it is 88 | * used as a noun and as a verb. 89 | */ 90 | print(i18n.trc("chat (verb)", "chat")); 91 | 92 | print(i18n.trc("chat (noun)", "chat")); 93 | 94 | /* 95 | * I18n.trn handles plurals. The third parameter contains the number 96 | * of objects to decide which plural form to use. 97 | */ 98 | print(i18n.trn("{0} file is open", "{0} files are open", 1, new Integer(1))); 99 | 100 | print(i18n.trn("{0} file is open", "{0} files are open", 2, new Integer(2))); 101 | } 102 | } 103 | 104 | private static void print(String text) 105 | { 106 | System.out.println(text); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/test/org/xnap/commons/i18n/I18nFactoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Steffen Pingel 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | package org.xnap.commons.i18n; 21 | 22 | import java.util.Locale; 23 | 24 | import junit.framework.TestCase; 25 | 26 | import org.xnap.commons.i18n.testpackage.MockResourceBundle; 27 | import org.xnap.commons.i18n.testpackage.noresources.HasNoOwnResources; 28 | import org.xnap.commons.i18n.testpackage.resources.HasItsOwnResources; 29 | 30 | /** 31 | * @author Felix Berger 32 | */ 33 | public class I18nFactoryTest extends TestCase { 34 | 35 | private static Locale[] LOCALES = { Locale.GERMAN, Locale.FRENCH }; 36 | 37 | private static String[] VALUES = { "Wert", "valeur" }; 38 | 39 | private Locale savedDefault; 40 | 41 | private String packageName; 42 | 43 | protected void setUp() throws Exception 44 | { 45 | packageName = MockResourceBundle.class.getName(); 46 | packageName = packageName.substring(0, packageName.lastIndexOf('.')); 47 | 48 | savedDefault = Locale.getDefault(); 49 | Locale.setDefault(Locale.GERMAN); 50 | 51 | I18nFactory.clearCache(); 52 | } 53 | 54 | protected void tearDown() throws Exception 55 | { 56 | Locale.setDefault(savedDefault); 57 | } 58 | 59 | public void testFindByBaseName() 60 | { 61 | for (int i = 0; i < LOCALES.length; i++) { 62 | Locale.setDefault(LOCALES[i]); 63 | I18n i18n = I18nFactory.findByBaseName(packageName + ".TestMessages", Locale.getDefault(), 64 | MockResourceBundle.class.getClassLoader(), I18nFactory.DEFAULT); 65 | assertEquals(LOCALES[i], i18n.getResources().getLocale()); 66 | assertEquals(VALUES[i], i18n.getResources().getString("value")); 67 | assertEquals(VALUES[i], i18n.tr("value")); 68 | } 69 | 70 | // same for mock up 71 | I18n i18n = I18nFactory.findByBaseName(packageName + ".MockResourceBundle", Locale.getDefault(), getClass() 72 | .getClassLoader(), I18nFactory.DEFAULT); 73 | assertEquals(MockResourceBundle.class, i18n.getResources().getClass()); 74 | assertEquals("value", i18n.getResources().getString("value")); 75 | assertEquals("value", i18n.tr("value")); 76 | } 77 | 78 | public void testReadFromPropertiesFile() 79 | { 80 | String baseName = I18nFactory.readFromPropertiesFile(packageName, Locale.getDefault(), getClass() 81 | .getClassLoader()); 82 | assertEquals("org.xnap.commons.i18n.testpackage.TestMessages", baseName); 83 | } 84 | 85 | public void testGetI18n() 86 | { 87 | I18n i18n = I18nFactory.getI18n(MockResourceBundle.class); 88 | assertNotSame(MockResourceBundle.class, i18n.getResources().getClass()); 89 | i18n = I18nFactory.getI18n(MockResourceBundle.class, "MockResourceBundle"); 90 | assertSame(MockResourceBundle.class, i18n.getResources().getClass()); 91 | } 92 | 93 | public void testGetI18nFromDefaultPackage() 94 | { 95 | I18n i18n = I18nFactory.getI18n(MockResourceBundle.class, "DefaultMessages", Locale.ENGLISH); 96 | assertEquals("DefaultBundle", i18n.tr("source")); 97 | } 98 | 99 | public void testOwnResources() 100 | { 101 | I18n i18n = I18nFactory.getI18n(HasItsOwnResources.class); 102 | i18n.setLocale(Locale.GERMAN); 103 | assertEquals("yes", i18n.tr("own")); 104 | } 105 | 106 | public void testNoOwnResources() 107 | { 108 | I18n i18n = I18nFactory.getI18n(HasNoOwnResources.class); 109 | i18n.setLocale(Locale.GERMAN); 110 | assertEquals(Locale.GERMAN, i18n.getResources().getLocale()); 111 | assertEquals("Wert", i18n.tr("value")); 112 | i18n.setLocale(Locale.FRENCH); 113 | assertEquals(Locale.FRENCH, i18n.getResources().getLocale()); 114 | assertEquals("valeur", i18n.tr("value")); 115 | } 116 | 117 | public void testGetI18nFallback() 118 | { 119 | I18n i18n = I18nFactory.getI18n(HasNoOwnResources.class, "NonExistant", Locale.getDefault(), 120 | I18nFactory.FALLBACK); 121 | assertTrue(i18n.getResources() instanceof EmptyResourceBundle); 122 | } 123 | 124 | public void testSetResources() 125 | { 126 | try { 127 | I18n i18n = I18nFactory.getI18n(MockResourceBundle.class); 128 | i18n.setResources(null); 129 | fail("NullPointerException expected"); 130 | } 131 | catch (NullPointerException npe) {} 132 | I18n i18n = I18nFactory.getI18n(MockResourceBundle.class); 133 | String baseName = MockResourceBundle.class.getName(); 134 | i18n.setResources(baseName, Locale.GERMAN, MockResourceBundle.class.getClassLoader()); 135 | assertEquals(MockResourceBundle.class, i18n.getResources().getClass()); 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /po/keys.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2009-02-10 19:33-0500\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=CHARSET\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" 19 | 20 | #: src/test/org/xnap/commons/i18n/I18nTest.java:59 21 | msgid "house" 22 | msgstr "" 23 | 24 | #: src/test/org/xnap/commons/i18n/I18nTest.java:60 25 | msgid "mouse" 26 | msgstr "" 27 | 28 | #: src/test/org/xnap/commons/i18n/I18nTest.java:61 29 | msgid "Automatic" 30 | msgstr "" 31 | 32 | #: src/test/org/xnap/commons/i18n/I18nTest.java:62 33 | msgid "Completion" 34 | msgstr "" 35 | 36 | #: src/test/org/xnap/commons/i18n/I18nTest.java:67 37 | #, java-format 38 | msgid "House Nr. {0} " 39 | msgstr "" 40 | 41 | #: src/test/org/xnap/commons/i18n/I18nTest.java:68 42 | #, java-format 43 | msgid "{0}" 44 | msgstr "" 45 | 46 | #: src/test/org/xnap/commons/i18n/I18nTest.java:73 47 | #: src/test/org/xnap/commons/i18n/I18nTest.java:169 48 | #, java-format 49 | msgid "Foo {1} {0}" 50 | msgid_plural "Foos" 51 | msgstr[0] "" 52 | msgstr[1] "" 53 | 54 | #: src/test/org/xnap/commons/i18n/I18nTest.java:74 55 | #: src/test/org/xnap/commons/i18n/I18nTest.java:170 56 | #, java-format 57 | msgid "Foo {0} {1}" 58 | msgid_plural "Foos" 59 | msgstr[0] "" 60 | msgstr[1] "" 61 | 62 | #: src/test/org/xnap/commons/i18n/I18nTest.java:79 63 | #: src/test/org/xnap/commons/i18n/I18nTest.java:175 64 | #, java-format 65 | msgid "Foo {1} {2} {0}" 66 | msgid_plural "Foos" 67 | msgstr[0] "" 68 | msgstr[1] "" 69 | 70 | #: src/test/org/xnap/commons/i18n/I18nTest.java:80 71 | #: src/test/org/xnap/commons/i18n/I18nTest.java:176 72 | #, java-format 73 | msgid "Foo {0} {1} {2}" 74 | msgid_plural "Foos" 75 | msgstr[0] "" 76 | msgstr[1] "" 77 | 78 | #: src/test/org/xnap/commons/i18n/I18nTest.java:85 79 | #: src/test/org/xnap/commons/i18n/I18nTest.java:182 80 | #, java-format 81 | msgid "Foo {1} {2} {3} {0}" 82 | msgid_plural "Foos" 83 | msgstr[0] "" 84 | msgstr[1] "" 85 | 86 | #: src/test/org/xnap/commons/i18n/I18nTest.java:86 87 | #: src/test/org/xnap/commons/i18n/I18nTest.java:184 88 | #, java-format 89 | msgid "Foo {0} {1} {2} {3}" 90 | msgid_plural "Foos" 91 | msgstr[0] "" 92 | msgstr[1] "" 93 | 94 | #: src/test/org/xnap/commons/i18n/I18nTest.java:91 95 | #: src/test/org/xnap/commons/i18n/I18nTest.java:151 96 | #: src/test/org/xnap/commons/i18n/I18nTest.java:152 97 | #: src/test/org/xnap/commons/i18n/I18nTest.java:153 98 | #, java-format 99 | msgid "Foo" 100 | msgid_plural "{0} Bars" 101 | msgstr[0] "" 102 | msgstr[1] "" 103 | 104 | #: src/test/org/xnap/commons/i18n/I18nTest.java:96 105 | #: src/test/org/xnap/commons/i18n/I18nTest.java:98 106 | msgctxt "noun" 107 | msgid "chat" 108 | msgstr "" 109 | 110 | #: src/test/org/xnap/commons/i18n/I18nTest.java:97 111 | #: src/test/org/xnap/commons/i18n/I18nTest.java:99 112 | #: src/test/org/xnap/commons/i18n/I18nTest.java:138 113 | #: src/test/org/xnap/commons/i18n/I18nTest.java:140 114 | msgctxt "verb" 115 | msgid "chat" 116 | msgstr "" 117 | 118 | #: src/test/org/xnap/commons/i18n/I18nTest.java:158 119 | #: src/test/org/xnap/commons/i18n/I18nTest.java:159 120 | #, java-format 121 | msgid "File" 122 | msgid_plural "{0} Files" 123 | msgstr[0] "" 124 | msgstr[1] "" 125 | 126 | #: src/test/org/xnap/commons/i18n/I18nTest.java:164 127 | #, java-format 128 | msgid "Foo {0} " 129 | msgid_plural "Foos {0}" 130 | msgstr[0] "" 131 | msgstr[1] "" 132 | 133 | #: src/test/org/xnap/commons/i18n/I18nTest.java:195 134 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:67 135 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:75 136 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:111 137 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:114 138 | msgid "value" 139 | msgstr "" 140 | 141 | #: src/test/org/xnap/commons/i18n/I18nTest.java:199 142 | msgctxt "dont translate to German" 143 | msgid "baobab" 144 | msgstr "" 145 | 146 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:96 147 | msgid "source" 148 | msgstr "" 149 | 150 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:103 151 | msgid "own" 152 | msgstr "" 153 | 154 | #: src/examples/I18nExample.java:39 155 | msgid "This text is marked for translation and is translated" 156 | msgstr "" 157 | 158 | #: src/examples/I18nExample.java:46 159 | msgid "This text is marked for translation but not translated" 160 | msgstr "" 161 | 162 | #: src/examples/I18nExample.java:62 163 | #, java-format 164 | msgid "Four: {0}" 165 | msgstr "" 166 | 167 | #: src/examples/I18nExample.java:70 168 | msgctxt "chat (verb)" 169 | msgid "chat" 170 | msgstr "" 171 | 172 | #: src/examples/I18nExample.java:72 173 | msgctxt "chat (noun)" 174 | msgid "chat" 175 | msgstr "" 176 | 177 | #: src/examples/I18nExample.java:78 src/examples/I18nExample.java:80 178 | #, java-format 179 | msgid "{0} file is open" 180 | msgid_plural "{0} files are open" 181 | msgstr[0] "" 182 | msgstr[1] "" 183 | -------------------------------------------------------------------------------- /po/de.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR Free Software Foundation, Inc. 3 | # FIRST AUTHOR , YEAR. 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: de\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "POT-Creation-Date: 2009-02-10 19:33-0500\n" 10 | "PO-Revision-Date: 2009-02-10 19:36-0500\n" 11 | "Last-Translator: Steffen Pingel \n" 12 | "Language-Team: \n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: 8bit\n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: KBabel 1.10.2\n" 18 | 19 | #: src/test/org/xnap/commons/i18n/I18nTest.java:59 20 | msgid "house" 21 | msgstr "Haus" 22 | 23 | #: src/test/org/xnap/commons/i18n/I18nTest.java:60 24 | msgid "mouse" 25 | msgstr "Maus" 26 | 27 | #: src/test/org/xnap/commons/i18n/I18nTest.java:61 28 | msgid "Automatic" 29 | msgstr "Automatisch" 30 | 31 | #: src/test/org/xnap/commons/i18n/I18nTest.java:62 32 | msgid "Completion" 33 | msgstr "Ergänzung" 34 | 35 | #: src/test/org/xnap/commons/i18n/I18nTest.java:67 36 | #, java-format 37 | msgid "House Nr. {0} " 38 | msgstr "Haus Nr. {0}" 39 | 40 | #: src/test/org/xnap/commons/i18n/I18nTest.java:68 41 | #, java-format 42 | msgid "{0}" 43 | msgstr "{0}" 44 | 45 | #: src/test/org/xnap/commons/i18n/I18nTest.java:73 46 | #: src/test/org/xnap/commons/i18n/I18nTest.java:169 47 | #, java-format 48 | msgid "Foo {1} {0}" 49 | msgid_plural "Foos" 50 | msgstr[0] "Foo {1} {0}" 51 | msgstr[1] "Foos" 52 | 53 | #: src/test/org/xnap/commons/i18n/I18nTest.java:74 54 | #: src/test/org/xnap/commons/i18n/I18nTest.java:170 55 | #, java-format 56 | msgid "Foo {0} {1}" 57 | msgid_plural "Foos" 58 | msgstr[0] "" 59 | msgstr[1] "" 60 | 61 | #: src/test/org/xnap/commons/i18n/I18nTest.java:79 62 | #: src/test/org/xnap/commons/i18n/I18nTest.java:175 63 | #, java-format 64 | msgid "Foo {1} {2} {0}" 65 | msgid_plural "Foos" 66 | msgstr[0] "" 67 | msgstr[1] "" 68 | 69 | #: src/test/org/xnap/commons/i18n/I18nTest.java:80 70 | #: src/test/org/xnap/commons/i18n/I18nTest.java:176 71 | #, java-format 72 | msgid "Foo {0} {1} {2}" 73 | msgid_plural "Foos" 74 | msgstr[0] "" 75 | msgstr[1] "" 76 | 77 | #: src/test/org/xnap/commons/i18n/I18nTest.java:85 78 | #: src/test/org/xnap/commons/i18n/I18nTest.java:182 79 | #, java-format 80 | msgid "Foo {1} {2} {3} {0}" 81 | msgid_plural "Foos" 82 | msgstr[0] "" 83 | msgstr[1] "" 84 | 85 | #: src/test/org/xnap/commons/i18n/I18nTest.java:86 86 | #: src/test/org/xnap/commons/i18n/I18nTest.java:184 87 | #, java-format 88 | msgid "Foo {0} {1} {2} {3}" 89 | msgid_plural "Foos" 90 | msgstr[0] "" 91 | msgstr[1] "" 92 | 93 | #: src/test/org/xnap/commons/i18n/I18nTest.java:91 94 | #: src/test/org/xnap/commons/i18n/I18nTest.java:151 95 | #: src/test/org/xnap/commons/i18n/I18nTest.java:152 96 | #: src/test/org/xnap/commons/i18n/I18nTest.java:153 97 | #, java-format 98 | msgid "Foo" 99 | msgid_plural "{0} Bars" 100 | msgstr[0] "Foo" 101 | msgstr[1] "{0} Bars" 102 | 103 | #: src/test/org/xnap/commons/i18n/I18nTest.java:96 104 | #: src/test/org/xnap/commons/i18n/I18nTest.java:98 105 | msgctxt "noun" 106 | msgid "chat" 107 | msgstr "Chat" 108 | 109 | #: src/test/org/xnap/commons/i18n/I18nTest.java:97 110 | #: src/test/org/xnap/commons/i18n/I18nTest.java:99 111 | #: src/test/org/xnap/commons/i18n/I18nTest.java:138 112 | #: src/test/org/xnap/commons/i18n/I18nTest.java:140 113 | msgctxt "verb" 114 | msgid "chat" 115 | msgstr "Chatten" 116 | 117 | #: src/test/org/xnap/commons/i18n/I18nTest.java:158 118 | #: src/test/org/xnap/commons/i18n/I18nTest.java:159 119 | #, java-format 120 | msgid "File" 121 | msgid_plural "{0} Files" 122 | msgstr[0] "Datei" 123 | msgstr[1] "{0} Dateien" 124 | 125 | #: src/test/org/xnap/commons/i18n/I18nTest.java:164 126 | #, java-format 127 | msgid "Foo {0} " 128 | msgid_plural "Foos {0}" 129 | msgstr[0] "" 130 | msgstr[1] "" 131 | 132 | #: src/test/org/xnap/commons/i18n/I18nTest.java:195 133 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:67 134 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:75 135 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:111 136 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:114 137 | msgid "value" 138 | msgstr "Wert" 139 | 140 | #: src/test/org/xnap/commons/i18n/I18nTest.java:199 141 | msgctxt "dont translate to German" 142 | msgid "baobab" 143 | msgstr "" 144 | 145 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:96 146 | msgid "source" 147 | msgstr "" 148 | 149 | #: src/test/org/xnap/commons/i18n/I18nFactoryTest.java:103 150 | msgid "own" 151 | msgstr "" 152 | 153 | #: src/examples/I18nExample.java:39 154 | msgid "This text is marked for translation and is translated" 155 | msgstr "" 156 | 157 | #: src/examples/I18nExample.java:46 158 | msgid "This text is marked for translation but not translated" 159 | msgstr "" 160 | 161 | #: src/examples/I18nExample.java:62 162 | #, java-format 163 | msgid "Four: {0}" 164 | msgstr "" 165 | 166 | #: src/examples/I18nExample.java:70 167 | msgctxt "chat (verb)" 168 | msgid "chat" 169 | msgstr "" 170 | 171 | #: src/examples/I18nExample.java:72 172 | msgctxt "chat (noun)" 173 | msgid "chat" 174 | msgstr "" 175 | 176 | #: src/examples/I18nExample.java:78 src/examples/I18nExample.java:80 177 | #, java-format 178 | msgid "{0} file is open" 179 | msgid_plural "{0} files are open" 180 | msgstr[0] "" 181 | msgstr[1] "" 182 | 183 | #~ msgid "Foo (context)" 184 | #~ msgstr "KontextFoo" 185 | -------------------------------------------------------------------------------- /src/java/org/xnap/commons/i18n/I18nManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Felix Berger 5 | * Copyright (C) 2005 Steffen Pingel 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | package org.xnap.commons.i18n; 22 | 23 | import java.lang.ref.WeakReference; 24 | import java.util.ArrayList; 25 | import java.util.Collections; 26 | import java.util.Iterator; 27 | import java.util.List; 28 | import java.util.Locale; 29 | 30 | /** 31 | * Manager class that maintains a set of {@link org.xnap.commons.i18n.I18n} 32 | * objects and {@link org.xnap.commons.i18n.LocaleChangeListener} objects. 33 | *

34 | * The locale of all managed I18n objects can be changed by 35 | * invoking {@link org.xnap.commons.i18n.I18nManager#setDefaultLocale(Locale)}. 36 | * 37 | * @author Felix Berger 38 | * @author Steffen Pingel 39 | * @since 0.9 40 | */ 41 | public class I18nManager { 42 | 43 | private static I18nManager instance = new I18nManager(); 44 | 45 | /** List of managed {@link I18n} objects. */ 46 | List i18ns = Collections.synchronizedList(new ArrayList()); 47 | 48 | /** List of managed {@link LocaleChangeListener} objects. */ 49 | List localeChangeListeners = new ArrayList(); 50 | 51 | private I18nManager() 52 | { 53 | } 54 | 55 | /** 56 | * Returns the global I18Manger singleton. 57 | * 58 | * @return the I18Manger instance 59 | * @since 0.9 60 | */ 61 | public static I18nManager getInstance() 62 | { 63 | return instance; 64 | } 65 | 66 | /** 67 | * Adds i18n to the list of managed I18n 68 | * objects. 69 | * 70 | * @param i18n 71 | * the I18n instance 72 | * @see #setDefaultLocale(Locale) 73 | * @see #remove(I18n) 74 | * @since 0.9 75 | */ 76 | public void add(I18n i18n) 77 | { 78 | i18ns.add(i18n); 79 | } 80 | 81 | /** 82 | * Sets the locale for all I18n instances that were instantiated through the 83 | * factory. 84 | *

85 | * Use this method to globally change the locale for all I18n based 86 | * translations. 87 | *

88 | * NOTE: This only works if the objects that display messages do not cache 89 | * translated messages. 90 | *

91 | * 92 | * @param locale 93 | * the new default locale 94 | * @see I18n#setLocale(Locale) 95 | * @since 0.9 96 | */ 97 | public void setDefaultLocale(Locale locale) 98 | { 99 | synchronized (i18ns) { 100 | for (Iterator it = i18ns.iterator(); it.hasNext();) { 101 | I18n i18n = (I18n)it.next(); 102 | i18n.setLocale(locale); 103 | } 104 | } 105 | fireLocaleChangedEvent(locale); 106 | } 107 | 108 | /** 109 | * Adds a listener that is notified when the default locale has been 110 | * changed. 111 | * 112 | * @param listener 113 | * the listener 114 | * @see #setDefaultLocale(Locale) 115 | * @since 0.9 116 | */ 117 | public void addLocaleChangeListener(LocaleChangeListener listener) 118 | { 119 | synchronized (localeChangeListeners) { 120 | localeChangeListeners.add(listener); 121 | } 122 | } 123 | 124 | /** 125 | * Adds a listener that is notified when the default locale has been changed 126 | * using a {@link WeakReference}. The listener is removed when it has been 127 | * cleaned up by the garbage collection. 128 | *

129 | * This is useful for temporary objects that may have an indeterminate 130 | * lifetime such as dialogs. 131 | * 132 | * @param listener 133 | * the listener 134 | * @see #setDefaultLocale(Locale) 135 | * @since 0.9 136 | */ 137 | public void addWeakLocaleChangeListener(LocaleChangeListener listener) 138 | { 139 | synchronized (localeChangeListeners) { 140 | localeChangeListeners.add(new WeakLocaleChangeListener(listener)); 141 | } 142 | } 143 | 144 | /** 145 | * Removes i18n from the list of managed I18n 146 | * objects. 147 | * 148 | * @param i18n 149 | * the I18n instance 150 | * @see #add(I18n) 151 | * @since 0.9 152 | */ 153 | public void remove(I18n i18n) 154 | { 155 | i18ns.remove(i18n); 156 | } 157 | 158 | /** 159 | * Removes listener from the list of objects that are 160 | * notified when the locale has changed. 161 | * 162 | * @param listener 163 | * the listener 164 | * @since 0.9 165 | */ 166 | public void removeLocaleChangeListener(LocaleChangeListener listener) 167 | { 168 | synchronized (localeChangeListeners) { 169 | localeChangeListeners.remove(listener); 170 | } 171 | } 172 | 173 | /** 174 | * Notifies listeners of a locale change. 175 | * 176 | * @param newLocale 177 | * new locale 178 | * @since 0.9 179 | */ 180 | protected void fireLocaleChangedEvent(Locale newLocale) 181 | { 182 | LocaleChangeListener[] listeners; 183 | synchronized (localeChangeListeners) { 184 | listeners = (LocaleChangeListener[])localeChangeListeners.toArray(new LocaleChangeListener[0]); 185 | } 186 | if (listeners.length > 0) { 187 | LocaleChangeEvent event = new LocaleChangeEvent(I18nFactory.class, newLocale); 188 | for (int i = listeners.length - 1; i >= 0; i--) { 189 | listeners[i].localeChanged(event); 190 | } 191 | } 192 | } 193 | 194 | private static class WeakLocaleChangeListener implements LocaleChangeListener { 195 | 196 | private WeakReference reference; 197 | 198 | public WeakLocaleChangeListener(LocaleChangeListener listener) 199 | { 200 | reference = new WeakReference(listener); 201 | } 202 | 203 | public void localeChanged(LocaleChangeEvent event) 204 | { 205 | Object listener = reference.get(); 206 | if (listener != null) { 207 | ((LocaleChangeListener)listener).localeChanged(event); 208 | } 209 | else { 210 | I18nManager.getInstance().removeLocaleChangeListener(this); 211 | } 212 | } 213 | 214 | } 215 | 216 | } 217 | -------------------------------------------------------------------------------- /src/test/org/xnap/commons/i18n/I18nTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Steffen Pingel 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | */ 20 | package org.xnap.commons.i18n; 21 | 22 | import java.util.Locale; 23 | import java.util.MissingResourceException; 24 | 25 | import junit.framework.TestCase; 26 | 27 | import org.xnap.commons.i18n.testpackage.MockResourceBundle; 28 | 29 | /** 30 | * @author Steffen Pingel 31 | * @author Felix Berger 32 | */ 33 | public class I18nTest extends TestCase { 34 | 35 | public static final String BASENAME = "org.xnap.commons.i18n.Messages"; 36 | 37 | private I18n i18nDE; 38 | 39 | private I18n i18nEN; 40 | 41 | protected void setUp() throws Exception 42 | { 43 | try { 44 | i18nDE = new I18n(BASENAME, Locale.GERMAN, getClass().getClassLoader()); 45 | } 46 | catch (MissingResourceException e) { 47 | throw new RuntimeException( 48 | "Please make sure you run 'mvn org.xnap.commons:maven-gettext-plugin:dist' before executing tests"); 49 | } 50 | i18nEN = new I18n(BASENAME, Locale.ENGLISH, getClass().getClassLoader()); 51 | } 52 | 53 | protected void tearDown() throws Exception 54 | { 55 | } 56 | 57 | public void testTr() 58 | { 59 | assertEquals("Haus", i18nDE.tr("house")); 60 | assertEquals("Maus", i18nDE.tr("mouse")); 61 | assertEquals("Automatisch", i18nDE.tr("Automatic")); 62 | assertEquals("Erg\u00e4nzung", i18nDE.tr("Completion")); 63 | } 64 | 65 | public void testTr1() 66 | { 67 | assertEquals("House Nr. 2 ", i18nEN.tr("House Nr. {0} ", new Integer(2))); 68 | assertEquals("0", i18nEN.tr("{0}", "0")); 69 | } 70 | 71 | public void testTr2() 72 | { 73 | assertEquals("Foo bar foo", i18nEN.tr("Foo {1} {0}", "foo", "bar")); 74 | assertEquals("Foo foo bar", i18nEN.tr("Foo {0} {1}", "foo", "bar")); 75 | } 76 | 77 | public void testTr3() 78 | { 79 | assertEquals("Foo bar baz foo", i18nEN.tr("Foo {1} {2} {0}", "foo", "bar", "baz")); 80 | assertEquals("Foo foo bar baz", i18nEN.tr("Foo {0} {1} {2}", "foo", "bar", "baz")); 81 | } 82 | 83 | public void testTr4() 84 | { 85 | assertEquals("Foo bar baz boing foo", i18nEN.tr("Foo {1} {2} {3} {0}", "foo", "bar", "baz", "boing")); 86 | assertEquals("Foo foo bar baz boing", i18nEN.tr("Foo {0} {1} {2} {3}", "foo", "bar", "baz", "boing")); 87 | } 88 | 89 | public void testMarktr() 90 | { 91 | assertEquals(I18n.marktr("Foo"), "Foo"); 92 | } 93 | 94 | public void testTrc() 95 | { 96 | assertEquals("chat", i18nEN.trc("noun", "chat")); 97 | assertEquals("chat", i18nEN.trc("verb", "chat")); 98 | assertEquals("Chat", i18nDE.trc("noun", "chat")); 99 | assertEquals("Chatten", i18nDE.trc("verb", "chat")); 100 | } 101 | 102 | public void testSetLocale() 103 | { 104 | I18n i18n = new I18n(new MockResourceBundle()); 105 | assertFalse(i18n.setLocale(Locale.FRENCH)); 106 | i18n.setResources(MockResourceBundle.class.getName(), Locale.GERMAN, MockResourceBundle.class.getClassLoader()); 107 | assertTrue(i18n.setLocale(Locale.FRENCH)); 108 | } 109 | 110 | public void testSetResources() 111 | { 112 | try { 113 | new I18n(null); 114 | fail("NullPointerException expected"); 115 | } 116 | catch (NullPointerException npe) {} 117 | String baseName = MockResourceBundle.class.getName(); 118 | try { 119 | i18nDE.setResources(null, Locale.GERMAN, MockResourceBundle.class.getClassLoader()); 120 | fail("NullPointerException expected"); 121 | } 122 | catch (NullPointerException npe) {} 123 | try { 124 | i18nDE.setResources(baseName, null, MockResourceBundle.class.getClassLoader()); 125 | fail("NullPointerException expected"); 126 | } 127 | catch (NullPointerException npe) {} 128 | try { 129 | i18nDE.setResources(baseName, Locale.GERMAN, null); 130 | fail("NullPointerException expected"); 131 | } 132 | catch (NullPointerException npe) {} 133 | } 134 | 135 | public void testSetSourceCodeLocale() 136 | { 137 | i18nDE.setSourceCodeLocale(Locale.GERMAN); 138 | assertEquals("chat", i18nDE.trc("verb", "chat")); 139 | i18nDE.setSourceCodeLocale(Locale.ENGLISH); 140 | assertEquals("Chatten", i18nDE.trc("verb", "chat")); 141 | 142 | try { 143 | i18nDE.setSourceCodeLocale(null); 144 | fail("null pointer exception expected"); 145 | } 146 | catch (NullPointerException npe) {} 147 | } 148 | 149 | public void testTrnEN() 150 | { 151 | assertEquals("Foo", i18nEN.trn("Foo", "{0} Bars", 1)); 152 | assertEquals("{0} Bars", i18nEN.trn("Foo", "{0} Bars", 2)); 153 | assertEquals("2 Bars", i18nEN.trn("Foo", "{0} Bars", 2, new Integer(2))); 154 | } 155 | 156 | public void testTrnDE() 157 | { 158 | assertEquals("Datei", i18nDE.trn("File", "{0} Files", 1, new Integer(1))); 159 | assertEquals("2 Dateien", i18nDE.trn("File", "{0} Files", 2, new Integer(2))); 160 | } 161 | 162 | public void testTrn1() 163 | { 164 | assertEquals("Foo foo ", i18nEN.trn("Foo {0} ", "Foos {0}", 1, "foo")); 165 | } 166 | 167 | public void testTrn2() 168 | { 169 | assertEquals("Foo bar foo", i18nEN.trn("Foo {1} {0}", "Foos", 1, "foo", "bar")); 170 | assertEquals("Foo foo bar", i18nEN.trn("Foo {0} {1}", "Foos", 1, "foo", "bar")); 171 | } 172 | 173 | public void testTrn3() 174 | { 175 | assertEquals("Foo bar baz foo", i18nEN.trn("Foo {1} {2} {0}", "Foos", 1, "foo", "bar", "baz")); 176 | assertEquals("Foo foo bar baz", i18nEN.trn("Foo {0} {1} {2}", "Foos", 1, "foo", "bar", "baz")); 177 | } 178 | 179 | public void testTrn4() 180 | { 181 | assertEquals("Foo bar baz boing foo", i18nEN 182 | .trn("Foo {1} {2} {3} {0}", "Foos", 1, "foo", "bar", "baz", "boing")); 183 | assertEquals("Foo foo bar baz boing", i18nEN 184 | .trn("Foo {0} {1} {2} {3}", "Foos", 1, "foo", "bar", "baz", "boing")); 185 | } 186 | 187 | public void testSetEmptyResources() 188 | { 189 | // this should load the empty resource bundle 190 | // we have to set the default to italian too, so 191 | // ResourceBundle.getBundle(...) doesn't fall back on the default locale 192 | // which might be there 193 | Locale.setDefault(Locale.ITALIAN); 194 | assertTrue(i18nDE.setLocale(Locale.ITALIAN)); 195 | assertEquals("value", i18nDE.tr("value")); 196 | } 197 | 198 | public void testTrcReturnsTextWhenTranslationNotFound() { 199 | assertEquals("baobab", i18nDE.trc("dont translate to German", "baobab")); 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /xdocs/tutorial.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tutorial 6 | 7 | 8 |

9 | 10 |

This page gives an overview of the Gettext Commons and 11 | describes how to integrate the library into existing Java 12 | applications.

13 | 14 |

Quick Links: I18nExample.java, API 17 | Documentation

18 |
19 | 20 |
21 |
    22 |
  1. Requirements
  2. 23 |
  3. Installation
  4. 24 |
  5. Internationalization
  6. 25 |
  7. Creating Resource Bundles
  8. 26 |
  9. Loading Resource Bundles
  10. 27 |
  11. Maven Integration
  12. 28 |
29 |
30 | 31 |
32 |
    33 |
  • Java 1.3 (or higher)
  • 34 |
  • GNU gettext
  • 35 |
36 |
37 | 38 |
39 | 40 | 41 | 42 | 43 |

Most Unix systems and Linux distributions ship with gettext 44 | packages.

45 |
46 |
47 | 48 |
49 |

The Gettext Commons provide the class I18n 51 | that has methods that need to be invoked each time a user visible 52 | string is used:

53 | 54 | 55 | I18n i18n = I18nFactory.getI18n(getClass()); 56 | 57 | System.out.println(i18n.tr("This text will be translated")); 58 | 59 | 60 |

I18n also supports proper handling of plurals:

61 | 62 | 63 | System.out.println(i18n.trn("Copied file.", "Copied files.", 1)); 64 | // will print "Copied file." 65 | 66 | System.out.println(i18n.trn("Copied file.", "Copied files.", 4)); 67 | // will print "Copied files." 68 | 69 | 70 |

In addition there are convenience methods that use the Java API 71 | MessageFormat.format() for substitution:

72 | 73 | 74 | System.out.println(i18n.tr("Folder: {0}", new File("/home/xnap-commons")); 75 | System.out.println(i18n.trn("{0} file", "{0} files", 5, new Integer(5))); 76 | 77 | 78 |

And sometimes it is necessary to provide different 79 | translations of the same word as some words may have multiple 80 | meanings in the native language the program is written but 81 | not in other languages:

82 | 83 | 84 | System.out.println(i18n.trc("chat (verb)", "chat")); 85 | System.out.println(i18n.trc("chat (noun)", "chat")); 86 | 87 |

The preferable way to create an I18n object is through the I18nFactory. 89 | The factory caches the I18n object internally using the the package 90 | name of the provided class object and registers it with 91 | I18nManager. Thus all classes of the same package will use the same 92 | I18n instance.

93 | 94 | 95 | public class SampleClass 96 | { 97 | private static I18n i18n = I18nFactory.getI18n(SampleClass.class); 98 | 99 | String localizedString; 100 | 101 | public SampleClass() 102 | { 103 | localizedString = i18n.tr("Hello, World"); 104 | } 105 | } 106 | 107 | 108 |

I18nManager 110 | lets you register independently created I18n objects and provides 111 | the facility to change the locale of all registered I18n objects thereby 112 | notifying possible LocaleChangeListeners:

113 | 114 | 115 | public class LocaleChangeAwareClass implements LocaleChangeListener 116 | { 117 | private static I18n i18n = I18nFactory.getI18n(LocaleChangeAwareClass.class); 118 | 119 | String localizedString; 120 | 121 | public LocaleChangeAwareClass() 122 | { 123 | localizedString = i18n.tr("Hello, World"); 124 | I18nManager.getInstance().addWeakLocaleChangeListener(this); 125 | } 126 | 127 | public void localeChanged(LocaleChangeEvent event) 128 | { 129 | // update strings 130 | localizedString = i18n.tr("Hello, World"); 131 | ... 132 | } 133 | } 134 | 135 | 136 |
137 |
138 |

Once the source code has been internationalized, i.e. all 139 | user visible strings are wrapped by a call to 140 | i18n.tr(), xgettext can be used to extract these 141 | strings for localization.

142 | 143 |

This 3 step process is illustrated in this figure:

144 | 145 |
146 | 147 |
    148 |
  1. 149 | xgettext scans the source code for calls to 150 | tr(), trc() and trn() and creates 151 | a pot file that contains all strings in the native language. 152 |
  2. 153 |
  3. 154 | msgmerge merges the strings into a po file that 155 | contains translations for a single locale. This file can be 156 | edited with convenient tools like poedit, KBabel or Emacs. 158 |
  4. 159 |
  5. 160 | msgfmt is used to generate Java class files that 161 | extend the Java ResourceBundle class. 162 |
  6. 163 |
164 | 165 |

Here is a simple example of running the gettext commands:

166 | 167 | 168 | # extract keys 169 | xgettext -ktrc -ktr -kmarktr -ktrn:1,2 -o po/keys.pot src/*.java 170 | 171 | # merge keys into localized po file 172 | msgmerge -U po/de.po po/keys.pot 173 | 174 | # translate file 175 | poedit po/de.po 176 | 177 | # create German ResourceBundle class file in app.i18n package 178 | msgfmt --java2 -d src/conf -r app.i18n.Messages -l de po/de.po 179 | 180 | 181 |
182 |
183 |

In order to specify the name of the resource bundles you want to 184 | use, you create an i18n.properties file and place it in your 185 | application's toplevel package. All subpackages will use this 186 | configuration file unless they find a different one on the way up in 187 | the package hierarchy.

188 | 189 |

i18n.properties expects the base name of the resources as 190 | the value of the key basename:

191 | 192 | basename=app.i18n.Messages 193 | 194 |

For more information on how the resource lookup works, please read here.

195 | 196 |
197 | 198 | 199 |
200 |

If Maven is used for building, the invocation of gettext can 201 | be easily integrated into the build process. Follow the 202 | appropriate link below for more information:

203 | 204 | 211 |
212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | com.googlecode.gettext-commons 4 | gettext-commons 5 | jar 6 | 0.9.9-SNAPSHOT 7 | Gettext Commons 8 | http://code.google.com/p/gettext-commons/ 9 | 10 | A library that supports gettext-based internationalization 11 | (i18n) of Java applications. 12 | 13 | 14 | 15 | GNU Library or Lesser General Public License (LGPL) 16 | http://www.gnu.org/licenses/lgpl.html 17 | 18 | 19 | 20 | 21 | Felix Berger 22 | bergerfx 23 | 24 | Developer 25 | 26 | http://www.felix.beldesign.de/ 27 | 28 | 29 | Tammo van Lessen 30 | tvanlessen 31 | 32 | Developer 33 | 34 | http://taval.de/ 35 | 36 | 37 | Steffen Pingel 38 | steffen.pingel 39 | 40 | Project Manager 41 | Developer 42 | 43 | http://steffenpingel.de 44 | 45 | 46 | Nicolas Fortin 47 | nicolas-f 48 | 49 | Developer 50 | 51 | http://www.orbisgis.org 52 | 53 | 54 | 55 | 56 | junit 57 | junit 58 | 3.8.1 59 | test 60 | 61 | 62 | 63 | 64 | scm:svn:http://gettext-commons.googlecode.com/svn/trunk 65 | 66 | 67 | scm:svn:https://gettext-commons.googlecode.com/svn/trunk 68 | 69 | http://gettext-commons.googlecode.com/svn/trunk 70 | 71 | 72 | src/java 73 | src/test 74 | 75 | 76 | src/conf 77 | 78 | 79 | 80 | 81 | src/test-resources 82 | 83 | 84 | 85 | 86 | 87 | org.apache.maven.plugins 88 | maven-compiler-plugin 89 | 90 | 1.4 91 | 1.4 92 | 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-eclipse-plugin 97 | 98 | 99 | 100 | org.eclipse.jdt.core.javanature 101 | 102 | 103 | 104 | 105 | org.eclipse.jdt.core.javabuilder 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | org.apache.maven.plugins 115 | maven-surefire-plugin 116 | 2.14 117 | 118 | true 119 | 120 | 121 | 122 | org.apache.felix 123 | maven-bundle-plugin 124 | 2.3.7 125 | 126 | 127 | bundle-manifest 128 | process-classes 129 | 130 | manifest 131 | 132 | 133 | 134 | true 135 | 136 | 137 | org.xnap.commons.i18n 138 | ${pom.artifactId} 139 | 140 | 141 | 142 | 143 | maven-jar-plugin 144 | 2.4 145 | 146 | 147 | ${project.build.outputDirectory}/META-INF/MANIFEST.MF 148 | 149 | 150 | 151 | 152 | maven-assembly-plugin 153 | 154 | 155 | src/assembly/bin.xml 156 | src/assembly/src.xml 157 | 158 | 159 | 160 | 161 | make-assembly 162 | package 163 | 164 | attached 165 | 166 | 167 | 168 | 169 | 170 | com.googlecode.gettext-commons 171 | gettext-maven-plugin 172 | 1.2.4 173 | 174 | 175 | convert-po-class 176 | compile 177 | 178 | dist 179 | 180 | 181 | 182 | 183 | src/test 184 | 185 | org.xnap.commons.i18n.Messages 186 | 187 | ${basedir}/po 188 | ${build.testOutputDirectory} 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /src/java/org/xnap/commons/i18n/I18nFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Felix Berger 5 | * Copyright (C) 2005 Steffen Pingel 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | package org.xnap.commons.i18n; 22 | 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.util.Locale; 26 | import java.util.MissingResourceException; 27 | import java.util.Properties; 28 | 29 | /** 30 | * Factory class that creates and caches I18n instances. 31 | *

32 | * Given a {@link Class} object the factory looks up the resource bundle 33 | * responsible for handling message translations. The bundle is returned with an 34 | * {@link I18n} object wrapped around it, which provides the translation 35 | * methods. The lookup is described at {@link #getI18n(Class,String)}. 36 | *

37 | * Use the factory for creating I18n objects to make sure no 38 | * extraneous objects are created. 39 | * 40 | * @author Felix Berger 41 | * @author Tammo van Lessen 42 | * @author Steffen Pingel 43 | * @since 0.9 44 | */ 45 | public class I18nFactory { 46 | 47 | private static final String BASENAME_KEY = "basename"; 48 | 49 | /** 50 | * Use the default configuration. 51 | * 52 | * @since 0.9.1 53 | */ 54 | public static final int DEFAULT = 0; 55 | /** 56 | * Fall back to a default resource bundle that returns the passed text if no 57 | * resource bundle can be located. 58 | * 59 | * @since 0.9.1 60 | */ 61 | public static final int FALLBACK = 1 << 0; 62 | /** 63 | * Look for files named {@link #PROPS_FILENAME} to determine the basename. 64 | * 65 | * @since 0.9.1 66 | */ 67 | public static final int READ_PROPERTIES = 2 << 0; 68 | /** 69 | * Do not cache {@link I18n} instance. 70 | * 71 | * @since 0.9.1 72 | */ 73 | public static final int NO_CACHE = 4 << 0; 74 | 75 | /** 76 | * Default name for Message bundles, is "i18n.Messages". 77 | * 78 | * @since 0.9.1 79 | */ 80 | public static final String DEFAULT_BASE_NAME = "i18n.Messages"; 81 | 82 | /** 83 | * Filename of the properties file that contains the i18n properties, is 84 | * "i18n.properties". 85 | * 86 | * @since 0.9 87 | */ 88 | public static final String PROPS_FILENAME = "i18n.properties"; 89 | 90 | private static final I18nCache i18nCache = new I18nCache(); 91 | 92 | private I18nFactory() 93 | { 94 | } 95 | 96 | /** 97 | * Clears the cache of i18n objects. Used by the test classes. 98 | */ 99 | static void clearCache() 100 | { 101 | i18nCache.visit(new I18nCache.Visitor() { 102 | 103 | public void visit(I18n i18n) 104 | { 105 | I18nManager.getInstance().remove(i18n); 106 | } 107 | }); 108 | i18nCache.clear(); 109 | } 110 | 111 | /** 112 | * Calls {@link #getI18n(Class, Locale) getI18n(clazz, Locale.getDefault())}. 113 | */ 114 | public static I18n getI18n(final Class clazz) 115 | { 116 | return getI18n(clazz, Locale.getDefault()); 117 | } 118 | 119 | /** 120 | * Calls {@link #getI18n(Class, Locale, int) getI18n(clazz, locale, 121 | * READ_PROPERTIES)}. 122 | * 123 | * @since 0.9.1 124 | */ 125 | public static I18n getI18n(final Class clazz, final Locale locale) 126 | { 127 | return getI18n(clazz, locale, READ_PROPERTIES); 128 | } 129 | 130 | /** 131 | * Returns the I18n instance responsible for translating messages in the 132 | * package specified by clazz. 133 | *

134 | * Lookup works by iterating upwards in the package hierarchy: First the 135 | * internal cache is asked for an I18n object for a package, otherwise the 136 | * algorithm looks for an i18n.properties file in the 137 | * package. The properties file is queried for a key named 138 | * basename whose value should be the fully qualified 139 | * resource/class name of the resource bundle, e.g 140 | * org.xnap.commons.i18n.Messages. 141 | *

142 | * If after the first iteration no I18n instance has been found, a second 143 | * search begins by looking for resource bundles having the name 144 | * baseName. 145 | * 146 | * @param clazz 147 | * the package hierarchy of the clazz and its class loader are 148 | * used for resolving and loading the resource bundle 149 | * @param locale 150 | * the locale of the underlying resource bundle 151 | * @param flags 152 | * a combination of these configuration flags: {@link #FALLBACK} 153 | * @return created or cached I18n instance 154 | * @throws MissingResourceException 155 | * if no resource bundle was found 156 | * @since 0.9.1 157 | */ 158 | public static I18n getI18n(final Class clazz, final Locale locale, final int flags) 159 | { 160 | ClassLoader classLoader = getClassLoader(clazz.getClassLoader()); 161 | 162 | String bundleName = null; 163 | if (isReadPropertiesSet(flags)) { 164 | String path = clazz.getName(); 165 | int index; 166 | do { 167 | index = path.lastIndexOf('.'); 168 | path = (index != -1) ? path.substring(0, index) : ""; 169 | bundleName = readFromPropertiesFile(path, locale, classLoader); 170 | } 171 | while (bundleName == null && index != -1); 172 | } 173 | 174 | if (bundleName == null) { 175 | bundleName = DEFAULT_BASE_NAME; 176 | } 177 | 178 | return getI18n("", bundleName, classLoader, locale, flags); 179 | } 180 | 181 | /** 182 | * Calls 183 | * {@link #getI18n(Class, String, Locale) getI18n(clazz, bundleName, Locale.getDefault())}. 184 | * 185 | * @since 0.9 186 | */ 187 | public static I18n getI18n(final Class clazz, final String bundleName) 188 | { 189 | return getI18n(clazz, bundleName, Locale.getDefault()); 190 | } 191 | 192 | /** 193 | * Calls 194 | * {@link #getI18n(Class, String, Locale, int) getI18n(clazz, bundleName, locale, DEFAULT)}. 195 | * 196 | * @since 0.9.1 197 | */ 198 | public static I18n getI18n(final Class clazz, final String bundleName, final Locale locale) 199 | { 200 | return getI18n(clazz, bundleName, locale, DEFAULT); 201 | } 202 | 203 | /** 204 | * Calls 205 | * {@link #getI18n(Class, String, Locale) getI18n(getPackageName(clazz), bundleName, clazz.getClassLoader(), locale, DEFAULT)}. 206 | * 207 | * @since 0.9.1 208 | */ 209 | public static I18n getI18n(final Class clazz, final String bundleName, final Locale locale, int flags) 210 | { 211 | return getI18n(clazz.getName(), bundleName, clazz.getClassLoader(), locale, flags); 212 | } 213 | 214 | /** 215 | * @since 0.9.1 216 | */ 217 | public static I18n getI18n(final String path, final String bundleName, final ClassLoader classLoader, final Locale locale, 218 | final int flags) 219 | { 220 | int index; 221 | String prefix = path; 222 | do { 223 | // chop of last segment of path 224 | index = prefix.lastIndexOf('.'); 225 | prefix = (index != -1) ? prefix.substring(0, index) : ""; 226 | String name = prefix.length() == 0 ? bundleName : prefix + "." + bundleName; 227 | 228 | // check cache 229 | I18n i18n = i18nCache.get(name, locale); 230 | if (i18n != null) { 231 | return i18n; 232 | } 233 | 234 | // look for resource bundle in class path 235 | i18n = findByBaseName(name, locale, getClassLoader(classLoader), flags); 236 | if (i18n != null) { 237 | if ((flags & NO_CACHE) == 0) { 238 | i18nCache.put(name, i18n); 239 | } 240 | return i18n; 241 | } 242 | } 243 | while (index != -1); 244 | 245 | // fallback to default bundle 246 | if (isFallbackSet(flags)) { 247 | I18n i18n = i18nCache.get("", locale); 248 | if (i18n == null) { 249 | i18n = new I18n(new EmptyResourceBundle(locale)); 250 | i18nCache.put("", i18n); 251 | } 252 | return i18n; 253 | } 254 | 255 | throw new MissingResourceException("Resource bundle not found", path, bundleName); 256 | } 257 | 258 | static ClassLoader getClassLoader(ClassLoader classLoader) { 259 | return (classLoader != null) ? classLoader : ClassLoader.getSystemClassLoader(); 260 | } 261 | 262 | /** 263 | * Tries to create an I18n instance from a properties file. 264 | * 265 | * @param path 266 | * @param loader 267 | * @return null if no properties file was found 268 | * @throws MissingResourceException 269 | * if properties file was found but specified resource not 270 | */ 271 | static String readFromPropertiesFile(final String path, final Locale locale, final ClassLoader loader) 272 | { 273 | Properties props = new Properties(); 274 | String filename = path.length() == 0 ? PROPS_FILENAME : path.replace('.', '/') + "/" + PROPS_FILENAME; 275 | InputStream in = loader.getResourceAsStream(filename); 276 | if (in != null) { 277 | try { 278 | props.load(in); 279 | } 280 | catch (IOException e) { 281 | // XXX now what? 282 | } 283 | finally { 284 | try { 285 | in.close(); 286 | } 287 | catch (IOException e) { 288 | // this exception is lost 289 | } 290 | } 291 | return props.getProperty(BASENAME_KEY); 292 | } 293 | return null; 294 | } 295 | 296 | /** 297 | * Uses the class loader to look for a messages properties file. 298 | * 299 | * @param baseName 300 | * the base name of the resource bundle 301 | * @param path 302 | * the path that prefixes baseName 303 | * @param loader 304 | * the class loader used to look up the bundle 305 | * @param flags 306 | * @return the created instance 307 | */ 308 | static I18n findByBaseName(final String baseName, final Locale locale, final ClassLoader loader, int flags) 309 | { 310 | try { 311 | return createI18n(baseName, locale, loader, flags); 312 | } 313 | catch (MissingResourceException e) { 314 | return null; 315 | } 316 | } 317 | 318 | /** 319 | * Creates a new i18n instance and registers it with {@link I18nManager}. 320 | * 321 | * @param baseName 322 | * the base name of the resource bundle 323 | * @param locale 324 | * the locale 325 | * @param loader 326 | * the class loader used to look up the bundle 327 | * @return the created instance 328 | */ 329 | private static I18n createI18n(final String baseName, final Locale locale, final ClassLoader loader, final int flags) 330 | { 331 | I18n i18n = new I18n(baseName, locale, loader); 332 | if (!isNoCacheSet(flags)) { 333 | I18nManager.getInstance().add(i18n); 334 | } 335 | return i18n; 336 | } 337 | 338 | private static boolean isFallbackSet(final int flags) 339 | { 340 | return (flags & FALLBACK) != 0; 341 | } 342 | 343 | private static boolean isReadPropertiesSet(final int flags) 344 | { 345 | return (flags & READ_PROPERTIES) != 0; 346 | } 347 | 348 | private static boolean isNoCacheSet(final int flags) 349 | { 350 | return (flags & NO_CACHE) != 0; 351 | } 352 | 353 | } 354 | -------------------------------------------------------------------------------- /src/java/org/xnap/commons/i18n/I18n.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Gettext Commons 3 | * 4 | * Copyright (C) 2005 Felix Berger 5 | * Copyright (C) 2005 Steffen Pingel 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | */ 21 | package org.xnap.commons.i18n; 22 | 23 | import java.lang.reflect.Method; 24 | import java.lang.reflect.Modifier; 25 | import java.text.MessageFormat; 26 | import java.util.Locale; 27 | import java.util.MissingResourceException; 28 | import java.util.ResourceBundle; 29 | 30 | /** 31 | * Provides methods for internationalization. 32 | *

33 | * To learn how message strings wrapped in one of the tr*() 34 | * methods can be extracted and localized, see this tutorial. 36 | * 37 | * @author Steffen Pingel 38 | * @author Felix Berger 39 | * @author Tammo van Lessen 40 | * @since 0.9 41 | */ 42 | public class I18n { 43 | 44 | private static final String CONTEXT_GLUE = "\u0004"; 45 | 46 | /** 47 | * Reference to the current localization bundles. 48 | */ 49 | private volatile ResourceBundle bundle; 50 | 51 | /** 52 | * The locale of the strings used in the source code. 53 | * 54 | * @see #trc(String, String) 55 | */ 56 | private volatile Locale sourceCodeLocale = Locale.ENGLISH; 57 | 58 | private String baseName; 59 | 60 | private ClassLoader loader; 61 | 62 | private volatile Locale locale; 63 | 64 | /** 65 | * Constructs an I18n object for a resource bundle. 66 | * 67 | * @param bundle 68 | * must not be null 69 | * @throws NullPointerException 70 | * if bundle is null 71 | * @since 0.9 72 | */ 73 | public I18n(ResourceBundle bundle) 74 | { 75 | setResources(bundle); 76 | } 77 | 78 | /** 79 | * Constructs an I18n object by calling {@link #setResources(String, Locale, 80 | * ClassLoader)}. 81 | * 82 | * @throws MissingResourceException 83 | * if the resource bundle could not be loaded 84 | * @throws NullPointerException 85 | * if one of the arguments is null 86 | * @since 0.9 87 | */ 88 | public I18n(String baseName, Locale locale, ClassLoader loader) 89 | { 90 | setResources(baseName, locale, loader); 91 | } 92 | 93 | /** 94 | * Returns the current resource bundle. 95 | * 96 | * @since 0.9 97 | */ 98 | public ResourceBundle getResources() 99 | { 100 | return bundle; 101 | } 102 | 103 | /** 104 | * Returns the locale this instance was created with. This can be different 105 | * from the locale of the resource bundle returned by 106 | * {@link #getResources()}. 107 | * 108 | * @return the locale or null, if this instance was directly created from a 109 | * resource bundle 110 | * @since 0.9 111 | */ 112 | public Locale getLocale() 113 | { 114 | return locale; 115 | } 116 | 117 | /** 118 | * Sets a resource bundle to be used for message translations. 119 | *

120 | * If this is called, the possibly previously specified class loader and 121 | * baseName are invalidated, since the bundle might be from a different 122 | * context. Subsequent calls to {@link #setLocale(Locale)} won't have any 123 | * effect. 124 | * 125 | * @since 0.9 126 | */ 127 | public synchronized void setResources(ResourceBundle bundle) 128 | { 129 | if (bundle == null) { 130 | throw new NullPointerException(); 131 | } 132 | this.bundle = bundle; 133 | this.baseName = null; 134 | this.locale = bundle.getLocale(); 135 | this.loader = null; 136 | } 137 | 138 | /** 139 | * Tries to load a resource bundle using {@link 140 | * ResourceBundle#getBundle(java.lang.String, java.util.Locale, 141 | * java.lang.ClassLoader)}. 142 | * 143 | * @throws MissingResourceException 144 | * if the bundle could not be loaded 145 | * @throws NullPointerException 146 | * if one of the arguments is null 147 | * @since 0.9 148 | */ 149 | public synchronized void setResources(String baseName, Locale locale, ClassLoader loader) 150 | { 151 | this.bundle = ResourceBundle.getBundle(baseName, locale, loader); 152 | this.baseName = baseName; 153 | this.locale = locale; 154 | this.loader = loader; 155 | } 156 | 157 | /** 158 | * Marks text to be translated, but doesn't return the 159 | * translation but text itself. 160 | * 161 | * @since 0.9 162 | */ 163 | public static final String marktr(String text) 164 | { 165 | return text; 166 | } 167 | 168 | /** 169 | * Tries to load a resource bundle for the locale. 170 | *

171 | * The resource bundle is then used for message translations. Note, you have 172 | * to retrieve all messages anew after a locale change in order for them to 173 | * be translated to the language specified by the new locale. 174 | *

175 | * 176 | * @return false if there is not enough information for loading a new 177 | * resource bundle, see {@link #setResources(ResourceBundle)}. 178 | * @throws MissingResourceException 179 | * if the resource bundle for locale could not be 180 | * found 181 | * @throws NullPointerException 182 | * if locale is null 183 | * @since 0.9 184 | */ 185 | public synchronized boolean setLocale(Locale locale) 186 | { 187 | if (baseName != null && loader != null) { 188 | setResources(baseName, locale, loader); 189 | return true; 190 | } 191 | else { 192 | this.locale = locale; 193 | } 194 | return false; 195 | } 196 | 197 | /** 198 | * Sets the locale of the text in the source code. 199 | *

200 | * Only languages that have one singular and one plural form can be used as 201 | * source code locales, since {@link #trn(String, String, long)} takes 202 | * exactly these two forms as parameters. 203 | * 204 | * @param locale 205 | * the locale 206 | * @throws NullPointerException 207 | * if locale is null 208 | * @see #trc(String, String) 209 | * @since 0.9 210 | */ 211 | public void setSourceCodeLocale(Locale locale) 212 | { 213 | if (locale == null) { 214 | throw new NullPointerException("locale must not be null"); 215 | } 216 | sourceCodeLocale = locale; 217 | } 218 | 219 | /** 220 | * Returns text translated into the currently selected 221 | * language. Every user-visible string in the program must be wrapped into 222 | * this function. 223 | * 224 | * @param text 225 | * text to translate 226 | * @return the translation 227 | * @since 0.9 228 | */ 229 | public final String tr(String text) 230 | { 231 | try { 232 | return bundle.getString(text); 233 | } 234 | catch (MissingResourceException e) { 235 | return text; 236 | } 237 | } 238 | 239 | /** 240 | * Returns text translated into the currently selected 241 | * language. 242 | *

243 | * Occurrences of {number} placeholders in text are replaced by 244 | * objects. 245 | *

246 | * Invokes 247 | * {@link MessageFormat#format(java.lang.String, java.lang.Object[])}. 248 | * 249 | * @param text 250 | * text to translate 251 | * @param objects 252 | * arguments to MessageFormat.format() 253 | * @return the translated text 254 | * @since 0.9 255 | */ 256 | public final String tr(String text, Object[] objects) 257 | { 258 | return MessageFormat.format(tr(text), objects); 259 | } 260 | 261 | /** 262 | * Convenience method that invokes {@link #tr(String, Object[])}. 263 | * 264 | * @since 0.9 265 | */ 266 | public final String tr(String text, Object o1) 267 | { 268 | return tr(text, new Object[]{ o1 }); 269 | } 270 | 271 | /** 272 | * Convenience method that invokes {@link #tr(String, Object[])}. 273 | * 274 | * @since 0.9 275 | */ 276 | public final String tr(String text, Object o1, Object o2) 277 | { 278 | return tr(text, new Object[]{ o1, o2 }); 279 | } 280 | 281 | /** 282 | * Convenience method that invokes {@link #tr(String, Object[])}. 283 | * 284 | * @since 0.9 285 | */ 286 | public final String tr(String text, Object o1, Object o2, Object o3) 287 | { 288 | return tr(text, new Object[]{ o1, o2, o3 }); 289 | } 290 | 291 | /** 292 | * Convenience method that invokes {@link #tr(String, Object[])}. 293 | * 294 | * @since 0.9 295 | */ 296 | public final String tr(String text, Object o1, Object o2, Object o3, Object o4) 297 | { 298 | return tr(text, new Object[]{ o1, o2, o3, o4 }); 299 | } 300 | 301 | /** 302 | * Returns the plural form for n of the translation of 303 | * text. 304 | * 305 | * @param text 306 | * the key string to be translated. 307 | * @param pluralText 308 | * the plural form of text. 309 | * @param n 310 | * value that determines the plural form 311 | * @return the translated text 312 | * @since 0.9 313 | */ 314 | public final String trn(String text, String pluralText, long n) 315 | { 316 | try { 317 | return trnInternal(bundle, text, pluralText, n); 318 | } 319 | catch (MissingResourceException e) { 320 | return (n == 1) ? text : pluralText; 321 | } 322 | } 323 | 324 | /** 325 | * Returns the plural form for n of the translation of 326 | * text. 327 | * 328 | * @param text 329 | * the key string to be translated. 330 | * @param pluralText 331 | * the plural form of text. 332 | * @param n 333 | * value that determines the plural form 334 | * @param objects 335 | * object args to be formatted and substituted. 336 | * @return the translated text 337 | * @since 0.9 338 | */ 339 | public final String trn(String text, String pluralText, long n, Object[] objects) 340 | { 341 | return MessageFormat.format(trn(text, pluralText, n), objects); 342 | } 343 | 344 | /** 345 | * Overloaded method that invokes 346 | * {@link #trn(String, String, long, Object[])} passing Object 347 | * arguments as an array. 348 | * 349 | * @since 0.9 350 | */ 351 | public final String trn(String text, String pluralText, long n, Object o1) 352 | { 353 | return trn(text, pluralText, n, new Object[]{ o1 }); 354 | } 355 | 356 | /** 357 | * Overloaded method that invokes 358 | * {@link #trn(String, String, long, Object[])} passing Object 359 | * arguments as an array. 360 | * 361 | * @since 0.9 362 | */ 363 | public final String trn(String text, String pluralText, long n, Object o1, Object o2) 364 | { 365 | return trn(text, pluralText, n, new Object[]{ o1, o2 }); 366 | } 367 | 368 | /** 369 | * Overloaded method that invokes 370 | * {@link #trn(String, String, long, Object[])} passing Object 371 | * arguments as an array. 372 | * 373 | * @since 0.9 374 | */ 375 | public final String trn(String text, String pluralText, long n, Object o1, Object o2, Object o3) 376 | { 377 | return trn(text, pluralText, n, new Object[]{ o1, o2, o3 }); 378 | } 379 | 380 | /** 381 | * Overloaded method that invokes 382 | * {@link #trn(String, String, long, Object[])} passing Object 383 | * arguments as an array. 384 | * 385 | * @since 0.9 386 | */ 387 | public final String trn(String text, String pluralText, long n, Object o1, Object o2, Object o3, Object o4) 388 | { 389 | return trn(text, pluralText, n, new Object[]{ o1, o2, o3, o4 }); 390 | } 391 | 392 | /** 393 | * Returns the plural form for n of the translation of ??? 394 | * 395 | * Based on GettextResource.java that is part of GNU gettext for Java 396 | * Copyright (C) 2001 Free Software Foundation, Inc. 397 | * 398 | * @param bundle a ResourceBundle 399 | * @param text the key string to be translated, an ASCII string 400 | * @param pluralText its English plural form 401 | * @return the translation of text depending on n, 402 | * or text or pluralText if none is found 403 | */ 404 | private static String trnInternal(ResourceBundle orgBundle, String text, String pluralText, long n) 405 | { 406 | ResourceBundle bundle = orgBundle; 407 | do { 408 | boolean isGetTextBundle = false; 409 | boolean hasPluralHandling = false; 410 | Method handleGetObjectMethod = null; 411 | Method getParentMethod = null; 412 | Method lookupMethod = null; 413 | Method pluralEvalMethod = null; 414 | try { 415 | handleGetObjectMethod = bundle.getClass().getMethod("handleGetObject", new Class[]{ String.class }); 416 | getParentMethod = bundle.getClass().getMethod("getParent", new Class[0]); 417 | isGetTextBundle = Modifier.isPublic(handleGetObjectMethod.getModifiers()); 418 | lookupMethod = bundle.getClass().getMethod("lookup", new Class[]{ String.class }); 419 | pluralEvalMethod = bundle.getClass().getMethod("pluralEval", new Class[]{ Long.TYPE }); 420 | hasPluralHandling = true; 421 | } 422 | catch (Exception e) {} 423 | if (isGetTextBundle) { 424 | // GNU gettext generated bundle 425 | if (hasPluralHandling) { 426 | // GNU gettext generated bundle w/ plural handling 427 | try { 428 | Object localValue = lookupMethod.invoke(bundle, new Object[]{ text }); 429 | if (localValue.getClass().isArray()) { 430 | String[] pluralforms = (String[])localValue; 431 | long index = 0; 432 | try { 433 | index = ((Long)pluralEvalMethod.invoke(bundle, new Object[]{ new Long(n) })) 434 | .longValue(); 435 | if (!(index >= 0 && index < pluralforms.length)) { 436 | index = 0; 437 | } 438 | } 439 | catch (IllegalAccessException e) {} 440 | return pluralforms[(int)index]; 441 | } 442 | else { 443 | // Found the value. It doesn't depend on n in this 444 | // case. 445 | return (String)localValue; 446 | } 447 | } 448 | catch (Exception e) {} 449 | } 450 | else { 451 | // GNU gettext generated bundle w/o plural handling 452 | try { 453 | Object localValue = handleGetObjectMethod.invoke(bundle, new Object[]{ text }); 454 | if (localValue != null) { 455 | return (String)localValue; 456 | } 457 | } 458 | catch (Exception e) {} 459 | } 460 | bundle = null; 461 | try { 462 | bundle = (ResourceBundle)getParentMethod.invoke(bundle, new Object[0]); 463 | } 464 | catch (Exception e) {} 465 | } 466 | else { 467 | return bundle.getString(text); 468 | } 469 | } 470 | while (bundle != null); 471 | throw new MissingResourceException("Can not find resource for key " + text + " in bundle " 472 | + orgBundle.getClass().getName(), orgBundle.getClass().getName(), text); 473 | } 474 | 475 | /** 476 | * Disambiguates translation keys. 477 | * 478 | * @param context 479 | * the context of the text to be translated 480 | * @param text 481 | * the ambiguous key message in the source locale 482 | * @return text if the locale of the underlying resource 483 | * bundle equals the source code locale, the disambiguated 484 | * translation of text otherwise 485 | * 486 | * @see #setSourceCodeLocale(Locale) 487 | * @since 0.9 488 | */ 489 | public final String trc(String context, String text) 490 | { 491 | if (sourceCodeLocale.equals(getResources().getLocale())) { 492 | return text; 493 | } else { 494 | String key = context + CONTEXT_GLUE + text; 495 | String translated = tr(key); 496 | // if no translation was found return text in source locale 497 | return translated == key ? text : translated; 498 | } 499 | } 500 | 501 | /** 502 | * Returns the plural form for n of the translation of 503 | * text. 504 | * 505 | * @param context 506 | * the context of the message to disambiguate it when translating 507 | * @param singularText 508 | * the key string to be translated. 509 | * @param pluralText 510 | * the plural form of text. 511 | * @param n 512 | * value that determines the plural form 513 | * @return the translated text 514 | * @since 0.9.5 515 | */ 516 | public final String trnc(String context, String singularText, String pluralText, long n) { 517 | try { 518 | return trnInternal(bundle, context + CONTEXT_GLUE + singularText, pluralText, n); 519 | } 520 | catch (MissingResourceException e) { 521 | return (n == 1) ? singularText : pluralText; 522 | } 523 | } 524 | 525 | /** 526 | * Returns the plural form for n of the translation of 527 | * text. 528 | * 529 | * @param context 530 | * the context of the message to disambiguate it when translating 531 | * @param singularText 532 | * the key string to be translated. 533 | * @param pluralText 534 | * the plural form of text. 535 | * @param n 536 | * value that determines the plural form 537 | * @param objects 538 | * object args to be formatted and substituted. 539 | * @return the translated text 540 | * @since 0.9 541 | */ 542 | public final String trnc(String context, String singularText, String pluralText, long n, Object[] objects) { 543 | return MessageFormat.format(trnc(context, singularText, pluralText, n), objects); 544 | } 545 | 546 | /** 547 | * Overloaded method that invokes 548 | * {@link #trnc(String, String, String, long, Object[])} passing obj 549 | * arguments as an array. 550 | * 551 | * @since 0.9.5 552 | */ 553 | public final String trnc(String comment, String singularText, String pluralText, long n, Object obj) { 554 | return MessageFormat.format(trnc(comment, singularText, pluralText, n), new Object[] { obj }); 555 | } 556 | 557 | /** 558 | * Overloaded method that invokes 559 | * {@link #trnc(String, String, String, long, Object[])} passing obj1 and obj2 560 | * arguments as an array. 561 | * 562 | * @since 0.9.5 563 | */ 564 | public final String trnc(String comment, String singularText, String pluralText, long n, Object obj1, Object obj2) { 565 | return MessageFormat.format(trnc(comment, singularText, pluralText, n), new Object[] { obj1, obj2 }); 566 | } 567 | 568 | /** 569 | * Overloaded method that invokes 570 | * {@link #trnc(String, String, String, long, Object[])} passing obj1, obj2 and obj3 571 | * arguments as an array. 572 | * 573 | * @since 0.9.5 574 | */ 575 | public final String trnc(String comment, String singularText, String pluralText, long n, Object obj1, Object obj2, Object obj3) { 576 | return MessageFormat.format(trnc(comment, singularText, pluralText, n), new Object[] { obj1, obj2, obj3 }); 577 | } 578 | 579 | /** 580 | * Overloaded method that invokes 581 | * {@link #trnc(String, String, String, long, Object[])} passing obj1, obj2, obj3 and obj4 582 | * arguments as an array. 583 | * 584 | * @since 0.9.5 585 | */ 586 | public final String trnc(String comment, String singularText, String pluralText, long n, Object obj1, Object obj2, Object obj3, Object obj4) { 587 | return MessageFormat.format(trnc(comment, singularText, pluralText, n), new Object[] { obj1, obj2, obj3, obj4 }); 588 | } 589 | 590 | } 591 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Wed Aug 22 11:10:30 EDT 2007 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.4 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning 12 | org.eclipse.jdt.core.compiler.source=1.3 13 | org.eclipse.jdt.core.formatter.align_type_members_on_columns=false 14 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 15 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 16 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 17 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 18 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 19 | org.eclipse.jdt.core.formatter.alignment_for_assignment=0 20 | org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 21 | org.eclipse.jdt.core.formatter.alignment_for_compact_if=52 22 | org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=48 23 | org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 24 | org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 25 | org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 26 | org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 27 | org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 28 | org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 29 | org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=64 30 | org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 31 | org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=64 32 | org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 33 | org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 34 | org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 35 | org.eclipse.jdt.core.formatter.blank_lines_after_package=1 36 | org.eclipse.jdt.core.formatter.blank_lines_before_field=1 37 | org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1 38 | org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 39 | org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 40 | org.eclipse.jdt.core.formatter.blank_lines_before_method=1 41 | org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 42 | org.eclipse.jdt.core.formatter.blank_lines_before_package=0 43 | org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 44 | org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 45 | org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line 46 | org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line 47 | org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line 48 | org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line 49 | org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line 50 | org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line 51 | org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line 52 | org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line 53 | org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line 54 | org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line 55 | org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line 56 | org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false 57 | org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=true 58 | org.eclipse.jdt.core.formatter.comment.format_block_comments=true 59 | org.eclipse.jdt.core.formatter.comment.format_header=false 60 | org.eclipse.jdt.core.formatter.comment.format_html=true 61 | org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true 62 | org.eclipse.jdt.core.formatter.comment.format_line_comments=true 63 | org.eclipse.jdt.core.formatter.comment.format_source_code=true 64 | org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true 65 | org.eclipse.jdt.core.formatter.comment.indent_root_tags=true 66 | org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert 67 | org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert 68 | org.eclipse.jdt.core.formatter.comment.line_length=80 69 | org.eclipse.jdt.core.formatter.compact_else_if=true 70 | org.eclipse.jdt.core.formatter.continuation_indentation=2 71 | org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 72 | org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false 73 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true 74 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true 75 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true 76 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true 77 | org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true 78 | org.eclipse.jdt.core.formatter.indent_empty_lines=false 79 | org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true 80 | org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true 81 | org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true 82 | org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false 83 | org.eclipse.jdt.core.formatter.indentation.size=4 84 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert 85 | org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert 86 | org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert 87 | org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert 88 | org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert 89 | org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert 90 | org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert 91 | org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert 92 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert 93 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert 94 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert 95 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert 96 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert 97 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert 98 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert 99 | org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert 100 | org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert 101 | org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert 102 | org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert 103 | org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert 104 | org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert 105 | org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert 106 | org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert 107 | org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=do not insert 108 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert 109 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert 110 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert 111 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert 112 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert 113 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert 114 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert 115 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert 116 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert 117 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert 118 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert 119 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert 120 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert 121 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert 122 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert 123 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert 124 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert 125 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert 126 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert 127 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert 128 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert 129 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert 130 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert 131 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert 132 | org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert 133 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert 134 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert 135 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert 136 | org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert 137 | org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert 138 | org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert 139 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert 140 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert 141 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert 142 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert 143 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert 144 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert 145 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert 146 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert 147 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert 148 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert 149 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert 150 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert 151 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert 152 | org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert 153 | org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert 154 | org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert 155 | org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert 156 | org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert 157 | org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert 158 | org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert 159 | org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert 160 | org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert 161 | org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert 162 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert 163 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert 164 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert 165 | org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert 166 | org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert 167 | org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert 168 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert 169 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert 170 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert 171 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert 172 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert 173 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert 174 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert 175 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert 176 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert 177 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert 178 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert 179 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert 180 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert 181 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert 182 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=insert 183 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert 184 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=insert 185 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert 186 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=insert 187 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert 188 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert 189 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert 190 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert 191 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert 192 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert 193 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert 194 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert 195 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert 196 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert 197 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert 198 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert 199 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert 200 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert 201 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert 202 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert 203 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert 204 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert 205 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert 206 | org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert 207 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert 208 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert 209 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert 210 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert 211 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert 212 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=do not insert 213 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert 214 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert 215 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert 216 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert 217 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert 218 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert 219 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert 220 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert 221 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert 222 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert 223 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert 224 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert 225 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert 226 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert 227 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert 228 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert 229 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert 230 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert 231 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert 232 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert 233 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert 234 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert 235 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert 236 | org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert 237 | org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert 238 | org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert 239 | org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert 240 | org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert 241 | org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert 242 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert 243 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert 244 | org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert 245 | org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert 246 | org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert 247 | org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert 248 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert 249 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert 250 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert 251 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert 252 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert 253 | org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false 254 | org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false 255 | org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false 256 | org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false 257 | org.eclipse.jdt.core.formatter.lineSplit=120 258 | org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false 259 | org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false 260 | org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 261 | org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 262 | org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false 263 | org.eclipse.jdt.core.formatter.tabulation.char=tab 264 | org.eclipse.jdt.core.formatter.tabulation.size=4 265 | org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false 266 | org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true 267 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | 504 | 505 | --------------------------------------------------------------------------------