/****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. This program is distributed in the hope * * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * * or via info@compiere.org or http://www.compiere.org/license.html * *****************************************************************************/ package org.compiere.util; import java.awt.ComponentOrientation; import java.io.Serializable; import java.text.DateFormat; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.logging.Level; import javax.print.attribute.standard.MediaSize; import org.compiere.model.MLanguage; import org.compiere.print.MPrintPaper; /** * Language Management. * * @author Jorg Janke * @version $Id: Language.java,v 1.2 2006/07/30 00:52:23 jjanke Exp $ */ public class Language implements Serializable { /** * generated serial id */ private static final long serialVersionUID = 7039775951366180267L; /************************************************************************** * Languages * http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt * Countries * http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm *************************************************************************/ /** Base Language */ private static final String AD_Language_en_US = "en_US"; /*** * System Languages.
* If you want to add a language, use the method getLanguage which extends the array **/ private static List s_languages = new ArrayList(); /** Base Language */ private static Language s_baseLanguage = null; private static boolean isBaseLanguageSet = false; static { s_languages.add(new Language ("English", AD_Language_en_US, Locale.US, null, null, MediaSize.NA.LETTER)); s_baseLanguage = s_languages.get(0); } /** Logger */ private static CLogger log = CLogger.getCLogger(Language.class.getName()); /** * Get Number of Languages * @return Language count */ public static int getLanguageCount() { return s_languages.size(); } // getLanguageCount /** * Get Language * @param index index * @return Language */ public static Language getLanguage (int index) { if (index < 0 || index >= s_languages.size()) return s_baseLanguage; return s_languages.get(index); } // getLanguage /** * Get Language.
* If language does not exist, create it on the fly assuming that it is valid * @param langInfo either language (en) or locale (en-US) or display name * @return Name (e.g. Deutsch) */ public synchronized static Language getLanguage (String langInfo) { int idxReplace = -1; String lang = langInfo; if (lang == null || lang.length() == 0) lang = System.getProperty("user.language", ""); // Search existing Languages for (int i = 0; i < s_languages.size(); i++) { if ( lang.equals(s_languages.get(i).getAD_Language()) || lang.equals(s_languages.get(i).getLanguageCode()) || lang.equals(s_languages.get(i).getName())) { if (!s_languages.get(i).m_fromDB && DB.isConnected()) { // if language was not get from DB and now we're connected idxReplace = i; break; } else { return s_languages.get(i); } } } // Create Language on the fly if (lang.length() == 5) // standard format _ { Language ll = null; String language = lang.substring(0,2); String country = lang.substring(3); Locale locale = new Locale(language, country); if (DB.isConnected()) { // first time connected? if (!isBaseLanguageSet) { setBaseLanguage(); } MLanguage dblang = MLanguage.get(Env.getCtx(), langInfo); if (dblang != null) { if (!( language.equals(dblang.getLanguageISO()) && country.equals(dblang.getCountryCode()) ) && dblang.getLanguageISO() != null && dblang.getCountryCode() != null ) { locale = new Locale(dblang.getLanguageISO(), dblang.getCountryCode()); } MediaSize mediaSize = MediaSize.ISO.A4; if (dblang.getAD_PrintPaper_ID() > 0) { MPrintPaper pp = MPrintPaper.get(dblang.getAD_PrintPaper_ID()); mediaSize = pp.getMediaSize(); } ll = new Language(dblang.getPrintName(), langInfo, locale, null, dblang.getDatePattern(), mediaSize); ll.m_fromDB = true; if (dblang.isBaseLanguage()) { idxReplace = 0; if (dblang.isSystemLanguage()) { // base language is uploaded also as System language, don't use base language but the corresponding translation s_baseLanguage = new Language ("no-base", "xx_XX", locale); } else { s_baseLanguage = ll; } } } } if (ll == null) { ll = new Language (lang, lang, locale); } if (log.isLoggable(Level.INFO)) { StringBuilder msglog = new StringBuilder("Adding Language=").append(language).append(", Country=").append(country).append(", Locale=").append(locale); log.info (msglog.toString()); } if (idxReplace >= 0) { s_languages.set(idxReplace, ll); } else { s_languages.add(ll); } return ll; } // Get the default one return s_baseLanguage; } // getLanguage /** * Set base language from AD_Language table */ private static void setBaseLanguage() { isBaseLanguageSet = true; String baselang = DB.getSQLValueStringEx(null, "SELECT AD_Language FROM AD_Language WHERE IsActive='Y' AND IsBaseLanguage = 'Y'"); if (baselang != null) { getLanguage(baselang); } } /** * Set baselang as base language * @param baselang */ public static void setBaseLanguage(String baselang) { Language lang = getLanguage(baselang); s_baseLanguage = lang; } /** * Is it the base language * @param langInfo either language (en) or locale (en-US) or display name * @return true if base language */ public static boolean isBaseLanguage (String langInfo) { if (langInfo == null || langInfo.length() == 0 || langInfo.equals(s_baseLanguage.getName()) || langInfo.equals(s_baseLanguage.getLanguageCode()) || langInfo.equals(s_baseLanguage.getAD_Language())) return true; return false; } // isBaseLanguage /** * Get Base Language * @return Base Language */ public static Language getBaseLanguage() { return s_baseLanguage; } // getBase /** * Get Base Language code. (e.g. en-US) * @return Base Language */ public static String getBaseAD_Language() { return s_baseLanguage.getAD_Language(); } // getBase /** * Get Locale from langInfo * @param langInfo either language (en) or locale (en-US) or display name * @return Locale */ public static Locale getLocale (String langInfo) { return getLanguage(langInfo).getLocale(); } // getLocale /** * Get Language from langInfo * @param langInfo either language (en) or locale (en-US) or display name * @return AD_Language (e.g. en-US) */ public static String getAD_Language (String langInfo) { return getLanguage(langInfo).getAD_Language(); } // getAD_Language /** * Get Language code from locale * @param locale Locale * @return AD_Language (e.g. en-US) */ public static String getAD_Language (Locale locale) { if (locale != null) { for (int i = 0; i < s_languages.size(); i++) { if (locale.getLanguage().equals(s_languages.get(i).getLocale().getLanguage())) return s_languages.get(i).getAD_Language(); } } return s_baseLanguage.getAD_Language(); } // getLocale /** * Get Language Name from langInfo * @param langInfo either language (en) or locale (en-US) or display name * @return Language Name (e.g. English) */ public static String getName (String langInfo) { return getLanguage(langInfo).getName(); } // getAD_Language /** * Returns true if Decimal Point (not comma) * @param langInfo either language (en) or locale (en-US) or display name * @return use of decimal point */ public static boolean isDecimalPoint(String langInfo) { return getLanguage(langInfo).isDecimalPoint(); } // getAD_Language /** * Get Display names of supported languages * @return Array of Language names */ public static String[] getNames() { String[] retValue = new String[s_languages.size()]; for (int i = 0; i < s_languages.size(); i++) retValue[i] = s_languages.get(i).getName(); return retValue; } // getNames /** * Get Current Login Language * @return login language */ public static Language getLoginLanguage () { return Env.getLanguage(Env.getCtx()); } // getLanguage /** * Set Current Login Language * @param language language */ public static void setLoginLanguage (Language language) { if (language != null) { Env.setContext(Env.getCtx(), Env.LANGUAGE, language.getAD_Language()); if (log.isLoggable(Level.CONFIG)) log.config(language.toString()); } } // setLanguage /** * Define Language * @param name - displayed value, e.g. English * @param AD_Language - the code of system supported language, e.g. en_US * (might be different than Locale - i.e. if the system does not support the language) * @param locale - the Locale, e.g. Locale.US * @param decimalPoint true if Decimal Point - if null, derived from Locale * @param javaDatePattern Java date pattern as not all locales are defined - if null, derived from Locale * @param mediaSize default media size */ public Language (String name, String AD_Language, Locale locale, Boolean decimalPoint, String javaDatePattern, MediaSize mediaSize) { if (name == null || AD_Language == null || locale == null) throw new IllegalArgumentException ("Language - parameter is null"); m_name = name; m_AD_Language = AD_Language; m_locale = locale; // m_decimalPoint = decimalPoint; setDateFormat (javaDatePattern); setMediaSize (mediaSize); } // Language /** * Define Language with AD_Language and default decimal point and date format * @param name - displayed value, e.g. English * @param AD_Language - the code of system supported language, e.g. en_US * (might be different than Locale - i.e. if the system does not support the language) * @param locale - the Locale, e.g. Locale.US */ public Language (String name, String AD_Language, Locale locale) { this (name, AD_Language, locale, null, null, null); } // Language /** * Copy constructor * @param copy */ public Language(Language copy) { this.m_AD_Language = copy.m_AD_Language; this.m_dateFormat = copy.m_dateFormat; this.m_dbDateFormat = copy.m_dbDateFormat; this.m_decimalPoint = copy.m_decimalPoint; this.m_fromDB = copy.m_fromDB; this.m_leftToRight = copy.m_leftToRight; this.m_locale = copy.m_locale; this.m_mediaSize = copy.m_mediaSize; this.m_name = copy.m_name; } /** Name */ private String m_name; /** Language (key) */ private String m_AD_Language; /** Locale */ private Locale m_locale; // private Boolean m_decimalPoint; private Boolean m_leftToRight; private SimpleDateFormat m_dateFormat; private String m_dbDateFormat; private MediaSize m_mediaSize = MediaSize.ISO.A4; private boolean m_fromDB = false; /** * Get Language Name. * e.g. English * @return name */ public String getName() { return m_name; } // getName /** * Get Application Dictionary Language (system supported). * e.g. en-US * @return AD_Language */ public String getAD_Language() { return m_AD_Language; } // getAD_Language /** * Set Application Dictionary Language (system supported). * @param AD_Language e.g. en-US */ public void setAD_Language (String AD_Language) { if (AD_Language != null) { m_AD_Language = AD_Language; if (log.isLoggable(Level.CONFIG)) log.config(toString()); } } // getAD_Language /** * Get Locale * @return locale */ public Locale getLocale() { return m_locale; } // getLocale /** * Overwrite Locale * @param locale locale */ public void setLocale (Locale locale) { if (locale == null) return; m_locale = locale; m_decimalPoint = null; // reset } // getLocale /** * Get Language Code. * e.g. en - derived from Locale * @return language code */ public String getLanguageCode() { return m_locale.getLanguage(); } // getLanguageCode /** * Component orientation is Left To Right * @return true if left-to-right */ public boolean isLeftToRight() { if (m_leftToRight == null) // returns true if language not iw, ar, fa, ur m_leftToRight = Boolean.valueOf(ComponentOrientation.getOrientation(m_locale).isLeftToRight()); return m_leftToRight.booleanValue(); } // isLeftToRight /** * Returns true if Decimal Point (not comma) * @return use of decimal point */ public boolean isDecimalPoint() { if (m_decimalPoint == null) { DecimalFormatSymbols dfs = new DecimalFormatSymbols(m_locale); m_decimalPoint = Boolean.valueOf(dfs.getDecimalSeparator() == '.'); } return m_decimalPoint.booleanValue(); } // isDecimalPoint /** * Is This the Base Language * @return true if base Language */ public boolean isBaseLanguage() { return this.equals(getBaseLanguage()); } // isBaseLanguage /** * Set Date Format Pattern.
* The date format is not checked for correctness * @param javaDatePattern for details see java.text.SimpleDateFormat, * format must be able to be converted to database date format by * using the upper case function. * It also must have leading zero for day and month. */ public synchronized void setDateFormat (String javaDatePattern) { if (javaDatePattern == null) return; m_dateFormat = (SimpleDateFormat)DateFormat.getDateInstance (DateFormat.SHORT, m_locale); try { m_dateFormat.applyPattern(javaDatePattern); } catch (Exception e) { log.severe(javaDatePattern + " - " + e); m_dateFormat = null; } } // setDateFormat /** * Get (Short) Date Format. * @return date format MM/dd/yyyy - dd.MM.yyyy */ public synchronized SimpleDateFormat getDateFormat() { if (m_dateFormat == null) { m_dateFormat = (SimpleDateFormat)DateFormat.getDateInstance (DateFormat.SHORT, m_locale); String sFormat = m_dateFormat.toPattern(); // some short formats have only one M and/or d (e.g. ths US) if (sFormat.indexOf("MM") == -1 || sFormat.indexOf("dd") == -1) { sFormat = sFormat.replaceFirst("d+", "dd"); sFormat = sFormat.replaceFirst("M+", "MM"); // log.finer(sFormat + " => " + nFormat); m_dateFormat.applyPattern(sFormat); } // Unknown short format => use JDBC if (m_dateFormat.toPattern().length() != 8) m_dateFormat.applyPattern("yyyy-MM-dd"); // 4 digit year if (m_dateFormat.toPattern().indexOf("yyyy") == -1) { sFormat = m_dateFormat.toPattern(); StringBuilder nFormat = new StringBuilder(); for (int i = 0; i < sFormat.length(); i++) { if (sFormat.charAt(i) == 'y') nFormat.append("yy"); else nFormat.append(sFormat.charAt(i)); } m_dateFormat.applyPattern(nFormat.toString()); } m_dateFormat.setLenient(true); } return (SimpleDateFormat) m_dateFormat.clone(); } // getDateFormat /** * Get Date Time Format. * @return Date Time format MMM d, yyyy h:mm:ss a z -or- dd.MM.yyyy HH:mm:ss z * -or- j nnn aaaa, H' ?????? 'm' ????' */ public SimpleDateFormat getDateTimeFormat() { SimpleDateFormat retValue = (SimpleDateFormat)DateFormat.getDateTimeInstance (DateFormat.MEDIUM, DateFormat.LONG, m_locale); return retValue; } // getDateTimeFormat /** * Get Time Format. * @return Time format h:mm:ss z or HH:mm:ss z */ public SimpleDateFormat getTimeFormat() { return (SimpleDateFormat)DateFormat.getTimeInstance (DateFormat.LONG, m_locale); } // getTimeFormat /** * Get Database Date Pattern.
* Derive from date pattern (make upper case and replace month as word with MM) * @return date pattern */ public String getDBdatePattern() { if (m_dbDateFormat == null) { m_dbDateFormat = getDateFormat().toPattern().toUpperCase(m_locale); // IDEMPIERE-3888 - temporary hack - a better solution would be to implement AD_Language.DBDatePattern m_dbDateFormat = m_dbDateFormat.replaceFirst("MMM*", "MM"); } return m_dbDateFormat; } // getDBdatePattern /** * Get default MediaSize * @return media size */ public MediaSize getMediaSize() { return m_mediaSize; } // getMediaSize /** * Set default MediaSize * @param size media size */ public void setMediaSize (MediaSize size) { if (size != null) m_mediaSize = size; } // setMediaSize /** * String Representation * @return string representation */ @Override public String toString() { StringBuilder sb = new StringBuilder("Language=["); sb.append(m_name).append(",Locale=").append(m_locale.toString()) .append(",AD_Language=").append(m_AD_Language) .append(",DatePattern=").append(getDBdatePattern()) .append(",DecimalPoint=").append(isDecimalPoint()) .append("]"); return sb.toString(); } // toString /** * Hash Code * @return hashcode */ @Override public int hashCode() { return m_AD_Language.hashCode(); } // hashcode /** * Equals. * Two languages are equal, if they have the same AD_Language * @param obj compare * @return true if AD_Language is the same */ @Override public boolean equals(Object obj) { if (obj instanceof Language) { Language cmp = (Language)obj; if (cmp.getAD_Language().equals(m_AD_Language)) return true; } return false; } // equals } // Language