Suche brauchbares I18N Lib

steffomio

Mitglied
Gibts da was?
Bei Apache habe ich nichts gefunden oder war grad blind auf beide Augen.

Ich dachte mir, das dieses Problem so populär sein sollte wie Logging, wo es auch ganz legendäre Libs wie Log4j gibt.

Also gibt es sowas auch für InternationalisatioN (I18N)?
 

steffomio

Mitglied
Das benutze ich bereits, und habe da ein ziemlich hässliches "Gestell" drüber gebaut.
Das erstellt mir zwar eine Datei mit den noch nicht übersetzten Keys und funktioniert auch sonst ganz gut.
Aber mir ist das jedoch alles zu Primitiv. So gibts z.B. keine Fallbacks und so'n bisschen extra Schnickschnack wäre auch nicht schlecht.
Gibts da nicht was besseres?
Java:
package de.steffomio.sockserver.I18N;

import de.steffomio.sockserver.util.PropertiesUtil;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
import org.apache.log4j.Logger;

/**
 *
 * @author Stefan Brinkmann <steffomio@arcor.de>
 */
public enum T {
    // available locales
    de_DE("de", "DE"), // <-- index[0] is default Translation
    en_EN("en", "EN");
    
    private static final Logger logger = Logger.getLogger(T.class);
    // current Locale
    private Locale locale = null;
    
    // Filename prefix of I18N Files
    private static String PREFIX_TRANSLATIONS_FILE = "translation";
    private static String KEY_NOT_FOUND = "::Key not found!";
    
    //current Translation
    private static ResourceBundle TRANSLATION = null;
    
    /**
     * 
     * Use T.activateTranslation(T.anyEntry)<br />
     * to load Resource of translation Data into Instance<br />
     * and set field as active Translation<br /><br />
     * 
     * To switch Translation use:<br />
     * T.activateTranslation(T.anyOtherEntry);<br />
     * T.translateAll();<br />
     * 
     * @param lang
     * @param country 
     */
    T(String lang, String country){
        locale = new Locale(lang, country);
        String Classpath = T.class.getPackage().getName().toString();
        int i = 0;
    }
    
    /**
     * 
     * @param translation 
     */
    public static void activateTranslation(T language){
        language.activateTranslation();
    }
    
    /**
     * loads translation Resource
     */
    public void activateTranslation(){
        TRANSLATION = ResourceBundle.getBundle(T.class.getPackage().getName().toString() + "." + PREFIX_TRANSLATIONS_FILE, locale);
    }
    
    /**
     * 
     * @param
     * @return T activated Language
     */
    public static T setLanguage(String language){
        
        //get all locales from T
        T[] tList = T.values();
        // search for available Translations
        for(int i = 0; i < tList.length; i++){
            if(language.equals(tList[i].toString())){
                tList[i].activateTranslation();
                return tList[i];
            }
        }
        
        // no valid translation found
        tList[0].activateTranslation();
        return tList[0];
    }
    
    /**
     * 
     * @param key
     * @param args
     * @return 
     */
    public static String t (String key, Object... args){
        // catch emty things
        if(key.equals("") || key == null){
            return "";
        }
        
        // return translation
        if(TRANSLATION.containsKey(key)){
            return MessageFormat.format(TRANSLATION.getString(key), args);
        }
        
        // write missed keys to developers best friend File ;)
        missedI18NKeys.put(key, "");
        return key + KEY_NOT_FOUND;
    }
    
    /**
    * for dev only
    * contains not found I18N Keys and write them to missedI18N.properties
    */
    public static void writeMissedKeys(){
        missedI18NKeys.writeOnExit();
    }
    
    private static MissedI18NKeys missedI18NKeys = new MissedI18NKeys();
    
    private static class MissedI18NKeys extends PropertiesUtil{
        
        private String _fileName = "./missed_I18N_keys.properties";
        
        public MissedI18NKeys(){
            //loadExternalFile(_fileName, true, true);
        }
        
        
        /**
         * try to sort and write possibly empty file with missed keys
         */
        public void writeOnExit(){
            try {
                storePropertiesSorted(_fileName, 5, "", true);
            } catch (IOException ex) {
                logger.error("Can't write out missed I18N Keys.", ex);
            }
        }
    }
}
 

turtle

Top Contributor
Aber mir ist das jedoch alles zu Primitiv. So gibts z.B. keine Fallbacks und so'n bisschen extra Schnickschnack wäre auch nicht schlecht.

Ich nehme den WindowBuilder von Eclipse. Da kannst Du einstellen, wie die Art des ResourceBundles gebildet werden soll. Darüber hinaus, quasi als Schnickschnack gibt's nen schönen PropertyEdtior, in dem Du alle Übersetzungen parallel sehen und erkennen kannst, wo noch Übersetzungen fehlen.

Reicht bei mir aus, zumal ein Fallback doch in ResourceBundle eingebaut ist, oder meinst Du was anderes?
 

Anhänge

  • i18n.png
    i18n.png
    71,2 KB · Aufrufe: 43

steffomio

Mitglied
Danke, die T class habe ich etwas umgebaut aber noch nicht wirklich getestet, weil ich grad an anderen bereichen baue.

Wenn es dich interessiert, hier die T und die dazu gehörige Util

Java:
public class T {
    
    private static final Logger logger = Logger.getLogger(T.class);
    
    // current locale
    private static Locs currentBundle = Locs.values()[0];
    
    // FallBack if key was not found
    public final static Locs FALL_BACK = Locs.en_EN;
    
    // write not existing keys to file
    private static KeyLogger keyLogger = new KeyLogger();
    
    /**
     * If FallBack don't has the key, the key itself will be displayed, Followed by the KEY_NOT_FOUND.<br/> You can call
     * writeMissedKeys() to write out missed keys to file in workdir
     */
    private static String KEY_NOT_FOUND = "::Key not found!";

    /**
     * handy way for direct access
     * @param key
     * @param args
     * @return 
     */
    public static String t(String key, Object... args) {
        return tr(key, args);
    }

    /**
     * Use this for wrappers in your Base classes
     * @param key
     * @param args
     * @return
     */
    public static String tr(String key, Object[] args) {
        // catch emty things
        if (key.equals("") || key == null) {
            return "";
        }

        // return translation
        if (currentBundle.rBundle.containsKey(key)) {
            return MessageFormat.format(currentBundle.rBundle.getString(key), args);

            // or FallBack
        } else if (FALL_BACK.rBundle.containsKey(key)) {
            return MessageFormat.format(FALL_BACK.rBundle.getString(key), args);
        }

        // or write missed keys to developers best friend File ;)
        keyLogger.put(key, "");
        return key + KEY_NOT_FOUND;
    }

    /**
     * set current used translationSet
     *
     * @param t
     */
    public static void setLanguage(Locs t) {
        currentBundle = t;
    }

    /**
     * for dev only contains not found I18N Keys and write them to missedI18N.properties
     */
    public static void writeMissedKeys() {
        keyLogger.write();
    }
    
    //<editor-fold defaultstate="collapsed" desc="Subclass Locs contains provided Locales">
    /**
     * 
     */
    public enum Locs{
        
        // available locales
        
        en_EN("en", "EN"),
        de_DE("de", "DE");
        
        public final String lang;
        public final String country;
        
        /**
         * The Package where the Recource Bundles are stored
         */
        private String resourcePackagePath = "de.steffomio.sockserver.resource.translation";
        /**
         * contains the ResourceBundle
         */
        public ResourceBundle rBundle;
        
        // current Locale
        private Locale locale;
        
        private Locs(String l, String c){
            lang = l;
            country = c;
            locale = new Locale(lang, country);
            try {
                rBundle = ResourceBundle.getBundle(resourcePackagePath, locale);
            } catch (MissingResourceException ex) {
                logger.fatal(ex.getMessage(), ex);
            }
        }
    }
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="SubClass KeyLogger">
    /**
     *
     */
    private static class KeyLogger extends PropertiesUtil {
        
        /**
         * try to sort and write possibly empty file with missed keys
         */
        public void write() {
            try {
                storePropertiesSorted("./missed_I18N_keys.properties", 5, "", true);
            } catch (IOException ex) {
                logger.error("Can't write out missed I18N Keys.", ex);
            }
        }
    }
    //</editor-fold>
}

und die Util:

Java:
public class PropertiesUtil extends Properties {

    /*
     *
     */
    public PropertiesUtil() {
    }

    /**
     *
     * @param prop
     * @param value search string
     * @return PropertiesUtil.Iteration
     */
    public String[] getByValue(Properties prop, String value) {
        // String array with max. possible entries
        String[] preList = new String[size()];

        // temp search Container 
        Map.Entry next;
        // iterate through Property
        Iterator iter = entrySet().iterator();
        int found = 0;
        while (iter.hasNext()) {
            // map next to Entry
            next = (Map.Entry) iter.next();
            // check and return
            if (next.getValue().equals(value)) {
                preList[found] = (String) next.getKey();
                found++;
            }
        }

        // cut length of array to found Items
        String[] list = new String[found];
        int i = 0;
        while (i < found) {
            list[i] = preList[i];
            i++;
        }
        return list;
    }

    /**
     *
     * @param path loads from <b>external</b> resources - not from inside the
     * executed .jar file.<br /><br />
     *
     * local Path is relative to executed .jar File or assigned working Dir <br
     * />like <b>dir/file.properties</b> absolute ath begins with Harddisk ID
     * like C:/dir1/dir2/file.properties <br /> don't use Backslash \ for File
     * seperator don't use trailing Slash for relative Paths
     *
     * @param overwrite overwrite existing Keys or not
     *
     * @param autoCreateFile creates file if not exists. Don't creates
     * Directories
     *
     * @return instance of Properties
     * @throws IOException
     */
    public void loadExternalFile(String path, boolean overwriteKeys, boolean autoCreateFile) throws IOException {
        Properties prop = new Properties();
        File file = new File(path);
        if (autoCreateFile == true && !file.isFile()) {
            file.createNewFile();
        }
        //load File to prop
        FileInputStream fis = new FileInputStream(file);
        prop.load(fis);
        mergeProperties(prop, overwriteKeys);
    }

    /**
     *
     * @param fullPath
     * @return
     * @throws IOException
     */
    /**
     *
     * @param fullPath full qualified slashed (not dotted!) Package Path <br
     * />like /com/me/application/resource/props.properties
     * @param overwriteKeys overwrite existing Keys or not
     */
    public void loadInternalFile(String fullPath, boolean overwriteKeys) throws IOException{
        Properties prop = new Properties();
        InputStream stream = PropertiesUtil.class.getResourceAsStream(fullPath);
        prop.load(stream);
        mergeProperties(prop, overwriteKeys);
        
    }

    /**
     *
     * Stores File outside of executed .jar File.<br /> For working Dir of jar
     * File simply use bare Filename like <br /> myFile.properties<br /> else
     * use full Paths like: <br /> String path =
     * System.getProperty("user.home"); String path =
     * System.getProperty("user.home") + "\\Local Settings\\ApplicationData";
     * String path = System.getProperty("user.dir"); // for working dir full
     * path
     *
     * @param prop
     * @param path
     * @param comment an in File Description (use \r\n for Linebreak)
     * @throws IOException
     */
    public void storeProperties(String path, String comment) throws IOException {
        store(new FileOutputStream(path), comment);
    }

    /**
     * same as storeProperties() but Properties are well sorted by keyName
     * 
     * @param path
     *      any suitable filepath
     * @param sortExtraLineBreak
     *      if property-key changes after String-index(n) an extra linebreak will be inserted for better owerview
     * @param comment
     *      comment on top of File. Maybe Licens Info, usage...
     * @param autoCreate 
     *      automatically create the File if not exists
     */
    public void storePropertiesSorted(String path, int sortExtraLineBreak, String comment, boolean autoCreate) throws IOException {

        // read keys into array
        String[] list = new String[size()];
        Enumeration keys = keys();
        int i = 0;
        while (keys.hasMoreElements()) {
            list[i++] = keys.nextElement().toString();
        }

        // sort keys
        Arrays.sort(list);

        // build file content
        String out = comment;
        String last = "";
        String now = "";
        int checkLength = sortExtraLineBreak;
        for (String s : list) {
            now = s.substring(0, s.length() < checkLength ? s.length() : checkLength);
            if (!now.equals(last)) {
                out += "\r\n";
                last = now;
            }
            out += "\r\n" + s + "=" + this.get(s);
        }

        // write out file
        FileUtil.writeString(path, out, autoCreate);
    }

    /**
     * read from other Properties and write into this Instance
     *
     * @param source the Properties from where will be readed
     * @param target the Properties to where will be written
     * @param overwrite if true, existing keys of target will be overwritten
     * @return
     */
    public void mergeProperties(Properties source, boolean overwrite) {
        Enumeration<Object> keys = source.keys();
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            if (overwrite == true) {
                put(key, source.getProperty(key));
            } else if (getProperty(key) == null) {
                put(key, source.getProperty(key));
            }
        }
    }
}

Einfach T.t("any key");
Nicht erstellte Keys werden in einer Datei im Arbeitsverzeichnis gespeichert, die man dann nur noch in die translation_xx_XX.properties kopieren muss -- und natürlich übersetzen.

Wems gefällt, darfs behalten.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
I Reflection: Suche Feld + in Unterklassen Java Basics - Anfänger-Themen 7
LimDul Suche Java Stream Tutorial Java Basics - Anfänger-Themen 2
M Suche Resteasy Example Java Basics - Anfänger-Themen 24
B Beliebiger String gegeben Suche Datum in String Java Basics - Anfänger-Themen 6
M binäre Suche im Intervall Java Basics - Anfänger-Themen 6
M binäre Suche Java Basics - Anfänger-Themen 4
H Suche Java3D 32 bit Java Basics - Anfänger-Themen 20
amelie123456 Lineare Suche / Binäre Suche Java Basics - Anfänger-Themen 2
F Suche nach betreuender Person für eine Jahresarbeit der 12. Klasse. Java Basics - Anfänger-Themen 6
K Warum ist die binäre Suche bei der verketteten Liste nicht so effektiv? Java Basics - Anfänger-Themen 3
H Suche jemanden für kleine Uni-Abgabe/ mit Vergütung Java Basics - Anfänger-Themen 1
RudiRüssel Binäre Suche, unsortiert, lokales Maximum Java Basics - Anfänger-Themen 15
Y Suche von Studenten anhand Ihrer Eigenschaften. Java Basics - Anfänger-Themen 1
F Auf der Suche in π Java Basics - Anfänger-Themen 13
C Suche Nachhilfe in Java Java Basics - Anfänger-Themen 5
T Binärbaum-Suche Implementation Java Basics - Anfänger-Themen 6
A suche dringend Hilfe!! Java Basics - Anfänger-Themen 6
N Operatoren Schreibtischtest der Reihen-Suche nach Aufschluss in die Basics Java Basics - Anfänger-Themen 1
B Suche free SVN Hosting Java Basics - Anfänger-Themen 12
S Binäre-Suche Algorithmus Java Basics - Anfänger-Themen 1
S Java Lineare-Suche Zeitmessung Java Basics - Anfänger-Themen 5
S Java Lineare Suche Java Basics - Anfänger-Themen 1
S Binäre-Suche bei unsortierten Daten Java Basics - Anfänger-Themen 7
E Die richtige Suche in der API Java Basics - Anfänger-Themen 1
S suche nach varible POSITION ... fuer das pixel-maennchen Java Basics - Anfänger-Themen 4
E Weg-Suche-Problem rekursiv Java Basics - Anfänger-Themen 12
B Suche Programme mit Fehlern Java Basics - Anfänger-Themen 9
jaleda100 Component für Suche Java Basics - Anfänger-Themen 4
L Suche ein sampel Projekt Java Basics - Anfänger-Themen 2
P Suche Aufwandsgenerator (o-notation) Java Basics - Anfänger-Themen 1
S Suche aktuelles 2D Grafik Tutorial Java Basics - Anfänger-Themen 5
M Suche hilfe bei Array Java Basics - Anfänger-Themen 4
L Binäre Suche mit Comparator Java Basics - Anfänger-Themen 5
J Methoden Suche effiziente Implementierung für eine Methode Java Basics - Anfänger-Themen 3
D Ich suche nach einer Möglickeit den Webseiten Inhalt per Java zu analysieren Automatisch Java Basics - Anfänger-Themen 3
B String: suche nach Wörter und in List<String> speichern Java Basics - Anfänger-Themen 3
D Erste Schritte Suche Quelltext Java Basics - Anfänger-Themen 7
M Rekursion Minimums Suche Java Basics - Anfänger-Themen 12
J Suche Hilfestellung Java Basics - Anfänger-Themen 10
G Erste Schritte Suche Java Programmierer für kleines Projekt Java Basics - Anfänger-Themen 1
J Suche die Emailadresse Java Basics - Anfänger-Themen 6
H Suche in Text und Markierung Java Basics - Anfänger-Themen 14
H Suche in einem Text Java Basics - Anfänger-Themen 17
H Erste Schritte Binäre Suche Java Basics - Anfänger-Themen 37
J Suche simples Beispiel für die EOFException Java Basics - Anfänger-Themen 1
H Rekursion Binäre Suche Java Basics - Anfänger-Themen 2
L Binäre Suche Java Basics - Anfänger-Themen 2
L Linerae Suche in einem sortierten Array Java Basics - Anfänger-Themen 2
N Array, lineare Suche, binäre Suche, Programm bleibt unerwartet stehen... Java Basics - Anfänger-Themen 6
I Innerhalb einer Methode suchen und hinzufügen. Neues Objekt in Suche dann? Java Basics - Anfänger-Themen 8
B Binäre Suche - Junit Test Java Basics - Anfänger-Themen 6
L Einfache Lineare Suche Java Basics - Anfänger-Themen 7
J Binäre Suche eines Array Java Basics - Anfänger-Themen 5
M Methoden Binäre Suche als rekursive Variante Java Basics - Anfänger-Themen 5
D Suche nach der Anzahl von Zonen zwischen zwei Punkten Java Basics - Anfänger-Themen 2
M Benutzerdefinierte Suche in einem String - outofbounds Java Basics - Anfänger-Themen 7
X Best Practice SUCHE ein gutes Javabuch! (kein Anfang von 0) Java Basics - Anfänger-Themen 5
B Binäre Suche in einem String Array Java Basics - Anfänger-Themen 10
A Heap Space Error bei rekursiver Suche in Dateien trotz nur einer Zeile im Speicher Java Basics - Anfänger-Themen 26
M Rekursive Suche in einem Feld Java Basics - Anfänger-Themen 11
S Suche richtigen Typ für Variabel mit den Werten (neu, gebraucht, beschädigt) Java Basics - Anfänger-Themen 7
M Best Practice Programmierstil Graphen-A*-Suche Java Basics - Anfänger-Themen 5
M Suche Hilfe bei sehr kleinen Quelltexten Java Basics - Anfänger-Themen 2
E Suche Klasse die eine Bedinung prüft und einen von zwei Auswahlwerten zurückgibt... Java Basics - Anfänger-Themen 6
D Erste Schritte suche hilfe für db-anbindung Java Basics - Anfänger-Themen 36
S Java Servlet - Suche Java Basics - Anfänger-Themen 1
P Hashing suche Java Basics - Anfänger-Themen 4
K Suche Hilfe bei einfachem Java Code ( Debuggen ) Java Basics - Anfänger-Themen 1
J Variablen Auf der suche nach einem Befehl Java Basics - Anfänger-Themen 2
M Binäre Suche Fehler überall =( Java Basics - Anfänger-Themen 2
Farbenfroh Suche Übungsaufgaben: BinaryTree, Stack Java Basics - Anfänger-Themen 0
D Binärbaum Suche Java Basics - Anfänger-Themen 5
U Vererbung Suche Hilfe anhand eines Bsp. Java Basics - Anfänger-Themen 1
L Suche Programmier-Projekt mit Anleitung Java Basics - Anfänger-Themen 3
A Suche Programmierer für Android App Java Basics - Anfänger-Themen 1
H Suche Vergleichstabelle für die Klassen String und StringBuilder Java Basics - Anfänger-Themen 1
X [SUCHE]Mitentwickler Java Basics - Anfänger-Themen 10
P Methoden suche funktion die char wert ausgibt wenn man numerischen wert und radix angibt Java Basics - Anfänger-Themen 1
D Binare Suche Java Basics - Anfänger-Themen 1
C Erste Schritte Bereich angeben bzw Fehler Suche Java Basics - Anfänger-Themen 6
L Suche in dreidimensionalen Arrays Java Basics - Anfänger-Themen 3
P Lineare Suche im Array Java Basics - Anfänger-Themen 5
X verschachtelte suche Java Basics - Anfänger-Themen 8
T Sortieren/Suche klappt nicht ganz (String Array) Java Basics - Anfänger-Themen 2
S Erste Schritte Suche nach einem guten JAVA-Buch (Definition im Thread) Java Basics - Anfänger-Themen 6
G suche den Begriff & wie programmiere ich sowas (ich ändere den Titel dann) Java Basics - Anfänger-Themen 2
M suche/brauche Links über rein GUI Beispielprogramme Java Basics - Anfänger-Themen 4
I Suche Component welches Map ähnelt Java Basics - Anfänger-Themen 11
D Binäre Suche für Integerarray in rekursiver Funktion Java Basics - Anfänger-Themen 5
G Erste Schritte Suche nach Zeichenkette Java Basics - Anfänger-Themen 26
J Suche Tipps zum erstellen von Algorithmen Java Basics - Anfänger-Themen 5
D Artikel-Suche implementieren Java Basics - Anfänger-Themen 7
S suche nach eclipse plug-in Java Basics - Anfänger-Themen 3
W Compiler-Fehler Binäre Suche Java Basics - Anfänger-Themen 2
R Suche Regex Ausdruck für HTML Java Basics - Anfänger-Themen 11
K Suche geeignete Code-Beispiele Java Basics - Anfänger-Themen 4
P Suche Java Programme mit gutem/anfängertauglichem Quellcode Java Basics - Anfänger-Themen 8
I Suche Compiler in Java SDK Java Basics - Anfänger-Themen 5
R String in Strig Suche Java Basics - Anfänger-Themen 2
M Suche Beispiel-Spiel Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben