1/* 2 * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/** 25 * @test 26 * @bug 4640234 4946057 4938151 4873691 5023181 27 * @summary Verifies the translation of time zone names, this test will catch 28 * presence of country name for english and selected locales for all 29 * ISO country codes. 30 * The test program also displays which timezone, country and 31 * language names are not translated 32 * @modules java.base/sun.util.resources 33 */ 34 35 36/* 37 * 4946057 Localization for ISO country & language data. 38 * 4938151 Time zones not translated 39 * 4873691 Changes in TimeZone mapping 40 */ 41 42import java.text.MessageFormat; 43import java.text.SimpleDateFormat; 44 45import java.util.Date; 46import java.util.Locale; 47import java.util.Enumeration; 48import java.util.HashMap; 49import java.util.Map; 50import java.util.ResourceBundle; 51import java.util.TimeZone; 52 53import sun.util.resources.LocaleData; 54 55public class Bug4640234 { 56 static SimpleDateFormat sdfEn = new SimpleDateFormat("zzzz", Locale.US); 57 static SimpleDateFormat sdfEnShort = new SimpleDateFormat("z", Locale.US); 58 static Locale locEn = Locale.ENGLISH; 59 60 static SimpleDateFormat sdfLoc; 61 static SimpleDateFormat sdfLocShort; 62 static Date date = new Date(); 63 64 // Define supported locales 65 static Locale[] locales2Test = new Locale[] { 66 new Locale("de"), 67 new Locale("es"), 68 new Locale("fr"), 69 new Locale("it"), 70 new Locale("ja"), 71 new Locale("ko"), 72 new Locale("sv"), 73 new Locale("zh", "CN"), 74 new Locale("zh", "TW") 75 }; 76 77 public static void main(String[] args) throws Exception { 78 Locale reservedLocale = Locale.getDefault(); 79 try { 80 Locale.setDefault(Locale.ENGLISH); 81 82 StringBuffer errors = new StringBuffer(""); 83 StringBuffer warnings = new StringBuffer(""); 84 85 String[] timezones = TimeZone.getAvailableIDs(); 86 String[] countries = locEn.getISOCountries(); 87 String[] languages = locEn.getISOLanguages(); 88 89 ResourceBundle resEn = LocaleData.getBundle("sun.util.resources.LocaleNames", 90 locEn); 91 Map<String, String> countryMapEn = getList(resEn, true); 92 Map<String, String> languageMapEn = getList(resEn, false); 93 94 ResourceBundle resLoc; 95 Map<String, String> countryMap; 96 Map<String, String> languageMap; 97 98 for (Locale locale : locales2Test) { 99 resLoc = LocaleData.getBundle("sun.util.resources.LocaleNames", 100 locale); 101 102 sdfLoc = new SimpleDateFormat("zzzz", locale); 103 sdfLocShort = new SimpleDateFormat("z", locale); 104 105 for (String timezone : timezones) { 106 if (isTZIgnored(timezone)) { 107 continue; 108 } 109 warnings.append(testTZ(timezone, locale)); 110 } 111 112 countryMap = getList(resLoc, true); 113 114 for (String country : countries) { 115 String[] result = testEntry(country, 116 countryMapEn, 117 countryMap, 118 locale, 119 "ERROR: {0} country name for country code: {1} not found!\n", 120 "WARNING: {0} country name for country code: {1} not localized!\n" 121 ); 122 if (warnings.indexOf(result[0]) == -1) { 123 warnings.append(result[0]); 124 } 125 if (errors.indexOf(result[1]) == -1) { 126 errors.append(result[1]); 127 } 128 } 129 130 languageMap = getList(resLoc, false); 131 for (String language : languages) { 132 String[] result = testEntry(language, 133 languageMapEn, 134 languageMap, 135 locale, 136 "ERROR: {0} language name for language code: {1} not found!\n", 137 "WARNING: {0} language name for language code: {1} not localized!\n"); 138 if (warnings.indexOf(result[0]) == -1) { 139 warnings.append(result[0]); 140 } 141 if (errors.indexOf(result[1]) == -1) { 142 errors.append(result[1]); 143 } 144 } 145 } 146 147 StringBuffer message = new StringBuffer(""); 148 if (!"".equals(errors.toString())) { 149 message.append("Test failed! "); 150 message.append("ERROR: some keys are missing! "); 151 } 152 153 if ("".equals(message.toString())) { 154 System.out.println("\nTest passed"); 155 System.out.println(warnings.toString()); 156 } else { 157 System.out.println("\nTest failed!"); 158 System.out.println(errors.toString()); 159 System.out.println(warnings.toString()); 160 throw new Exception("\n" + message); 161 } 162 } finally { 163 // restore the reserved locale 164 Locale.setDefault(reservedLocale); 165 } 166 } 167 168 /** 169 * Compares the english timezone name and timezone name in specified locale 170 * @param timeZoneName - name of the timezone to compare 171 * @param locale - locale to test against english 172 * @return empty string when passed, descriptive error message in other cases 173 */ 174 private static String testTZ(String timeZoneName, Locale locale) { 175 StringBuffer timeZoneResult = new StringBuffer(""); 176 TimeZone tz = TimeZone.getTimeZone(timeZoneName); 177 sdfEn.setTimeZone(tz); 178 sdfEnShort.setTimeZone(tz); 179 sdfLoc.setTimeZone(tz); 180 sdfLocShort.setTimeZone(tz); 181 182 String en, enShort, loc, locShort; 183 en = sdfEn.format(date); 184 enShort = sdfEnShort.format(date); 185 loc = sdfLoc.format(date); 186 locShort = sdfLocShort.format(date); 187 188 String displayLanguage = locale.getDisplayLanguage(); 189 String displayCountry = locale.getDisplayCountry(); 190 191 if (loc.equals(en)) { 192 timeZoneResult.append("["); 193 timeZoneResult.append(displayLanguage); 194 if (!"".equals(displayCountry)) { 195 timeZoneResult.append(" "); 196 timeZoneResult.append(displayCountry); 197 } 198 timeZoneResult.append("] timezone \""); 199 timeZoneResult.append(timeZoneName); 200 timeZoneResult.append("\" long name \"" + en); 201 timeZoneResult.append("\" not localized!\n"); 202 } 203 204 if (!locShort.equals(enShort)) { 205 timeZoneResult.append("["); 206 timeZoneResult.append(displayLanguage); 207 if (!"".equals(displayCountry)) { 208 timeZoneResult.append(" "); 209 timeZoneResult.append(displayCountry); 210 } 211 timeZoneResult.append("] timezone \""); 212 timeZoneResult.append(timeZoneName); 213 timeZoneResult.append("\" short name \"" + enShort); 214 timeZoneResult.append("\" is localized \""); 215 timeZoneResult.append(locShort); 216 timeZoneResult.append("\"!\n"); 217 } 218 return timeZoneResult.toString(); 219 } 220 221 /** 222 * Verifies whether the name for ISOCode is localized. 223 * @param ISOCode - ISO country/language code for country/language name 224 * to test 225 * @param entriesEn - array of english country/language names 226 * @param entriesLoc - array of localized country/language names for 227 * specified locale 228 * @param locale - locale to test against english 229 * @param notFoundMessage - message in form ready for MessageFormat, 230 * {0} will be human readable language name, {1} will be ISOCode. 231 * @param notLocalizedMessage - message in for ready for MessageFormat, 232 * same formatting like for notFountMessage 233 * @return array of two empty strings when passed, descriptive error message 234 * in other cases, [0] - warnings for not localized, [1] - errors for 235 * missing keys. 236 */ 237 private static String[] testEntry(String ISOCode, 238 Map<String, String> entriesEn, 239 Map<String, String> entriesLoc, 240 Locale locale, 241 String notFoundMessage, 242 String notLocalizedMessage) { 243 String nameEn = null; 244 String nameLoc = null; 245 246 for (String key: entriesEn.keySet()) { 247 if (ISOCode.equalsIgnoreCase(key)) { 248 nameEn = entriesEn.get(key); 249 break; 250 } 251 } 252 253 for (String key: entriesLoc.keySet()) { 254 if (ISOCode.equalsIgnoreCase(key)) { 255 nameLoc = entriesLoc.get(key); 256 break; 257 } 258 } 259 260 if (nameEn == null) { 261 // We should not get here but test is a MUST have 262 return new String[] {"", 263 MessageFormat.format(notFoundMessage, "English", ISOCode)}; 264 } 265 266 if (nameLoc == null) { 267 return new String[] {"", 268 MessageFormat.format(notFoundMessage, 269 locale.getDisplayName(), ISOCode)}; 270 } 271 272 if (nameEn.equals(nameLoc)) { 273 return new String[] {MessageFormat.format(notLocalizedMessage, 274 locale.getDisplayName(), ISOCode), 275 ""}; 276 } 277 278 return new String[] {"", ""}; 279 } 280 281 private static boolean isTZIgnored(String TZName) { 282 if (TZName.startsWith("Etc/GMT") || 283 TZName.indexOf("Riyadh8") != -1 || 284 TZName.equals("GMT0") || 285 TZName.equals("MET") 286 ) { 287 return true; 288 } 289 return false; 290 } 291 292 private static Map<String, String> getList( 293 ResourceBundle rs, Boolean getCountryList) { 294 char beginChar = 'a'; 295 char endChar = 'z'; 296 if (getCountryList) { 297 beginChar = 'A'; 298 endChar = 'Z'; 299 } 300 301 Map<String, String> hm = new HashMap<String, String>(); 302 Enumeration<String> keys = rs.getKeys(); 303 while (keys.hasMoreElements()) { 304 String s = keys.nextElement(); 305 if (s.length() == 2 && 306 s.charAt(0) >= beginChar && s.charAt(0) <= endChar) { 307 hm.put(s, rs.getString(s)); 308 } 309 } 310 return hm; 311 } 312} 313