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