package com.limegroup.gnutella.gui; import java.awt.Font; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import com.limegroup.gnutella.settings.ApplicationSettings; import com.limegroup.gnutella.util.CommonUtils; /** * Contains the information about a single language. * * Also contains factory methods for retrieving supported languages. */ public class LanguageInfo { private final String languageCode; private final String countryCode; private final String variantCode; private final String display; private final String countryName; private final String variantName; /** * Constructs a new LanguageInfo object with the given * languageCode, countryCode, variantCode, * languageName, countryName, and variantName. */ public LanguageInfo(String lc, String cc, String vc, String ln, String cn, String vn) { languageCode = lc.trim(); countryCode = cc.trim(); variantCode = vc.trim(); display = ln.trim(); countryName = cn.trim(); variantName = vn.trim(); } /** * Returns true if the languageCode, countryCode & variantCode * match the String[] */ public boolean matches(String[] codes) { String lc = codes[0]; String cc = codes[1]; String vc = codes[2]; if(lc == null) lc = ""; if(cc == null) cc = ""; if(vc == null) vc = ""; return languageCode.equals(lc) && countryCode.equals(cc) && variantCode.equals(vc); } /** * Determines whether or not this language is the current language. */ public boolean isCurrent() { String lc = ApplicationSettings.LANGUAGE.getValue(); String cc = ApplicationSettings.COUNTRY.getValue(); String lv = ApplicationSettings.LOCALE_VARIANT.getValue(); boolean isLV, isCC, isLC; isLV = lv == null || lv.equals("") || lv.equals(variantCode); isCC = cc == null || cc.equals("") || cc.equals(countryCode); isLC = ((lc == null || lc.equals("")) && languageCode.equals("en")) || lc.equals(languageCode); return isLV && isCC && isLC; } /** * Applies this language code to be the new language of the program. */ public void apply() { ApplicationSettings.LANGUAGE.setValue(languageCode); ApplicationSettings.COUNTRY.setValue(countryCode); ApplicationSettings.LOCALE_VARIANT.setValue(variantCode); GUIMediator.resetLocale(); } /** * Returns a description of this language. * If the variantName is not 'international' or '', then * the display is: * languageName, variantName (countryName) * Otherwise, the display is: * languageName (countryName) */ public String toString() { if( variantName != null && !variantName.toLowerCase().equals("international") && !variantName.equals("") ) return display + ", " + variantName + " (" + countryName + ")"; else return display + " (" + countryName + ")"; } /** * Returns an array of supported language as a LanguageInfo[], * always having the English language as the first element. * * This will only include languages that can be displayed using * the given font. If the font is null, all languages are returned. */ public static LanguageInfo[] getLanguages(Font font) { List langs = null; if( CommonUtils.isTestingVersion() ) langs = getLanguagesFromDisk(); else langs = getLanguagesFromJar(); langs.add(0, new LanguageInfo("en", "", "", "English", "United States", "")); // Remove languages that cannot be displayed using this font. if(font != null && !CommonUtils.isMacOSX()) { for(Iterator i = langs.iterator(); i.hasNext(); ) { if(!GUIUtils.canDisplay(font, i.next().toString())) i.remove(); } } return (LanguageInfo[])langs.toArray(new LanguageInfo[langs.size()]); } /** * Returns the languages as found from the classpath in MessagesBundles.jar */ private static List getLanguagesFromJar() { List langs = new LinkedList(); File jar = CommonUtils.getResourceFile("MessagesBundles.jar"); if(!jar.exists()) return langs; ZipFile zip = null; try { zip = new ZipFile(jar); Enumeration entries = zip.entries(); while(entries.hasMoreElements()) { String name = ((ZipEntry)entries.nextElement()).getName(); if(!name.startsWith("MessagesBundle_") || name.indexOf("_en") != -1 || !name.endsWith(".properties")) continue; InputStream in = CommonUtils.getResourceStream(name); loadFile(langs, in); } } catch(IOException e) { // oh well. } finally { if(zip != null) try{ zip.close(); } catch(IOException ioe) {} } return langs; } /** * Returns the languages as found in the * ../lib/messagebundles/MessagesBundle_*.properties files. */ private static List getLanguagesFromDisk() { List langs = new LinkedList(); File lib = new File("../lib/messagebundles"); if(!lib.isDirectory()) return langs; String[] files = lib.list(); for(int i = 0; i < files.length; i++) { if(!files[i].startsWith("MessagesBundle_") || files[i].indexOf("_en") != -1 || !files[i].endsWith(".properties")) continue; try { InputStream in = new FileInputStream(new File(lib, files[i])); loadFile(langs, in); } catch(FileNotFoundException fnfe) { // oh well. } } return langs; } /** * Loads a single file into a List. */ private static void loadFile(List langs, InputStream in) { Properties p = new Properties(); try { in = new BufferedInputStream(in); p.load(in); String lc = p.getProperty("LOCALE_LANGUAGE_CODE"); String cc = p.getProperty("LOCALE_COUNTRY_CODE"); String vc = p.getProperty("LOCALE_VARIANT_CODE"); String ln = p.getProperty("LOCALE_LANGUAGE_NAME"); String cn = p.getProperty("LOCALE_COUNTRY_NAME"); String vn = p.getProperty("LOCALE_VARIANT_NAME"); langs.add( new LanguageInfo(lc, cc, vc, ln, cn, vn) ); // all exceptions are ignorable } catch(IOException ignored) { } catch(IllegalArgumentException ignored) { } catch(NullPointerException ignored) { } finally { if( in != null ) try { in.close(); } catch(IOException ioe) {} } } }