GNU Classpath (0.92) | |
Frames | No Frames |
1: /* Locale.java -- i18n locales 2: Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.util; 40: 41: import gnu.classpath.SystemProperties; 42: import gnu.java.locale.LocaleHelper; 43: 44: import java.io.IOException; 45: import java.io.ObjectInputStream; 46: import java.io.ObjectOutputStream; 47: import java.io.Serializable; 48: 49: /** 50: * Locales represent a specific country and culture. Classes which can be 51: * passed a Locale object tailor their information for a given locale. For 52: * instance, currency number formatting is handled differently for the USA 53: * and France. 54: * 55: * <p>Locales are made up of a language code, a country code, and an optional 56: * set of variant strings. Language codes are represented by 57: * <a href="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt"> 58: * ISO 639:1988</a> w/ additions from ISO 639/RA Newsletter No. 1/1989 59: * and a decision of the Advisory Committee of ISO/TC39 on August 8, 1997. 60: * 61: * <p>Country codes are represented by 62: * <a href="http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html"> 63: * ISO 3166</a>. Variant strings are vendor and browser specific. Standard 64: * variant strings include "POSIX" for POSIX, "WIN" for MS-Windows, and 65: * "MAC" for Macintosh. When there is more than one variant string, they must 66: * be separated by an underscore (U+005F). 67: * 68: * <p>The default locale is determined by the values of the system properties 69: * user.language, user.country (or user.region), and user.variant, defaulting 70: * to "en_US". Note that the locale does NOT contain the conversion and 71: * formatting capabilities (for that, use ResourceBundle and java.text). 72: * Rather, it is an immutable tag object for identifying a given locale, which 73: * is referenced by these other classes when they must make locale-dependent 74: * decisions. 75: * 76: * @see ResourceBundle 77: * @see java.text.Format 78: * @see java.text.NumberFormat 79: * @see java.text.Collator 80: * @author Jochen Hoenicke 81: * @author Paul Fisher 82: * @author Eric Blake (ebb9@email.byu.edu) 83: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 84: * @since 1.1 85: * @status updated to 1.4 86: */ 87: public final class Locale implements Serializable, Cloneable 88: { 89: /** Locale which represents the English language. */ 90: public static final Locale ENGLISH = getLocale("en"); 91: 92: /** Locale which represents the French language. */ 93: public static final Locale FRENCH = getLocale("fr"); 94: 95: /** Locale which represents the German language. */ 96: public static final Locale GERMAN = getLocale("de"); 97: 98: /** Locale which represents the Italian language. */ 99: public static final Locale ITALIAN = getLocale("it"); 100: 101: /** Locale which represents the Japanese language. */ 102: public static final Locale JAPANESE = getLocale("ja"); 103: 104: /** Locale which represents the Korean language. */ 105: public static final Locale KOREAN = getLocale("ko"); 106: 107: /** Locale which represents the Chinese language. */ 108: public static final Locale CHINESE = getLocale("zh"); 109: 110: /** Locale which represents the Chinese language as used in China. */ 111: public static final Locale SIMPLIFIED_CHINESE = getLocale("zh", "CN"); 112: 113: /** 114: * Locale which represents the Chinese language as used in Taiwan. 115: * Same as TAIWAN Locale. 116: */ 117: public static final Locale TRADITIONAL_CHINESE = getLocale("zh", "TW"); 118: 119: /** Locale which represents France. */ 120: public static final Locale FRANCE = getLocale("fr", "FR"); 121: 122: /** Locale which represents Germany. */ 123: public static final Locale GERMANY = getLocale("de", "DE"); 124: 125: /** Locale which represents Italy. */ 126: public static final Locale ITALY = getLocale("it", "IT"); 127: 128: /** Locale which represents Japan. */ 129: public static final Locale JAPAN = getLocale("ja", "JP"); 130: 131: /** Locale which represents Korea. */ 132: public static final Locale KOREA = getLocale("ko", "KR"); 133: 134: /** 135: * Locale which represents China. 136: * Same as SIMPLIFIED_CHINESE Locale. 137: */ 138: public static final Locale CHINA = SIMPLIFIED_CHINESE; 139: 140: /** 141: * Locale which represents the People's Republic of China. 142: * Same as CHINA Locale. 143: */ 144: public static final Locale PRC = CHINA; 145: 146: /** 147: * Locale which represents Taiwan. 148: * Same as TRADITIONAL_CHINESE Locale. 149: */ 150: public static final Locale TAIWAN = TRADITIONAL_CHINESE; 151: 152: /** Locale which represents the United Kingdom. */ 153: public static final Locale UK = getLocale("en", "GB"); 154: 155: /** Locale which represents the United States. */ 156: public static final Locale US = getLocale("en", "US"); 157: 158: /** Locale which represents the English speaking portion of Canada. */ 159: public static final Locale CANADA = getLocale("en", "CA"); 160: 161: /** Locale which represents the French speaking portion of Canada. */ 162: public static final Locale CANADA_FRENCH = getLocale("fr", "CA"); 163: 164: /** 165: * Compatible with JDK 1.1+. 166: */ 167: private static final long serialVersionUID = 9149081749638150636L; 168: 169: /** 170: * The language code, as returned by getLanguage(). 171: * 172: * @serial the languange, possibly "" 173: */ 174: private String language; 175: 176: /** 177: * The country code, as returned by getCountry(). 178: * 179: * @serial the country, possibly "" 180: */ 181: private String country; 182: 183: /** 184: * The variant code, as returned by getVariant(). 185: * 186: * @serial the variant, possibly "" 187: */ 188: private String variant; 189: 190: /** 191: * This is the cached hashcode. When writing to stream, we write -1. 192: * 193: * @serial should be -1 in serial streams 194: */ 195: private transient int hashcode; 196: 197: /** 198: * Array storing all available locales. 199: */ 200: private static transient Locale[] availableLocales; 201: 202: /** 203: * Locale cache. Only created locale objects are stored. 204: * Contains all supported locales when getAvailableLocales() 205: * got called. 206: */ 207: private static transient HashMap localeMap; 208: 209: /** 210: * The default locale. Except for during bootstrapping, this should never be 211: * null. Note the logic in the main constructor, to detect when 212: * bootstrapping has completed. 213: */ 214: private static Locale defaultLocale; 215: 216: static { 217: String language = SystemProperties.getProperty("user.language", "en"); 218: String country = SystemProperties.getProperty("user.country", "US"); 219: String region = SystemProperties.getProperty("user.region", null); 220: String variant = SystemProperties.getProperty("user.variant", ""); 221: 222: defaultLocale = getLocale(language, 223: (region != null) ? region : country, 224: variant); 225: } 226: 227: /** 228: * Array storing all the available two-letter ISO639 languages. 229: */ 230: private static transient String[] languageCache; 231: 232: /** 233: * Array storing all the available two-letter ISO3166 country codes. 234: */ 235: private static transient String[] countryCache; 236: 237: /** 238: * Retrieves the locale with the specified language from the cache. 239: * 240: * @param language the language of the locale to retrieve. 241: * @return the locale. 242: */ 243: private static Locale getLocale(String language) 244: { 245: return getLocale(language, "", ""); 246: } 247: 248: /** 249: * Retrieves the locale with the specified language and country 250: * from the cache. 251: * 252: * @param language the language of the locale to retrieve. 253: * @param country the country of the locale to retrieve. 254: * @return the locale. 255: */ 256: private static Locale getLocale(String language, String country) 257: { 258: return getLocale(language, country, ""); 259: } 260: 261: /** 262: * Retrieves the locale with the specified language, country 263: * and variant from the cache. 264: * 265: * @param language the language of the locale to retrieve. 266: * @param country the country of the locale to retrieve. 267: * @param variant the variant of the locale to retrieve. 268: * @return the locale. 269: */ 270: private static Locale getLocale(String language, String country, String variant) 271: { 272: if (localeMap == null) 273: localeMap = new HashMap(256); 274: 275: String name = language + "_" + country + "_" + variant; 276: Locale locale = (Locale) localeMap.get(name); 277: 278: if (locale == null) 279: { 280: locale = new Locale(language, country, variant); 281: localeMap.put(name, locale); 282: } 283: 284: return locale; 285: } 286: 287: /** 288: * Convert new iso639 codes to the old ones. 289: * 290: * @param language the language to check 291: * @return the appropriate code 292: */ 293: private String convertLanguage(String language) 294: { 295: if (language.equals("")) 296: return language; 297: language = language.toLowerCase(); 298: int index = "he,id,yi".indexOf(language); 299: if (index != -1) 300: return "iw,in,ji".substring(index, index + 2); 301: return language; 302: } 303: 304: /** 305: * Creates a new locale for the given language and country. 306: * 307: * @param language lowercase two-letter ISO-639 A2 language code 308: * @param country uppercase two-letter ISO-3166 A2 contry code 309: * @param variant vendor and browser specific 310: * @throws NullPointerException if any argument is null 311: */ 312: public Locale(String language, String country, String variant) 313: { 314: // During bootstrap, we already know the strings being passed in are 315: // the correct capitalization, and not null. We can't call 316: // String.toUpperCase during this time, since that depends on the 317: // default locale. 318: if (defaultLocale != null) 319: { 320: language = convertLanguage(language).intern(); 321: country = country.toUpperCase().intern(); 322: variant = variant.intern(); 323: } 324: this.language = language; 325: this.country = country; 326: this.variant = variant; 327: hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode(); 328: } 329: 330: /** 331: * Creates a new locale for the given language and country. 332: * 333: * @param language lowercase two-letter ISO-639 A2 language code 334: * @param country uppercase two-letter ISO-3166 A2 country code 335: * @throws NullPointerException if either argument is null 336: */ 337: public Locale(String language, String country) 338: { 339: this(language, country, ""); 340: } 341: 342: /** 343: * Creates a new locale for a language. 344: * 345: * @param language lowercase two-letter ISO-639 A2 language code 346: * @throws NullPointerException if either argument is null 347: * @since 1.4 348: */ 349: public Locale(String language) 350: { 351: this(language, "", ""); 352: } 353: 354: /** 355: * Returns the default Locale. The default locale is generally once set 356: * on start up and then never changed. Normally you should use this locale 357: * for everywhere you need a locale. The initial setting matches the 358: * default locale, the user has chosen. 359: * 360: * @return the default locale for this virtual machine 361: */ 362: public static Locale getDefault() 363: { 364: return defaultLocale; 365: } 366: 367: /** 368: * Changes the default locale. Normally only called on program start up. 369: * Note that this doesn't change the locale for other programs. This has 370: * a security check, 371: * <code>PropertyPermission("user.language", "write")</code>, because of 372: * its potential impact to running code. 373: * 374: * @param newLocale the new default locale 375: * @throws NullPointerException if newLocale is null 376: * @throws SecurityException if permission is denied 377: */ 378: public static void setDefault(Locale newLocale) 379: { 380: if (newLocale == null) 381: throw new NullPointerException(); 382: SecurityManager sm = System.getSecurityManager(); 383: if (sm != null) 384: sm.checkPermission(new PropertyPermission("user.language", "write")); 385: defaultLocale = newLocale; 386: } 387: 388: /** 389: * Returns the list of available locales. 390: * 391: * @return the installed locales 392: */ 393: public static synchronized Locale[] getAvailableLocales() 394: { 395: if (availableLocales == null) 396: { 397: int len = LocaleHelper.getLocaleCount(); 398: availableLocales = new Locale[len]; 399: 400: for (int i = 0; i < len; i++) 401: { 402: String language; 403: String country = ""; 404: String variant = ""; 405: String name = LocaleHelper.getLocaleName(i); 406: 407: language = name.substring(0, 2); 408: 409: if (name.length() > 2) 410: country = name.substring(3); 411: 412: int index = country.indexOf("_"); 413: if (index > 0) 414: { 415: variant = country.substring(index + 1); 416: country = country.substring(0, index - 1); 417: } 418: 419: availableLocales[i] = getLocale(language, country, variant); 420: } 421: } 422: 423: return (Locale[]) availableLocales.clone(); 424: } 425: 426: /** 427: * Returns a list of all 2-letter uppercase country codes as defined 428: * in ISO 3166. 429: * 430: * @return a list of acceptable country codes 431: */ 432: public static String[] getISOCountries() 433: { 434: if (countryCache == null) 435: { 436: countryCache = getISOStrings("territories"); 437: } 438: 439: return (String[]) countryCache.clone(); 440: } 441: 442: /** 443: * Returns a list of all 2-letter lowercase language codes as defined 444: * in ISO 639 (both old and new variant). 445: * 446: * @return a list of acceptable language codes 447: */ 448: public static String[] getISOLanguages() 449: { 450: if (languageCache == null) 451: { 452: languageCache = getISOStrings("languages"); 453: } 454: return (String[]) languageCache.clone(); 455: } 456: 457: /** 458: * Returns the set of keys from the specified resource hashtable, filtered 459: * so that only two letter strings are returned. 460: * 461: * @param tableName the name of the table from which to retrieve the keys. 462: * @return an array of two-letter strings. 463: */ 464: private static String[] getISOStrings(String tableName) 465: { 466: int count = 0; 467: ResourceBundle bundle = 468: ResourceBundle.getBundle("gnu.java.locale.LocaleInformation"); 469: Enumeration e = bundle.getKeys(); 470: ArrayList tempList = new ArrayList(); 471: 472: while (e.hasMoreElements()) 473: { 474: String key = (String) e.nextElement(); 475: 476: if (key.startsWith(tableName + ".")) 477: { 478: String str = key.substring(tableName.length() + 1); 479: 480: if (str.length() == 2 481: && Character.isLetter(str.charAt(0)) 482: && Character.isLetter(str.charAt(1))) 483: { 484: tempList.add(str); 485: ++count; 486: } 487: } 488: } 489: 490: String[] strings = new String[count]; 491: 492: for (int a = 0; a < count; ++a) 493: strings[a] = (String) tempList.get(a); 494: 495: return strings; 496: } 497: 498: /** 499: * Returns the language code of this locale. Some language codes have changed 500: * as ISO 639 has evolved; this returns the old name, even if you built 501: * the locale with the new one. 502: * 503: * @return language code portion of this locale, or an empty String 504: */ 505: public String getLanguage() 506: { 507: return language; 508: } 509: 510: /** 511: * Returns the country code of this locale. 512: * 513: * @return country code portion of this locale, or an empty String 514: */ 515: public String getCountry() 516: { 517: return country; 518: } 519: 520: /** 521: * Returns the variant code of this locale. 522: * 523: * @return the variant code portion of this locale, or an empty String 524: */ 525: public String getVariant() 526: { 527: return variant; 528: } 529: 530: /** 531: * Gets the string representation of the current locale. This consists of 532: * the language, the country, and the variant, separated by an underscore. 533: * The variant is listed only if there is a language or country. Examples: 534: * "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC". 535: * 536: * @return the string representation of this Locale 537: * @see #getDisplayName() 538: */ 539: public String toString() 540: { 541: if (language.length() == 0 && country.length() == 0) 542: return ""; 543: else if (country.length() == 0 && variant.length() == 0) 544: return language; 545: StringBuffer result = new StringBuffer(language); 546: result.append('_').append(country); 547: if (variant.length() != 0) 548: result.append('_').append(variant); 549: return result.toString(); 550: } 551: 552: /** 553: * Returns the three-letter ISO language abbrevation of this locale. 554: * 555: * @throws MissingResourceException if the three-letter code is not known 556: */ 557: public String getISO3Language() 558: { 559: // We know all strings are interned so we can use '==' for better performance. 560: if (language == "") 561: return ""; 562: int index 563: = ("aa,ab,af,am,ar,as,ay,az,ba,be,bg,bh,bi,bn,bo,br,ca,co,cs,cy,da," 564: + "de,dz,el,en,eo,es,et,eu,fa,fi,fj,fo,fr,fy,ga,gd,gl,gn,gu,ha,iw," 565: + "hi,hr,hu,hy,ia,in,ie,ik,in,is,it,iu,iw,ja,ji,jw,ka,kk,kl,km,kn," 566: + "ko,ks,ku,ky,la,ln,lo,lt,lv,mg,mi,mk,ml,mn,mo,mr,ms,mt,my,na,ne," 567: + "nl,no,oc,om,or,pa,pl,ps,pt,qu,rm,rn,ro,ru,rw,sa,sd,sg,sh,si,sk," 568: + "sl,sm,sn,so,sq,sr,ss,st,su,sv,sw,ta,te,tg,th,ti,tk,tl,tn,to,tr," 569: + "ts,tt,tw,ug,uk,ur,uz,vi,vo,wo,xh,ji,yo,za,zh,zu") 570: .indexOf(language); 571: 572: if (index % 3 != 0 || language.length() != 2) 573: throw new MissingResourceException 574: ("Can't find ISO3 language for " + language, 575: "java.util.Locale", language); 576: 577: // Don't read this aloud. These are the three letter language codes. 578: return 579: ("aarabkaframharaasmaymazebakbelbulbihbisbenbodbrecatcoscescymdandeu" 580: + "dzoellengepospaesteusfasfinfijfaofrafrygaigdhglggrngujhauhebhinhrv" 581: + "hunhyeinaindileipkindislitaikuhebjpnyidjawkatkazkalkhmkankorkaskur" 582: + "kirlatlinlaolitlavmlgmrimkdmalmonmolmarmsamltmyanaunepnldnorociorm" 583: + "oripanpolpusporquerohrunronruskinsansndsagsrpsinslkslvsmosnasomsqi" 584: + "srpsswsotsunsweswatamteltgkthatirtuktgltsntonturtsotattwiuigukrurd" 585: + "uzbvievolwolxhoyidyorzhazhozul") 586: .substring(index, index + 3); 587: } 588: 589: /** 590: * Returns the three-letter ISO country abbrevation of the locale. 591: * 592: * @throws MissingResourceException if the three-letter code is not known 593: */ 594: public String getISO3Country() 595: { 596: // We know all strings are interned so we can use '==' for better performance. 597: if (country == "") 598: return ""; 599: int index 600: = ("AD,AE,AF,AG,AI,AL,AM,AN,AO,AQ,AR,AS,AT,AU,AW,AZ,BA,BB,BD,BE,BF," 601: + "BG,BH,BI,BJ,BM,BN,BO,BR,BS,BT,BV,BW,BY,BZ,CA,CC,CF,CG,CH,CI,CK," 602: + "CL,CM,CN,CO,CR,CU,CV,CX,CY,CZ,DE,DJ,DK,DM,DO,DZ,EC,EE,EG,EH,ER," 603: + "ES,ET,FI,FJ,FK,FM,FO,FR,FX,GA,GB,GD,GE,GF,GH,GI,GL,GM,GN,GP,GQ," 604: + "GR,GS,GT,GU,GW,GY,HK,HM,HN,HR,HT,HU,ID,IE,IL,IN,IO,IQ,IR,IS,IT," 605: + "JM,JO,JP,KE,KG,KH,KI,KM,KN,KP,KR,KW,KY,KZ,LA,LB,LC,LI,LK,LR,LS," 606: + "LT,LU,LV,LY,MA,MC,MD,MG,MH,MK,ML,MM,MN,MO,MP,MQ,MR,MS,MT,MU,MV," 607: + "MW,MX,MY,MZ,NA,NC,NE,NF,NG,NI,NL,NO,NP,NR,NU,NZ,OM,PA,PE,PF,PG," 608: + "PH,PK,PL,PM,PN,PR,PT,PW,PY,QA,RE,RO,RU,RW,SA,SB,SC,SD,SE,SG,SH," 609: + "SI,SJ,SK,SL,SM,SN,SO,SR,ST,SV,SY,SZ,TC,TD,TF,TG,TH,TJ,TK,TM,TN," 610: + "TO,TP,TR,TT,TV,TW,TZ,UA,UG,UM,US,UY,UZ,VA,VC,VE,VG,VI,VN,VU,WF," 611: + "WS,YE,YT,YU,ZA,ZM,ZR,ZW") 612: .indexOf(country); 613: 614: if (index % 3 != 0 || country.length() != 2) 615: throw new MissingResourceException 616: ("Can't find ISO3 country for " + country, 617: "java.util.Locale", country); 618: 619: // Don't read this aloud. These are the three letter country codes. 620: return 621: ("ANDAREAFGATGAIAALBARMANTAGOATAARGASMAUTAUSABWAZEBIHBRBBGDBELBFABGR" 622: + "BHRBDIBENBMUBRNBOLBRABHSBTNBVTBWABLRBLZCANCCKCAFCOGCHECIVCOKCHLCMR" 623: + "CHNCOLCRICUBCPVCXRCYPCZEDEUDJIDNKDMADOMDZAECUESTEGYESHERIESPETHFIN" 624: + "FJIFLKFSMFROFRAFXXGABGBRGRDGEOGUFGHAGIBGRLGMBGINGLPGNQGRCSGSGTMGUM" 625: + "GNBGUYHKGHMDHNDHRVHTIHUNIDNIRLISRINDIOTIRQIRNISLITAJAMJORJPNKENKGZ" 626: + "KHMKIRCOMKNAPRKKORKWTCYMKAZLAOLBNLCALIELKALBRLSOLTULUXLVALBYMARMCO" 627: + "MDAMDGMHLMKDMLIMMRMNGMACMNPMTQMRTMSRMLTMUSMDVMWIMEXMYSMOZNAMNCLNER" 628: + "NFKNGANICNLDNORNPLNRUNIUNZLOMNPANPERPYFPNGPHLPAKPOLSPMPCNPRIPRTPLW" 629: + "PRYQATREUROMRUSRWASAUSLBSYCSDNSWESGPSHNSVNSJMSVKSLESMRSENSOMSURSTP" 630: + "SLVSYRSWZTCATCDATFTGOTHATJKTKLTKMTUNTONTMPTURTTOTUVTWNTZAUKRUGAUMI" 631: + "USAURYUZBVATVCTVENVGBVIRVNMVUTWLFWSMYEMMYTYUGZAFZMBZARZWE") 632: .substring(index, index + 3); 633: } 634: 635: /** 636: * Gets the country name suitable for display to the user, formatted 637: * for the default locale. This has the same effect as 638: * <pre> 639: * getDisplayLanguage(Locale.getDefault()); 640: * </pre> 641: * 642: * @return the language name of this locale localized to the default locale, 643: * with the ISO code as backup 644: */ 645: public String getDisplayLanguage() 646: { 647: return getDisplayLanguage(defaultLocale); 648: } 649: 650: /** 651: * <p> 652: * Gets the name of the language specified by this locale, in a form suitable 653: * for display to the user. If possible, the display name will be localized 654: * to the specified locale. For example, if the locale instance is 655: * <code>Locale.GERMANY</code>, and the specified locale is <code>Locale.UK</code>, 656: * the result would be 'German'. Using the German locale would instead give 657: * 'Deutsch'. If the display name can not be localized to the supplied 658: * locale, it will fall back on other output in the following order: 659: * </p> 660: * <ul> 661: * <li>the display name in the default locale</li> 662: * <li>the display name in English</li> 663: * <li>the ISO code</li> 664: * </ul> 665: * <p> 666: * If the language is unspecified by this locale, then the empty string is 667: * returned. 668: * </p> 669: * 670: * @param inLocale the locale to use for formatting the display string. 671: * @return the language name of this locale localized to the given locale, 672: * with the default locale, English and the ISO code as backups. 673: * @throws NullPointerException if the supplied locale is null. 674: */ 675: public String getDisplayLanguage(Locale inLocale) 676: { 677: try 678: { 679: ResourceBundle res = 680: ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", 681: inLocale, 682: ClassLoader.getSystemClassLoader()); 683: 684: return res.getString("languages." + language); 685: } 686: catch (MissingResourceException e) 687: { 688: return language; 689: } 690: } 691: 692: /** 693: * Returns the country name of this locale localized to the 694: * default locale. If the localized is not found, the ISO code 695: * is returned. This has the same effect as 696: * <pre> 697: * getDisplayCountry(Locale.getDefault()); 698: * </pre> 699: * 700: * @return the country name of this locale localized to the given locale, 701: * with the ISO code as backup 702: */ 703: public String getDisplayCountry() 704: { 705: return getDisplayCountry(defaultLocale); 706: } 707: 708: /** 709: * <p> 710: * Gets the name of the country specified by this locale, in a form suitable 711: * for display to the user. If possible, the display name will be localized 712: * to the specified locale. For example, if the locale instance is 713: * <code>Locale.GERMANY</code>, and the specified locale is <code>Locale.UK</code>, 714: * the result would be 'Germany'. Using the German locale would instead give 715: * 'Deutschland'. If the display name can not be localized to the supplied 716: * locale, it will fall back on other output in the following order: 717: * </p> 718: * <ul> 719: * <li>the display name in the default locale</li> 720: * <li>the display name in English</li> 721: * <li>the ISO code</li> 722: * </ul> 723: * <p> 724: * If the country is unspecified by this locale, then the empty string is 725: * returned. 726: * </p> 727: * 728: * @param inLocale the locale to use for formatting the display string. 729: * @return the country name of this locale localized to the given locale, 730: * with the default locale, English and the ISO code as backups. 731: * @throws NullPointerException if the supplied locale is null. 732: */ 733: public String getDisplayCountry(Locale inLocale) 734: { 735: try 736: { 737: ResourceBundle res = 738: ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", 739: inLocale, 740: ClassLoader.getSystemClassLoader()); 741: 742: return res.getString("territories." + country); 743: } 744: catch (MissingResourceException e) 745: { 746: return country; 747: } 748: } 749: 750: /** 751: * Returns the variant name of this locale localized to the 752: * default locale. If the localized is not found, the variant code 753: * itself is returned. This has the same effect as 754: * <pre> 755: * getDisplayVariant(Locale.getDefault()); 756: * </pre> 757: * 758: * @return the variant code of this locale localized to the given locale, 759: * with the ISO code as backup 760: */ 761: public String getDisplayVariant() 762: { 763: return getDisplayVariant(defaultLocale); 764: } 765: 766: 767: /** 768: * <p> 769: * Gets the name of the variant specified by this locale, in a form suitable 770: * for display to the user. If possible, the display name will be localized 771: * to the specified locale. For example, if the locale instance is a revised 772: * variant, and the specified locale is <code>Locale.UK</code>, the result 773: * would be 'REVISED'. Using the German locale would instead give 774: * 'Revidiert'. If the display name can not be localized to the supplied 775: * locale, it will fall back on other output in the following order: 776: * </p> 777: * <ul> 778: * <li>the display name in the default locale</li> 779: * <li>the display name in English</li> 780: * <li>the ISO code</li> 781: * </ul> 782: * <p> 783: * If the variant is unspecified by this locale, then the empty string is 784: * returned. 785: * </p> 786: * 787: * @param inLocale the locale to use for formatting the display string. 788: * @return the variant name of this locale localized to the given locale, 789: * with the default locale, English and the ISO code as backups. 790: * @throws NullPointerException if the supplied locale is null. 791: */ 792: public String getDisplayVariant(Locale inLocale) 793: { 794: try 795: { 796: ResourceBundle res = 797: ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", 798: inLocale, 799: ClassLoader.getSystemClassLoader()); 800: 801: return res.getString("variants." + variant); 802: } 803: catch (MissingResourceException e) 804: { 805: return variant; 806: } 807: } 808: 809: /** 810: * Gets all local components suitable for display to the user, formatted 811: * for the default locale. For the language component, getDisplayLanguage 812: * is called. For the country component, getDisplayCountry is called. 813: * For the variant set component, getDisplayVariant is called. 814: * 815: * <p>The returned String will be one of the following forms:<br> 816: * <pre> 817: * language (country, variant) 818: * language (country) 819: * language (variant) 820: * country (variant) 821: * language 822: * country 823: * variant 824: * </pre> 825: * 826: * @return String version of this locale, suitable for display to the user 827: */ 828: public String getDisplayName() 829: { 830: return getDisplayName(defaultLocale); 831: } 832: 833: /** 834: * Gets all local components suitable for display to the user, formatted 835: * for a specified locale. For the language component, 836: * getDisplayLanguage(Locale) is called. For the country component, 837: * getDisplayCountry(Locale) is called. For the variant set component, 838: * getDisplayVariant(Locale) is called. 839: * 840: * <p>The returned String will be one of the following forms:<br> 841: * <pre> 842: * language (country, variant) 843: * language (country) 844: * language (variant) 845: * country (variant) 846: * language 847: * country 848: * variant 849: * </pre> 850: * 851: * @param locale locale to use for formatting 852: * @return String version of this locale, suitable for display to the user 853: */ 854: public String getDisplayName(Locale locale) 855: { 856: StringBuffer result = new StringBuffer(); 857: int count = 0; 858: String[] delimiters = {"", " (", ","}; 859: if (language.length() != 0) 860: { 861: result.append(delimiters[count++]); 862: result.append(getDisplayLanguage(locale)); 863: } 864: if (country.length() != 0) 865: { 866: result.append(delimiters[count++]); 867: result.append(getDisplayCountry(locale)); 868: } 869: if (variant.length() != 0) 870: { 871: result.append(delimiters[count++]); 872: result.append(getDisplayVariant(locale)); 873: } 874: if (count > 1) 875: result.append(")"); 876: return result.toString(); 877: } 878: 879: /** 880: * Does the same as <code>Object.clone()</code> but does not throw 881: * a <code>CloneNotSupportedException</code>. Why anyone would 882: * use this method is a secret to me, since this class is immutable. 883: * 884: * @return the clone 885: */ 886: public Object clone() 887: { 888: // This class is final, so no need to use native super.clone(). 889: return new Locale(language, country, variant); 890: } 891: 892: /** 893: * Return the hash code for this locale. The hashcode is the logical 894: * xor of the hash codes of the language, the country and the variant. 895: * The hash code is precomputed, since <code>Locale</code>s are often 896: * used in hash tables. 897: * 898: * @return the hashcode 899: */ 900: public int hashCode() 901: { 902: return hashcode; 903: } 904: 905: /** 906: * Compares two locales. To be equal, obj must be a Locale with the same 907: * language, country, and variant code. 908: * 909: * @param obj the other locale 910: * @return true if obj is equal to this 911: */ 912: public boolean equals(Object obj) 913: { 914: if (this == obj) 915: return true; 916: if (! (obj instanceof Locale)) 917: return false; 918: Locale l = (Locale) obj; 919: 920: return (language == l.language 921: && country == l.country 922: && variant == l.variant); 923: } 924: 925: /** 926: * Write the locale to an object stream. 927: * 928: * @param s the stream to write to 929: * @throws IOException if the write fails 930: * @serialData The first three fields are Strings representing language, 931: * country, and variant. The fourth field is a placeholder for 932: * the cached hashcode, but this is always written as -1, and 933: * recomputed when reading it back. 934: */ 935: private void writeObject(ObjectOutputStream s) 936: throws IOException 937: { 938: s.writeObject(language); 939: s.writeObject(country); 940: s.writeObject(variant); 941: // Hashcode field is always written as -1. 942: s.writeInt(-1); 943: } 944: 945: /** 946: * Reads a locale from the input stream. 947: * 948: * @param s the stream to read from 949: * @throws IOException if reading fails 950: * @throws ClassNotFoundException if reading fails 951: * @serialData the hashCode is always invalid and must be recomputed 952: */ 953: private void readObject(ObjectInputStream s) 954: throws IOException, ClassNotFoundException 955: { 956: language = ((String) s.readObject()).intern(); 957: country = ((String) s.readObject()).intern(); 958: variant = ((String) s.readObject()).intern(); 959: // Recompute hashcode. 960: hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode(); 961: } 962: } // class Locale
GNU Classpath (0.92) |