Locale.java 26 KB

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