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