blob: a509bb29ac71feb07450d9f57a9868df0f1cdf99 [file] [log] [blame]
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001#!/usr/bin/python2
Hung-Te Lin34f3d382015-04-10 18:18:23 +08002# -*- coding: utf-8 -*-
Hung-Te Lin76c55b22015-03-31 14:47:14 +08003# Copyright 2015 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Authoritative source for Chromium OS region/locale configuration.
8
9Run this module to display all known regions (use --help to see options).
10"""
11
12from __future__ import print_function
13
14import argparse
15import collections
16import json
17import re
18import sys
19
20import yaml
21
22
23# The regular expression to check values in Region.keyboards and Region.locales.
24# Keyboards should come with xkb: protocol, or the input methods (ime:, m17n:).
25# Examples: xkb:us:intl:eng, ime:ime:zh-t:cangjie
26KEYBOARD_PATTERN = re.compile(r'^xkb:\w+:\w*:\w+$|'
27 r'^(ime|m17n|t13n):[\w:-]+$')
28# Locale should be a combination of language and location.
29# Examples: en-US, ja.
30LOCALE_PATTERN = re.compile(r'^(\w+)(-[A-Z0-9]+)?$')
31
32
33class Enum(frozenset):
34 """An enumeration type.
35
36 Usage:
37 To create a enum object:
38 dummy_enum = Enum(['A', 'B', 'C'])
39
40 To access a enum object, use:
41 dummy_enum.A
42 dummy_enum.B
43 """
44
45 def __getattr__(self, name):
46 if name in self:
47 return name
48 raise AttributeError
49
50
51class RegionException(Exception):
52 """Exception in Region handling."""
53 pass
54
55
56def MakeList(value):
57 """Converts the given value to a list.
58
59 Returns:
60 A list of elements from "value" if it is iterable (except string);
61 otherwise, a list contains only one element.
62 """
63 if (isinstance(value, collections.Iterable) and
64 not isinstance(value, basestring)):
65 return list(value)
66 return [value]
67
68
69class Region(object):
70 """Comprehensive, standard locale configuration per country/region.
71
72 See :ref:`regions-values` for detailed information on how to set these values.
73 """
74 # pylint gets confused by some of the docstrings.
75 # pylint: disable=C0322
76
77 # ANSI = US-like
78 # ISO = UK-like
79 # JIS = Japanese
80 # KS = Korean
81 # ABNT2 = Brazilian (like ISO but with an extra key to the left of the
82 # right shift key)
83 KeyboardMechanicalLayout = Enum(['ANSI', 'ISO', 'JIS', 'KS', 'ABNT2'])
84
85 region_code = None
86 """A unique identifier for the region. This may be a lower-case
87 `ISO 3166-1 alpha-2 code
88 <http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2>`_ (e.g., ``us``),
89 a variant within an alpha-2 entity (e.g., ``ca.fr``), or an
90 identifier for a collection of countries or entities (e.g.,
91 ``latam-es-419`` or ``nordic``). See :ref:`region-codes`.
92
93 Note that ``uk`` is not a valid identifier; ``gb`` is used as it is
94 the real alpha-2 code for the UK."""
95
96 keyboards = None
97 """A list of keyboard layout identifiers (e.g., ``xkb:us:intl:eng``
98 or ``m17n:ar``). This field was designed to be the physical keyboard layout
99 in the beginning, and then becomes a list of OOBE keyboard selection, which
100 then includes non-physical layout elements like input methods (``ime:``).
101 To avoid confusion, physical layout is now defined by
102 :py:attr:`keyboard_mechanical_layout`, and this is reserved for logical
103 layouts.
104
105 This is identical to the legacy VPD ``keyboard_layout`` value."""
106
107 time_zones = None
108 """A list of default `tz database time zone
109 <http://en.wikipedia.org/wiki/List_of_tz_database_time_zones>`_
110 identifiers (e.g., ``America/Los_Angeles``). See
111 `timezone_settings.cc <http://goo.gl/WSVUeE>`_ for supported time
112 zones.
113
114 This is identical to the legacy VPD ``initial_timezone`` value."""
115
116 locales = None
117 """A list of default locale codes (e.g., ``en-US``); see
118 `l10n_util.cc <http://goo.gl/kVkht>`_ for supported locales.
119
120 This is identital to the legacy VPD ``initial_locale`` field."""
121
122 keyboard_mechanical_layout = None
123 """The keyboard's mechanical layout (``ANSI`` [US-like], ``ISO``
124 [UK-like], ``JIS`` [Japanese], ``ABNT2`` [Brazilian] or ``KS`` [Korean])."""
125
126 description = None
127 """A human-readable description of the region.
128 This defaults to :py:attr:`region_code` if not set."""
129
130 notes = None
131 """Implementation notes about the region. This may be None."""
132
133 numeric_id = None
134 """An integer for mapping into Chrome OS HWID.
135 Please never change this once it is assigned."""
136
Hung-Te Lin436b6cc2015-04-03 12:15:47 +0800137 regulatory_domain = None
138 """An ISO 3166-1 alpha 2 upper-cased two-letter region code for setting
139 Wireless regulatory. See crosbug.com/p/38745 for more details.
140
141 When omitted, this will derive from region_code."""
142
Hung-Te Lin1a14cc42015-04-14 01:23:34 +0800143 confirmed = None
144 """An optional boolean flag to indicate if the region data is confirmed."""
145
146 FIELDS = ['numeric_id', 'region_code', 'description', 'keyboards',
147 'time_zones', 'locales', 'keyboard_mechanical_layout',
148 'regulatory_domain']
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800149 """Names of fields that define the region."""
150
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800151 def __init__(self, region_code, keyboards, time_zones, locales,
152 keyboard_mechanical_layout, description=None, notes=None,
Hung-Te Lin436b6cc2015-04-03 12:15:47 +0800153 numeric_id=None, regdomain=None):
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800154 """Constructor.
155
156 Args:
157 region_code: See :py:attr:`region_code`.
158 keyboards: See :py:attr:`keyboards`. A single string is accepted for
159 backward compatibility.
160 time_zones: See :py:attr:`time_zones`.
161 locales: See :py:attr:`locales`. A single string is accepted
162 for backward compatibility.
163 keyboard_mechanical_layout: See :py:attr:`keyboard_mechanical_layout`.
164 description: See :py:attr:`description`.
165 notes: See :py:attr:`notes`.
166 numeric_id: See :py:attr:`numeric_id`. This must be None or a
167 non-negative integer.
Hung-Te Lin436b6cc2015-04-03 12:15:47 +0800168 regdomain: See :py:attr:`regulatory_domain`.
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800169 """
Hung-Te Lin436b6cc2015-04-03 12:15:47 +0800170
171 def regdomain_from_region(region):
172 if region.find('.') >= 0:
173 region = region[:region.index('.')]
174 if len(region) == 2:
175 return region.upper()
176 return None
177
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800178 # Quick check: should be 'gb', not 'uk'
179 if region_code == 'uk':
180 raise RegionException("'uk' is not a valid region code (use 'gb')")
181
182 self.region_code = region_code
183 self.keyboards = MakeList(keyboards)
184 self.time_zones = MakeList(time_zones)
185 self.locales = MakeList(locales)
186 self.keyboard_mechanical_layout = keyboard_mechanical_layout
187 self.description = description or region_code
188 self.notes = notes
189 self.numeric_id = numeric_id
Hung-Te Lin436b6cc2015-04-03 12:15:47 +0800190 self.regulatory_domain = (regdomain or regdomain_from_region(region_code))
Hung-Te Lin1a14cc42015-04-14 01:23:34 +0800191 self.confirmed = None
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800192
193 if self.numeric_id is not None:
194 if not isinstance(self.numeric_id, int):
195 raise TypeError('Numeric ID is %r but should be an integer' %
196 (self.numeric_id,))
197 if self.numeric_id < 0:
198 raise ValueError('Numeric ID is %r but should be non-negative' %
199 self.numeric_id)
200
201 for f in (self.keyboards, self.locales):
202 assert all(isinstance(x, str) for x in f), (
203 'Expected a list of strings, not %r' % f)
204 for f in self.keyboards:
205 assert KEYBOARD_PATTERN.match(f), (
206 'Keyboard pattern %r does not match %r' % (
207 f, KEYBOARD_PATTERN.pattern))
208 for f in self.locales:
209 assert LOCALE_PATTERN.match(f), (
210 'Locale %r does not match %r' % (
211 f, LOCALE_PATTERN.pattern))
Hung-Te Lin436b6cc2015-04-03 12:15:47 +0800212 assert (self.regulatory_domain and
213 len(self.regulatory_domain) == 2 and
214 self.regulatory_domain.upper() == self.regulatory_domain), (
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800215 'Regulatory domain settings error for region %s' % region_code)
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800216
217 def __repr__(self):
218 return 'Region(%s)' % (', '.join([getattr(self, x) for x in self.FIELDS]))
219
220 def GetFieldsDict(self):
221 """Returns a dict of all substantive fields.
222
223 notes and description are excluded.
224 """
225 return dict((k, getattr(self, k)) for k in self.FIELDS)
226
227_KML = Region.KeyboardMechanicalLayout
228REGIONS_LIST = [
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800229 Region(
230 'au', 'xkb:us::eng', 'Australia/Sydney', 'en-AU', _KML.ANSI,
231 'Australia', None, 1),
232 Region(
233 'be', 'xkb:be::nld', 'Europe/Brussels', 'en-GB', _KML.ISO,
234 'Belgium',
235 'Flemish (Belgian Dutch) keyboard; British English language for '
236 'neutrality', 2),
237 Region(
238 'br', 'xkb:br::por', 'America/Sao_Paulo', 'pt-BR', _KML.ABNT2,
239 'Brazil (ABNT2)',
240 (
241 'ABNT2 = ABNT NBR 10346 variant 2. This is the preferred layout '
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800242 'for Brazil. ABNT2 is mostly an ISO layout, but it 12 keys between '
243 'the shift keys; see http://goo.gl/twA5tq'), 3),
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800244 Region(
245 'br.abnt', 'xkb:br::por', 'America/Sao_Paulo', 'pt-BR',
246 _KML.ISO, 'Brazil (ABNT)',
247 (
248 'Like ABNT2, but lacking the extra key to the left of the right '
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800249 'shift key found in that layout. ABNT2 (the "br" region) is '
250 'preferred to this layout'), 4),
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800251 Region(
252 'br.usintl', 'xkb:us:intl:eng', 'America/Sao_Paulo', 'pt-BR',
253 _KML.ANSI, 'Brazil (US Intl)',
254 'Brazil with US International keyboard layout. ABNT2 ("br") and '
255 'ABNT1 ("br.abnt1 ") are both preferred to this.', 5),
256 Region(
257 'ca.ansi', 'xkb:us::eng', 'America/Toronto', 'en-CA', _KML.ANSI,
258 'Canada (US keyboard)',
259 'Canada with US (ANSI) keyboard. Not for en/fr hybrid ANSI '
260 'keyboards; for that you would want ca.hybridansi. See '
261 'http://goto/cros-canada', 6),
262 Region(
263 'ca.fr', 'xkb:ca::fra', 'America/Toronto', 'fr-CA', _KML.ISO,
264 'Canada (French keyboard)',
265 (
266 'Canadian French (ISO) keyboard. The most common configuration for '
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800267 'Canadian French SKUs. See http://goto/cros-canada'), 7),
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800268 Region(
269 'ca.hybrid', 'xkb:ca:eng:eng', 'America/Toronto', 'en-CA',
270 _KML.ISO, 'Canada (hybrid ISO)',
271 (
272 'Canada with hybrid (ISO) xkb:ca:eng:eng + xkb:ca::fra keyboard, '
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800273 'defaulting to English language and keyboard. Used only if there '
274 'needs to be a single SKU for all of Canada. See '
275 'http://goto/cros-canada'), 8),
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800276 Region(
277 'ca.hybridansi', 'xkb:ca:eng:eng', 'America/Toronto', 'en-CA',
278 _KML.ANSI, 'Canada (hybrid ANSI)',
279 (
280 'Canada with hybrid (ANSI) xkb:ca:eng:eng + xkb:ca::fra keyboard, '
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800281 'defaulting to English language and keyboard. Used only if there '
282 'needs to be a single SKU for all of Canada. See '
283 'http://goto/cros-canada'), 9),
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800284 Region(
285 'ca.multix', 'xkb:ca:multix:fra', 'America/Toronto', 'fr-CA',
286 _KML.ISO, 'Canada (multilingual)',
287 (
288 "Canadian Multilingual keyboard; you probably don't want this. See "
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800289 'http://goto/cros-canada'), 10),
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800290 Region(
291 'ch', 'xkb:ch::ger', 'Europe/Zurich', 'en-US', _KML.ISO,
292 'Switzerland',
293 'German keyboard, but US English to be language-neutral; used in '
294 'the common case that there is only a single Swiss SKU.', 11),
295 Region(
296 'de', 'xkb:de::ger', 'Europe/Berlin', 'de', _KML.ISO, 'Germany',
297 None, 12),
298 Region(
299 'es', 'xkb:es::spa', 'Europe/Madrid', 'es', _KML.ISO, 'Spain',
300 None, 13),
301 Region(
302 'fi', 'xkb:fi::fin', 'Europe/Helsinki', 'fi', _KML.ISO, 'Finland',
303 None, 14),
304 Region(
305 'fr', 'xkb:fr::fra', 'Europe/Paris', 'fr', _KML.ISO, 'France',
306 None, 15),
307 Region(
308 'gb', 'xkb:gb:extd:eng', 'Europe/London', 'en-GB', _KML.ISO, 'UK',
309 None, 16),
310 Region(
311 'ie', 'xkb:gb:extd:eng', 'Europe/Dublin', 'en-GB', _KML.ISO,
312 'Ireland', None, 17),
313 Region(
314 'in', 'xkb:us::eng', 'Asia/Calcutta', 'en-US', _KML.ANSI, 'India',
315 None, 18),
316 Region(
317 'it', 'xkb:it::ita', 'Europe/Rome', 'it', _KML.ISO, 'Italy', None,
318 19),
319 Region(
320 'latam-es-419', 'xkb:es::spa', 'America/Mexico_City', 'es-419',
321 _KML.ISO, 'Hispanophone Latin America',
322 (
323 'Spanish-speaking countries in Latin America, using the Iberian '
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800324 '(Spain) Spanish keyboard, which is increasingly dominant in '
325 'Latin America. Known to be correct for '
326 'Chile, Colombia, Mexico, Peru; '
327 'still unconfirmed for other es-419 countries. The old Latin '
328 'American layout (xkb:latam::spa) has not been approved; before '
329 'using that you must seek review through http://goto/vpdsettings. '
330 'See also http://goo.gl/Iffuqh. Note that 419 is the UN M.49 '
Hung-Te Lin436b6cc2015-04-03 12:15:47 +0800331 'region code for Latin America'), 20, 'MX'),
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800332 Region(
333 'my', 'xkb:us::eng', 'Asia/Kuala_Lumpur', 'ms', _KML.ANSI,
334 'Malaysia', None, 21),
335 Region(
336 'nl', 'xkb:us:intl:eng', 'Europe/Amsterdam', 'nl', _KML.ANSI,
337 'Netherlands', None, 22),
338 Region(
339 'nordic', 'xkb:se::swe', 'Europe/Stockholm', 'en-US', _KML.ISO,
340 'Nordics',
341 (
342 'Unified SKU for Sweden, Norway, and Denmark. This defaults '
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800343 'to Swedish keyboard layout, but starts with US English language '
344 'for neutrality. Use if there is a single combined SKU for Nordic '
Hung-Te Lin436b6cc2015-04-03 12:15:47 +0800345 'countries.'), 23, 'SE'),
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800346 Region(
347 'nz', 'xkb:us::eng', 'Pacific/Auckland', 'en-NZ', _KML.ANSI,
348 'New Zealand', None, 24),
349 Region(
350 'ph', 'xkb:us::eng', 'Asia/Manila', 'en-US', _KML.ANSI,
351 'Philippines', None, 25),
352 Region(
353 'ru', 'xkb:ru::rus', 'Europe/Moscow', 'ru', _KML.ANSI, 'Russia',
354 'For R31+ only; R30 and earlier must use US keyboard for login',
355 26),
356 Region(
357 'se', 'xkb:se::swe', 'Europe/Stockholm', 'sv', _KML.ISO, 'Sweden',
358 (
359 'Use this if there separate SKUs for Nordic countries (Sweden, '
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800360 'Norway, and Denmark), or the device is only shipping to Sweden. '
361 "If there is a single unified SKU, use 'nordic' instead."), 27),
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800362 Region(
363 'sg', 'xkb:us::eng', 'Asia/Singapore', 'en-GB', _KML.ANSI,
364 'Singapore', None, 28),
365 Region(
366 'us', 'xkb:us::eng', 'America/Los_Angeles', 'en-US', _KML.ANSI,
367 'United States', None, 29),
368 Region(
369 'jp', 'xkb:jp::jpn', 'Asia/Tokyo', 'ja', _KML.JIS, 'Japan', None,
370 30),
371 Region(
372 'za', 'xkb:us:intl:eng', 'Africa/Johannesburg', 'en-ZA',
373 _KML.ANSI, 'South Africa', None, 31),
374 Region(
375 'ng', 'xkb:us:intl:eng', 'Africa/Lagos', 'en-GB', _KML.ANSI,
376 'Nigeria', None, 32),
377 Region(
378 'hk',
379 ['xkb:us::eng', 'ime:zh-t:cangjie', 'ime:zh-t:quick',
380 'ime:zh-t:array', 'ime:zh-t:dayi', 'ime:zh-t:zhuyin',
381 'ime:zh-t:pinyin'], 'Asia/Hong_Kong',
382 ['zh-TW', 'en-GB', 'zh-CN'], _KML.ANSI, 'Hong Kong', None, 33),
383 Region(
384 'gcc', ['xkb:us::eng', 'm17n:ar', 't13n:ar'], 'Asia/Riyadh',
385 ['ar', 'en-GB'], _KML.ANSI, 'Gulf Cooperation Council (GCC)',
386 (
387 'GCC is a regional intergovernmental political and economic '
388 'union consisting of all Arab states of the Persian Gulf except '
389 'for Iraq. Its member states are the Islamic monarchies of '
390 'Bahrain, Kuwait, Oman, Qatar, Saudi Arabia, and the United Arab '
391 'Emirates.'), 34, 'SA'),
392 Region(
393 'cz', ['xkb:cz::cze', 'xkb:cz:qwerty:cze'], 'Europe/Prague',
394 ['cs', 'en-GB'], _KML.ISO, 'Czech Republic', None, 35),
395 Region(
396 'th',
397 ['xkb:us::eng', 'm17n:th', 'm17n:th_pattajoti', 'm17n:th_tis'],
398 'Asia/Bangkok', ['th', 'en-GB'], _KML.ANSI, 'Thailand', None, 36),
399 Region(
400 'id', 'xkb:us::ind', 'Asia/Jakarta', ['id', 'en-GB'], _KML.ANSI,
401 'Indonesia', None, 37),
402 Region(
403 'tw',
404 ['xkb:us::eng', 'ime:zh-t:zhuyin', 'ime:zh-t:array',
405 'ime:zh-t:dayi', 'ime:zh-t:cangjie', 'ime:zh-t:quick',
406 'ime:zh-t:pinyin'], 'Asia/Taipei', ['zh-TW', 'en-US'],
407 _KML.ANSI, 'Taiwan', None, 38),
408 Region(
409 'pl', 'xkb:pl::pol', 'Europe/Warsaw', ['pl', 'en-GB'],
410 _KML.ANSI, 'Poland', None, 39),
411 Region(
412 'gr', ['xkb:us::eng', 'xkb:gr::gre', 't13n:el'], 'Europe/Athens',
413 ['el', 'en-GB'], _KML.ANSI, 'Greece', None, 40),
414 Region(
415 'il', ['xkb:us::eng', 'xkb:il::heb', 't13n:he'], 'Asia/Jerusalem',
416 ['he', 'en-US', 'ar'], _KML.ANSI, 'Israel', None, 41),
417 Region(
418 'pt', 'xkb:pt::por', 'Europe/Lisbon', ['pt-PT', 'en-GB'],
419 _KML.ISO, 'Portugal', None, 42),
420 Region(
421 'ro', ['xkb:us::eng', 'xkb:ro::rum'], 'Europe/Bucharest',
422 ['ro', 'hu', 'de', 'en-GB'], _KML.ISO, 'Romania', None, 43),
423 Region(
424 'kr', ['xkb:us::eng', 'ime:ko:hangul'], 'Asia/Seoul',
425 ['ko', 'en-US'], _KML.KS, 'South Korea', None, 44),
426 Region(
427 'ae', 'xkb:us::eng', 'Asia/Dubai', 'ar', _KML.ANSI, 'UAE', None,
428 45),
429 Region(
430 'za.us', 'xkb:us::eng', 'Africa/Johannesburg', 'en-ZA',
431 _KML.ANSI, 'South Africa', None, 46),
432 Region(
433 'vn',
434 ['xkb:us::eng', 'm17n:vi_telex', 'm17n:vi_vni', 'm17n:vi_viqr',
435 'm17n:vi_tcvn'], 'Asia/Ho_Chi_Minh',
436 ['vi', 'en-GB', 'en-US', 'fr', 'zh-TW'], _KML.ANSI, 'Vietnam',
437 None, 47),
438 Region(
439 'at', ['xkb:de::ger', 'xkb:de:neo:ger'], 'Europe/Vienna',
440 ['de', 'en-GB'], _KML.ISO, 'Austria', None, 48),
441 Region(
442 'sk', ['xkb:us::eng', 'xkb:sk::slo'], 'Europe/Bratislava',
443 ['sk', 'hu', 'cs', 'en-GB'], _KML.ISO, 'Slovakia', None, 49),
444 Region(
445 'ch.usintl', 'xkb:us:intl:eng', 'Europe/Zurich', 'en-US',
446 _KML.ANSI, 'Switzerland (US Intl)',
447 'Switzerland with US International keyboard layout.', 50)]
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800448"""A list of :py:class:`regions.Region` objects for
449all **confirmed** regions. A confirmed region is a region whose
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800450properties are known to be correct and valid: all contents (locale / timezone /
451keyboards) are supported by Chrome."""
Hung-Te Lin76c55b22015-03-31 14:47:14 +0800452
453
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +0800454UNCONFIRMED_REGIONS_LIST = [
455 Region(
456 'bd', 'xkb:bd::ben', 'Asia/Dhaka', ['bn-BD', 'en'], _KML.ANSI,
457 'Bangladesh', None, 51),
458 Region(
459 'bf', 'xkb:bf::fra', 'Africa/Ouagadougou', 'fr-BF', _KML.ANSI,
460 'Burkina Faso', None, 52),
461 Region(
462 'bg', ['xkb:bg::bul', 'xkb:bg:phonetic:bul'], 'Europe/Sofia',
463 ['bg', 'tr', 'en-GB'], _KML.ANSI, 'Bulgaria', None, 53),
464 Region(
465 'ba', 'xkb:ba::bos', 'Europe/Sarajevo', ['bs', 'hr-BA', 'sr-BA'],
466 _KML.ANSI, 'Bosnia and Herzegovina', None, 54),
467 Region(
468 'bb', 'xkb:bb::eng', 'America/Barbados', 'en-BB', _KML.ANSI,
469 'Barbados', None, 55),
470 Region(
471 'wf', 'xkb:us::eng', 'Pacific/Wallis', ['wls', 'fud', 'fr-WF'],
472 _KML.ANSI, 'Wallis and Futuna', None, 56),
473 Region(
474 'bl', 'xkb:bl::fra', 'America/St_Barthelemy', 'fr', _KML.ANSI,
475 'Saint Barthelemy', None, 57),
476 Region(
477 'bm', 'xkb:bm::eng', 'Atlantic/Bermuda', ['en-BM', 'pt'],
478 _KML.ANSI, 'Bermuda', None, 58),
479 Region(
480 'bn', 'xkb:bn::msa', 'Asia/Brunei', ['ms-BN', 'en-BN'],
481 _KML.ANSI, 'Brunei', None, 59),
482 Region(
483 'bo', 'xkb:bo::spa', 'America/La_Paz', ['es-BO', 'qu', 'ay'],
484 _KML.ANSI, 'Bolivia', None, 60),
485 Region(
486 'bh', 'xkb:bh::ara', 'Asia/Bahrain', ['ar-BH', 'en', 'fa', 'ur'],
487 _KML.ANSI, 'Bahrain', None, 61),
488 Region(
489 'bi', 'xkb:bi::fra', 'Africa/Bujumbura', ['fr-BI', 'rn'],
490 _KML.ANSI, 'Burundi', None, 62),
491 Region(
492 'bj', 'xkb:bj::fra', 'Africa/Porto-Novo', 'fr-BJ', _KML.ANSI,
493 'Benin', None, 63),
494 Region(
495 'bt', 'xkb:bt::dzo', 'Asia/Thimphu', 'dz', _KML.ANSI, 'Bhutan',
496 None, 64),
497 Region(
498 'jm', 'xkb:jm::eng', 'America/Jamaica', 'en-JM', _KML.ANSI,
499 'Jamaica', None, 65),
500 Region(
501 'bw', 'xkb:bw::eng', 'Africa/Gaborone', ['en-BW', 'tn-BW'],
502 _KML.ANSI, 'Botswana', None, 66),
503 Region(
504 'ws', 'xkb:ws::smo', 'Pacific/Apia', ['sm', 'en-WS'], _KML.ANSI,
505 'Samoa', None, 67),
506 Region(
507 'bq', 'xkb:bq::nld', 'America/Kralendijk', ['nl', 'pap', 'en'],
508 _KML.ANSI, 'Bonaire, Saint Eustatius and Saba ', None, 68),
509 Region(
510 'bs', 'xkb:bs::eng', 'America/Nassau', 'en-BS', _KML.ANSI,
511 'Bahamas', None, 69),
512 Region(
513 'je', 'xkb:je::eng', 'Europe/Jersey', ['en', 'pt'], _KML.ANSI,
514 'Jersey', None, 70),
515 Region(
516 'by', 'xkb:by::bel', 'Europe/Minsk', ['be', 'ru'], _KML.ANSI,
517 'Belarus', None, 71),
518 Region(
519 'bz', 'xkb:bz::eng', 'America/Belize', ['en-BZ', 'es'],
520 _KML.ANSI, 'Belize', None, 72),
521 Region(
522 'rw', 'xkb:rw::kin', 'Africa/Kigali',
523 ['rw', 'en-RW', 'fr-RW', 'sw'], _KML.ANSI, 'Rwanda', None, 73),
524 Region(
525 'rs', 'xkb:rs::srp', 'Europe/Belgrade', ['sr', 'hu', 'bs', 'rom'],
526 _KML.ANSI, 'Serbia', None, 74),
527 Region(
528 'tl', 'xkb:us::eng', 'Asia/Dili', ['tet', 'pt-TL', 'id', 'en'],
529 _KML.ANSI, 'East Timor', None, 75),
530 Region(
531 're', 'xkb:re::fra', 'Indian/Reunion', 'fr-RE', _KML.ANSI,
532 'Reunion', None, 76),
533 Region(
534 'tm', 'xkb:tm::tuk', 'Asia/Ashgabat', ['tk', 'ru', 'uz'],
535 _KML.ANSI, 'Turkmenistan', None, 77),
536 Region(
537 'tj', 'xkb:tj::tgk', 'Asia/Dushanbe', ['tg', 'ru'], _KML.ANSI,
538 'Tajikistan', None, 78),
539 Region(
540 'tk', 'xkb:us::eng', 'Pacific/Fakaofo', ['tkl', 'en-TK'],
541 _KML.ANSI, 'Tokelau', None, 79),
542 Region(
543 'gw', 'xkb:gw::por', 'Africa/Bissau', ['pt-GW', 'pov'],
544 _KML.ANSI, 'Guinea-Bissau', None, 80),
545 Region(
546 'gu', 'xkb:gu::eng', 'Pacific/Guam', ['en-GU', 'ch-GU'],
547 _KML.ANSI, 'Guam', None, 81),
548 Region(
549 'gt', 'xkb:gt::spa', 'America/Guatemala', 'es-GT', _KML.ANSI,
550 'Guatemala', None, 82),
551 Region(
552 'gs', 'xkb:gs::eng', 'Atlantic/South_Georgia', 'en', _KML.ANSI,
553 'South Georgia and the South Sandwich Islands', None, 83),
554 Region(
555 'gq', 'xkb:gq::spa', 'Africa/Malabo', ['es-GQ', 'fr'],
556 _KML.ANSI, 'Equatorial Guinea', None, 84),
557 Region(
558 'gp', 'xkb:gp::fra', 'America/Guadeloupe', 'fr-GP', _KML.ANSI,
559 'Guadeloupe', None, 85),
560 Region(
561 'gy', 'xkb:gy::eng', 'America/Guyana', 'en-GY', _KML.ANSI,
562 'Guyana', None, 86),
563 Region(
564 'gg', 'xkb:gg::eng', 'Europe/Guernsey', ['en', 'fr'], _KML.ANSI,
565 'Guernsey', None, 87),
566 Region(
567 'gf', 'xkb:gf::fra', 'America/Cayenne', 'fr-GF', _KML.ANSI,
568 'French Guiana', None, 88),
569 Region(
570 'ge', 'xkb:ge::geo', 'Asia/Tbilisi', 'ka', _KML.ANSI, 'Georgia', None,
571 89),
572 Region(
573 'gd', 'xkb:gd::eng', 'America/Grenada', 'en-GD', _KML.ANSI,
574 'Grenada', None, 90),
575 Region(
576 'ga', 'xkb:ga::fra', 'Africa/Libreville', 'fr-GA', _KML.ANSI,
577 'Gabon', None, 91),
578 Region(
579 'sv', 'xkb:sv::spa', 'America/El_Salvador', 'es-SV', _KML.ANSI,
580 'El Salvador', None, 92),
581 Region(
582 'gn', 'xkb:gn::fra', 'Africa/Conakry', 'fr-GN', _KML.ANSI,
583 'Guinea', None, 93),
584 Region(
585 'gm', 'xkb:gm::eng', 'Africa/Banjul',
586 ['en-GM', 'mnk', 'wof', 'wo', 'ff'], _KML.ANSI, 'Gambia', None, 94),
587 Region(
588 'gl', 'xkb:gl::kal',
589 ['America/Godthab', 'America/Danmarkshavn',
590 'America/Scoresbysund', 'America/Thule'], ['kl', 'da-GL', 'en'],
591 _KML.ANSI, 'Greenland', None, 95),
592 Region(
593 'gi', 'xkb:gi::eng', 'Europe/Gibraltar',
594 ['en-GI', 'es', 'it', 'pt'], _KML.ANSI, 'Gibraltar', None, 96),
595 Region(
596 'gh', 'xkb:gh::eng', 'Africa/Accra', ['en-GH', 'ak', 'ee', 'tw'],
597 _KML.ANSI, 'Ghana', None, 97),
598 Region(
599 'om', 'xkb:om::ara', 'Asia/Muscat', ['ar-OM', 'en', 'bal', 'ur'],
600 _KML.ANSI, 'Oman', None, 98),
601 Region(
602 'tn', 'xkb:tn::ara', 'Africa/Tunis', ['ar-TN', 'fr'], _KML.ANSI,
603 'Tunisia', None, 99),
604 Region(
605 'jo', 'xkb:jo::ara', 'Asia/Amman', ['ar-JO', 'en'], _KML.ANSI,
606 'Jordan', None, 100),
607 Region(
608 'hr', 'xkb:hr::scr', 'Europe/Zagreb', ['hr', 'en-GB'],
609 _KML.ISO, 'Croatia', None, 101),
610 Region(
611 'ht', 'xkb:ht::hat', 'America/Port-au-Prince', ['ht', 'fr-HT'],
612 _KML.ANSI, 'Haiti', None, 102),
613 Region(
614 'hu', ['xkb:us::eng', 'xkb:hu::hun'], 'Europe/Budapest',
615 ['hu', 'en-GB'], _KML.ISO, 'Hungary', None, 103),
616 Region(
617 'hn', 'xkb:hn::spa', 'America/Tegucigalpa', 'es-HN', _KML.ANSI,
618 'Honduras', None, 104),
619 Region(
620 've', 'xkb:ve::spa', 'America/Caracas', 'es-VE', _KML.ANSI,
621 'Venezuela', None, 105),
622 Region(
623 'pr', 'xkb:pr::eng', 'America/Puerto_Rico', ['en-PR', 'es-PR'],
624 _KML.ANSI, 'Puerto Rico', None, 106),
625 Region(
626 'ps', 'xkb:ps::ara', ['Asia/Gaza', 'Asia/Hebron'], 'ar-PS',
627 _KML.ANSI, 'Palestinian Territory', None, 107),
628 Region(
629 'pw', 'xkb:us::eng', 'Pacific/Palau',
630 ['pau', 'sov', 'en-PW', 'tox', 'ja', 'fil', 'zh'], _KML.ANSI,
631 'Palau', None, 108),
632 Region(
633 'sj', 'xkb:sj::nor', 'Arctic/Longyearbyen', ['no', 'ru'],
634 _KML.ANSI, 'Svalbard and Jan Mayen', None, 109),
635 Region(
636 'py', 'xkb:py::spa', 'America/Asuncion', ['es-PY', 'gn'],
637 _KML.ANSI, 'Paraguay', None, 110),
638 Region(
639 'iq', 'xkb:iq::ara', 'Asia/Baghdad', ['ar-IQ', 'ku', 'hy'],
640 _KML.ANSI, 'Iraq', None, 111),
641 Region(
642 'pa', 'xkb:pa::spa', 'America/Panama', ['es-PA', 'en'],
643 _KML.ANSI, 'Panama', None, 112),
644 Region(
645 'pf', 'xkb:pf::fra',
646 ['Pacific/Tahiti', 'Pacific/Marquesas', 'Pacific/Gambier'],
647 ['fr-PF', 'ty'], _KML.ANSI, 'French Polynesia', None, 113),
648 Region(
649 'pg', 'xkb:pg::eng',
650 ['Pacific/Port_Moresby', 'Pacific/Bougainville'],
651 ['en-PG', 'ho', 'meu', 'tpi'], _KML.ANSI, 'Papua New Guinea', None,
652 114),
653 Region(
654 'pe', 'xkb:pe::spa', 'America/Lima', ['es-PE', 'qu', 'ay'],
655 _KML.ANSI, 'Peru', None, 115),
656 Region(
657 'pk', 'xkb:pk::urd', 'Asia/Karachi',
658 ['ur-PK', 'en-PK', 'pa', 'sd', 'ps', 'brh'], _KML.ANSI,
659 'Pakistan', None, 116),
660 Region(
661 'pn', 'xkb:pn::eng', 'Pacific/Pitcairn', 'en-PN', _KML.ANSI,
662 'Pitcairn', None, 117),
663 Region(
664 'pm', 'xkb:pm::fra', 'America/Miquelon', 'fr-PM', _KML.ANSI,
665 'Saint Pierre and Miquelon', None, 118),
666 Region(
667 'zm', 'xkb:zm::eng', 'Africa/Lusaka',
668 ['en-ZM', 'bem', 'loz', 'lun', 'lue', 'ny', 'toi'], _KML.ANSI,
669 'Zambia', None, 119),
670 Region(
671 'eh', 'xkb:eh::ara', 'Africa/El_Aaiun', ['ar', 'mey'],
672 _KML.ANSI, 'Western Sahara', None, 120),
673 Region(
674 'ee', 'xkb:ee::est', 'Europe/Tallinn', ['et', 'ru', 'en-GB'], _KML.ISO,
675 'Estonia', None, 121),
676 Region(
677 'eg', 'xkb:eg::ara', 'Africa/Cairo', ['ar-EG', 'en', 'fr'],
678 _KML.ANSI, 'Egypt', None, 122),
679 Region(
680 'ec', 'xkb:ec::spa', ['America/Guayaquil', 'Pacific/Galapagos'],
681 'es-EC', _KML.ANSI, 'Ecuador', None, 123),
682 Region(
683 'sb', 'xkb:sb::eng', 'Pacific/Guadalcanal', ['en-SB', 'tpi'],
684 _KML.ANSI, 'Solomon Islands', None, 124),
685 Region(
686 'et', 'xkb:et::amh', 'Africa/Addis_Ababa',
687 ['am', 'en-ET', 'om-ET', 'ti-ET', 'so-ET', 'sid'], _KML.ANSI,
688 'Ethiopia', None, 125),
689 Region(
690 'so', 'xkb:so::som', 'Africa/Mogadishu',
691 ['so-SO', 'ar-SO', 'it', 'en-SO'], _KML.ANSI, 'Somalia', None, 126),
692 Region(
693 'zw', 'xkb:zw::eng', 'Africa/Harare', ['en-ZW', 'sn', 'nr', 'nd'],
694 _KML.ANSI, 'Zimbabwe', None, 127),
695 Region(
696 'sa', 'xkb:us::eng', 'Asia/Riyadh', 'ar-SA', _KML.ANSI,
697 'Saudi Arabia', None, 128),
698 Region(
699 'er', 'xkb:er::aar', 'Africa/Asmara',
700 ['aa-ER', 'ar', 'tig', 'kun', 'ti-ER'], _KML.ANSI, 'Eritrea', None,
701 129),
702 Region(
703 'me', 'xkb:me::srp', 'Europe/Podgorica',
704 ['sr', 'hu', 'bs', 'sq', 'hr', 'rom'], _KML.ANSI, 'Montenegro',
705 None, 130),
706 Region(
707 'md', 'xkb:md::ron', 'Europe/Chisinau', ['ro', 'ru', 'gag', 'tr'],
708 _KML.ANSI, 'Moldova', None, 131),
709 Region(
710 'mg', 'xkb:mg::fra', 'Indian/Antananarivo', ['fr-MG', 'mg'],
711 _KML.ANSI, 'Madagascar', None, 132),
712 Region(
713 'mf', 'xkb:mf::fra', 'America/Marigot', 'fr', _KML.ANSI,
714 'Saint Martin', None, 133),
715 Region(
716 'ma', 'xkb:ma::ara', 'Africa/Casablanca', ['ar-MA', 'fr'],
717 _KML.ANSI, 'Morocco', None, 134),
718 Region(
719 'mc', 'xkb:mc::fra', 'Europe/Monaco', ['fr-MC', 'en', 'it'],
720 _KML.ANSI, 'Monaco', None, 135),
721 Region(
722 'uz', 'xkb:uz::uzb', ['Asia/Samarkand', 'Asia/Tashkent'],
723 ['uz', 'ru', 'tg'], _KML.ANSI, 'Uzbekistan', None, 136),
724 Region(
725 'mm', 'xkb:mm::mya', 'Asia/Rangoon', 'my', _KML.ANSI, 'Myanmar',
726 None, 137),
727 Region(
728 'ml', 'xkb:ml::fra', 'Africa/Bamako', ['fr-ML', 'bm'],
729 _KML.ANSI, 'Mali', None, 138),
730 Region(
731 'mo', 'xkb:mo::zho', 'Asia/Macau', ['zh', 'zh-MO', 'pt'],
732 _KML.ANSI, 'Macao', None, 139),
733 Region(
734 'mn', 'xkb:mn::mon',
735 ['Asia/Ulaanbaatar', 'Asia/Hovd', 'Asia/Choibalsan'],
736 ['mn', 'ru'], _KML.ANSI, 'Mongolia', None, 140),
737 Region(
738 'mh', 'xkb:mh::mah', ['Pacific/Majuro', 'Pacific/Kwajalein'],
739 ['mh', 'en-MH'], _KML.ANSI, 'Marshall Islands', None, 141),
740 Region(
741 'mk', 'xkb:mk::mkd', 'Europe/Skopje',
742 ['mk', 'sq', 'tr', 'rmm', 'sr'], _KML.ANSI, 'Macedonia', None, 142),
743 Region(
744 'mu', 'xkb:mu::eng', 'Indian/Mauritius', ['en-MU', 'bho', 'fr'],
745 _KML.ANSI, 'Mauritius', None, 143),
746 Region(
747 'mt', ['xkb:us::eng', 'xkb:mt::mlt'], 'Europe/Malta', ['mt', 'en-GB'],
748 _KML.ISO, 'Malta', None, 144),
749 Region(
750 'mw', 'xkb:mw::nya', 'Africa/Blantyre',
751 ['ny', 'yao', 'tum', 'swk'], _KML.ANSI, 'Malawi', None, 145),
752 Region(
753 'mv', 'xkb:mv::div', 'Indian/Maldives', ['dv', 'en'], _KML.ANSI,
754 'Maldives', None, 146),
755 Region(
756 'mq', 'xkb:mq::fra', 'America/Martinique', 'fr-MQ', _KML.ANSI,
757 'Martinique', None, 147),
758 Region(
759 'mp', 'xkb:us::eng', 'Pacific/Saipan',
760 ['fil', 'tl', 'zh', 'ch-MP', 'en-MP'], _KML.ANSI,
761 'Northern Mariana Islands', None, 148),
762 Region(
763 'ms', 'xkb:ms::eng', 'America/Montserrat', 'en-MS', _KML.ANSI,
764 'Montserrat', None, 149),
765 Region(
766 'mr', 'xkb:mr::ara', 'Africa/Nouakchott',
767 ['ar-MR', 'fuc', 'snk', 'fr', 'mey', 'wo'], _KML.ANSI,
768 'Mauritania', None, 150),
769 Region(
770 'im', 'xkb:im::eng', 'Europe/Isle_of_Man', ['en', 'gv'],
771 _KML.ANSI, 'Isle of Man', None, 151),
772 Region(
773 'ug', 'xkb:ug::eng', 'Africa/Kampala',
774 ['en-UG', 'lg', 'sw', 'ar'], _KML.ANSI, 'Uganda', None, 152),
775 Region(
776 'tz', 'xkb:tz::swa', 'Africa/Dar_es_Salaam',
777 ['sw-TZ', 'en', 'ar'], _KML.ANSI, 'Tanzania', None, 153),
778 Region(
779 'mx', 'xkb:mx::spa',
780 ['America/Mexico_City', 'America/Cancun', 'America/Merida',
781 'America/Monterrey', 'America/Matamoros', 'America/Mazatlan',
782 'America/Chihuahua', 'America/Ojinaga', 'America/Hermosillo',
783 'America/Tijuana', 'America/Santa_Isabel',
784 'America/Bahia_Banderas'], 'es-MX', _KML.ANSI, 'Mexico', None, 154),
785 Region(
786 'io', 'xkb:io::eng', 'Indian/Chagos', 'en-IO', _KML.ANSI,
787 'British Indian Ocean Territory', None, 155),
788 Region(
789 'sh', 'xkb:sh::eng', 'Atlantic/St_Helena', 'en-SH', _KML.ANSI,
790 'Saint Helena', None, 156),
791 Region(
792 'fj', 'xkb:fj::eng', 'Pacific/Fiji', ['en-FJ', 'fj'], _KML.ANSI,
793 'Fiji', None, 157),
794 Region(
795 'fk', 'xkb:fk::eng', 'Atlantic/Stanley', 'en-FK', _KML.ANSI,
796 'Falkland Islands', None, 158),
797 Region(
798 'fm', 'xkb:fm::eng',
799 ['Pacific/Chuuk', 'Pacific/Pohnpei', 'Pacific/Kosrae'],
800 ['en-FM', 'chk', 'pon', 'yap', 'kos', 'uli', 'woe', 'nkr', 'kpg'],
801 _KML.ANSI, 'Micronesia', None, 159),
802 Region(
803 'fo', 'xkb:fo::fao', 'Atlantic/Faroe', ['fo', 'da-FO'],
804 _KML.ANSI, 'Faroe Islands', None, 160),
805 Region(
806 'ni', 'xkb:ni::spa', 'America/Managua', ['es-NI', 'en'],
807 _KML.ANSI, 'Nicaragua', None, 161),
808 Region(
809 'no', 'xkb:no::nor', 'Europe/Oslo',
810 ['no', 'nb', 'nn', 'se', 'fi'], _KML.ISO, 'Norway', None, 162),
811 Region(
812 'na', 'xkb:na::eng', 'Africa/Windhoek',
813 ['en-NA', 'af', 'de', 'hz', 'naq'], _KML.ANSI, 'Namibia', None, 163),
814 Region(
815 'vu', 'xkb:vu::bis', 'Pacific/Efate', ['bi', 'en-VU', 'fr-VU'],
816 _KML.ANSI, 'Vanuatu', None, 164),
817 Region(
818 'nc', 'xkb:nc::fra', 'Pacific/Noumea', 'fr-NC', _KML.ANSI,
819 'New Caledonia', None, 165),
820 Region(
821 'ne', 'xkb:ne::fra', 'Africa/Niamey',
822 ['fr-NE', 'ha', 'kr', 'dje'], _KML.ANSI, 'Niger', None, 166),
823 Region(
824 'nf', 'xkb:nf::eng', 'Pacific/Norfolk', 'en-NF', _KML.ANSI,
825 'Norfolk Island', None, 167),
826 Region(
827 'np', 'xkb:np::nep', 'Asia/Kathmandu', ['ne', 'en'], _KML.ANSI,
828 'Nepal', None, 168),
829 Region(
830 'nr', 'xkb:nr::nau', 'Pacific/Nauru', ['na', 'en-NR'],
831 _KML.ANSI, 'Nauru', None, 169),
832 Region(
833 'nu', 'xkb:us::eng', 'Pacific/Niue', ['niu', 'en-NU'],
834 _KML.ANSI, 'Niue', None, 170),
835 Region(
836 'ck', 'xkb:ck::eng', 'Pacific/Rarotonga', ['en-CK', 'mi'],
837 _KML.ANSI, 'Cook Islands', None, 171),
838 Region(
839 'ci', 'xkb:ci::fra', 'Africa/Abidjan', 'fr-CI', _KML.ANSI,
840 'Ivory Coast', None, 172),
841 Region(
842 'co', 'xkb:co::spa', 'America/Bogota', 'es-CO', _KML.ANSI,
843 'Colombia', None, 173),
844 Region(
845 'cn', 'xkb:us::eng', 'Asia/Shanghai', 'zh-CN', _KML.ANSI, 'China',
846 None, 174),
847 Region(
848 'cm', 'xkb:cm::eng', 'Africa/Douala', ['en-CM', 'fr-CM'],
849 _KML.ANSI, 'Cameroon', None, 175),
850 Region(
851 'cl', 'xkb:cl::spa', ['America/Santiago', 'Pacific/Easter'],
852 'es-CL', _KML.ANSI, 'Chile', None, 176),
853 Region(
854 'cc', 'xkb:cc::msa', 'Indian/Cocos', ['ms-CC', 'en'], _KML.ANSI,
855 'Cocos Islands', None, 177),
856 Region(
857 'cg', 'xkb:cg::fra', 'Africa/Brazzaville',
858 ['fr-CG', 'kg', 'ln-CG'], _KML.ANSI, 'Republic of the Congo', None,
859 178),
860 Region(
861 'cf', 'xkb:cf::fra', 'Africa/Bangui', ['fr-CF', 'sg', 'ln', 'kg'],
862 _KML.ANSI, 'Central African Republic', None, 179),
863 Region(
864 'cd', 'xkb:cd::fra', ['Africa/Kinshasa', 'Africa/Lubumbashi'],
865 ['fr-CD', 'ln', 'kg'], _KML.ANSI,
866 'Democratic Republic of the Congo', None, 180),
867 Region(
868 'cy', 'xkb:cy::ell', 'Asia/Nicosia', ['el-CY', 'tr-CY', 'en'],
869 _KML.ANSI, 'Cyprus', None, 181),
870 Region(
871 'cx', 'xkb:cx::eng', 'Indian/Christmas', ['en', 'zh', 'ms-CC'],
872 _KML.ANSI, 'Christmas Island', None, 182),
873 Region(
874 'cr', 'xkb:cr::spa', 'America/Costa_Rica', ['es-CR', 'en'],
875 _KML.ANSI, 'Costa Rica', None, 183),
876 Region(
877 'cw', 'xkb:cw::nld', 'America/Curacao', ['nl', 'pap'],
878 _KML.ANSI, 'Curacao', None, 184),
879 Region(
880 'cv', 'xkb:cv::por', 'Atlantic/Cape_Verde', 'pt-CV', _KML.ANSI,
881 'Cape Verde', None, 185),
882 Region(
883 'cu', 'xkb:cu::spa', 'America/Havana', 'es-CU', _KML.ANSI, 'Cuba',
884 None, 186),
885 Region(
886 'sz', 'xkb:sz::eng', 'Africa/Mbabane', ['en-SZ', 'ss-SZ'],
887 _KML.ANSI, 'Swaziland', None, 187),
888 Region(
889 'sy', 'xkb:sy::ara', 'Asia/Damascus',
890 ['ar-SY', 'ku', 'hy', 'arc', 'fr', 'en'], _KML.ANSI, 'Syria', None,
891 188),
892 Region(
893 'sx', 'xkb:sx::nld', 'America/Lower_Princes', ['nl', 'en'],
894 _KML.ANSI, 'Sint Maarten', None, 189),
895 Region(
896 'kg', 'xkb:kg::kir', 'Asia/Bishkek', ['ky', 'uz', 'ru'],
897 _KML.ANSI, 'Kyrgyzstan', None, 190),
898 Region(
899 'ke', 'xkb:ke::eng', 'Africa/Nairobi', ['en-KE', 'sw-KE'],
900 _KML.ANSI, 'Kenya', None, 191),
901 Region(
902 'ss', 'xkb:ss::eng', 'Africa/Juba', 'en', _KML.ANSI,
903 'South Sudan', None, 192),
904 Region(
905 'sr', 'xkb:sr::nld', 'America/Paramaribo',
906 ['nl-SR', 'en', 'srn', 'hns', 'jv'], _KML.ANSI, 'Suriname', None, 193),
907 Region(
908 'ki', 'xkb:ki::eng',
909 ['Pacific/Tarawa', 'Pacific/Enderbury', 'Pacific/Kiritimati'],
910 ['en-KI', 'gil'], _KML.ANSI, 'Kiribati', None, 194),
911 Region(
912 'kh', 'xkb:kh::khm', 'Asia/Phnom_Penh', ['km', 'fr', 'en'],
913 _KML.ANSI, 'Cambodia', None, 195),
914 Region(
915 'kn', 'xkb:kn::eng', 'America/St_Kitts', 'en-KN', _KML.ANSI,
916 'Saint Kitts and Nevis', None, 196),
917 Region(
918 'km', 'xkb:km::ara', 'Indian/Comoro', ['ar', 'fr-KM'],
919 _KML.ANSI, 'Comoros', None, 197),
920 Region(
921 'st', 'xkb:st::por', 'Africa/Sao_Tome', 'pt-ST', _KML.ANSI,
922 'Sao Tome and Principe', None, 198),
923 Region(
924 'si', 'xkb:si::slv', 'Europe/Ljubljana',
925 ['sl', 'hu', 'it', 'sr', 'de', 'hr', 'en-GB'], _KML.ISO,
926 'Slovenia', None, 199),
927 Region(
928 'kp', 'xkb:kp::kor', 'Asia/Pyongyang', 'ko-KP', _KML.ANSI,
929 'North Korea', None, 200),
930 Region(
931 'kw', 'xkb:kw::ara', 'Asia/Kuwait', ['ar-KW', 'en'], _KML.ANSI,
932 'Kuwait', None, 201),
933 Region(
934 'sn', 'xkb:sn::fra', 'Africa/Dakar',
935 ['fr-SN', 'wo', 'fuc', 'mnk'], _KML.ANSI, 'Senegal', None, 202),
936 Region(
937 'sm', 'xkb:sm::ita', 'Europe/San_Marino', 'it-SM', _KML.ANSI,
938 'San Marino', None, 203),
939 Region(
940 'sl', 'xkb:sl::eng', 'Africa/Freetown', ['en-SL', 'men', 'tem'],
941 _KML.ANSI, 'Sierra Leone', None, 204),
942 Region(
943 'sc', 'xkb:sc::eng', 'Indian/Mahe', ['en-SC', 'fr-SC'],
944 _KML.ANSI, 'Seychelles', None, 205),
945 Region(
946 'kz', 'xkb:kz::kaz',
947 ['Asia/Almaty', 'Asia/Qyzylorda', 'Asia/Aqtobe', 'Asia/Aqtau',
948 'Asia/Oral'], ['kk', 'ru'], _KML.ANSI, 'Kazakhstan', None, 206),
949 Region(
950 'ky', 'xkb:ky::eng', 'America/Cayman', 'en-KY', _KML.ANSI,
951 'Cayman Islands', None, 207),
952 Region(
953 'sd', 'xkb:sd::ara', 'Africa/Khartoum', ['ar-SD', 'en', 'fia'],
954 _KML.ANSI, 'Sudan', None, 208),
955 Region(
956 'do', 'xkb:do::spa', 'America/Santo_Domingo', 'es-DO',
957 _KML.ANSI, 'Dominican Republic', None, 209),
958 Region(
959 'dm', 'xkb:dm::eng', 'America/Dominica', 'en-DM', _KML.ANSI,
960 'Dominica', None, 210),
961 Region(
962 'dj', 'xkb:dj::fra', 'Africa/Djibouti',
963 ['fr-DJ', 'ar', 'so-DJ', 'aa'], _KML.ANSI, 'Djibouti', None, 211),
964 Region(
965 'dk', 'xkb:dk::dan', 'Europe/Copenhagen',
966 ['da-DK', 'en', 'fo', 'de-DK'], _KML.ISO, 'Denmark', None, 212),
967 Region(
968 'vg', 'xkb:vg::eng', 'America/Tortola', 'en-VG', _KML.ANSI,
969 'British Virgin Islands', None, 213),
970 Region(
971 'ye', 'xkb:ye::ara', 'Asia/Aden', 'ar-YE', _KML.ANSI, 'Yemen',
972 None, 214),
973 Region(
974 'dz', 'xkb:dz::ara', 'Africa/Algiers', 'ar-DZ', _KML.ANSI,
975 'Algeria', None, 215),
976 Region(
977 'uy', 'xkb:uy::spa', 'America/Montevideo', 'es-UY', _KML.ANSI,
978 'Uruguay', None, 216),
979 Region(
980 'yt', 'xkb:yt::fra', 'Indian/Mayotte', 'fr-YT', _KML.ANSI,
981 'Mayotte', None, 217),
982 Region(
983 'um', 'xkb:um::eng',
984 ['Pacific/Johnston', 'Pacific/Midway', 'Pacific/Wake'], 'en-UM',
985 _KML.ANSI, 'United States Minor Outlying Islands', None, 218),
986 Region(
987 'lb', 'xkb:lb::ara', 'Asia/Beirut',
988 ['ar-LB', 'fr-LB', 'en', 'hy'], _KML.ANSI, 'Lebanon', None, 219),
989 Region(
990 'lc', 'xkb:lc::eng', 'America/St_Lucia', 'en-LC', _KML.ANSI,
991 'Saint Lucia', None, 220),
992 Region(
993 'la', 'xkb:la::lao', 'Asia/Vientiane', ['lo', 'fr', 'en'],
994 _KML.ANSI, 'Laos', None, 221),
995 Region(
996 'tv', 'xkb:us::eng', 'Pacific/Funafuti',
997 ['tvl', 'en', 'sm', 'gil'], _KML.ANSI, 'Tuvalu', None, 222),
998 Region(
999 'tt', 'xkb:tt::eng', 'America/Port_of_Spain',
1000 ['en-TT', 'hns', 'fr', 'es', 'zh'], _KML.ANSI,
1001 'Trinidad and Tobago', None, 223),
1002 Region(
1003 'tr', 'xkb:tr::tur', 'Europe/Istanbul',
1004 ['tr', 'ku', 'diq', 'az', 'av'], _KML.ISO, 'Turkey', None, 224),
1005 Region(
1006 'lk', 'xkb:lk::sin', 'Asia/Colombo', ['si', 'ta', 'en'],
1007 _KML.ANSI, 'Sri Lanka', None, 225),
1008 Region(
1009 'li', 'xkb:ch::ger', 'Europe/Vaduz', ['de', 'en-GB'], _KML.ISO,
1010 'Liechtenstein', None, 226),
1011 Region(
1012 'lv', 'xkb:lv:apostrophe:lav', 'Europe/Riga',
1013 ['lv', 'lt', 'ru', 'en-GB'], _KML.ISO, 'Latvia', None, 227),
1014 Region(
1015 'to', 'xkb:to::ton', 'Pacific/Tongatapu', ['to', 'en-TO'],
1016 _KML.ANSI, 'Tonga', None, 228),
1017 Region(
1018 'lt', 'xkb:lt::lit', 'Europe/Vilnius', ['lt', 'ru', 'pl', 'en-GB'],
1019 _KML.ISO, 'Lithuania', None, 229),
1020 Region(
1021 'lu', 'xkb:lu::ltz', 'Europe/Luxembourg',
1022 ['lb', 'de-LU', 'fr-LU'], _KML.ANSI, 'Luxembourg', None, 230),
1023 Region(
1024 'lr', 'xkb:lr::eng', 'Africa/Monrovia', 'en-LR', _KML.ANSI,
1025 'Liberia', None, 231),
1026 Region(
1027 'ls', 'xkb:ls::eng', 'Africa/Maseru', ['en-LS', 'st', 'zu', 'xh'],
1028 _KML.ANSI, 'Lesotho', None, 232),
1029 Region(
1030 'tf', 'xkb:tf::fra', 'Indian/Kerguelen', 'fr', _KML.ANSI,
1031 'French Southern Territories', None, 233),
1032 Region(
1033 'tg', 'xkb:tg::fra', 'Africa/Lome',
1034 ['fr-TG', 'ee', 'hna', 'kbp', 'dag', 'ha'], _KML.ANSI, 'Togo',
1035 None, 234),
1036 Region(
1037 'td', 'xkb:td::fra', 'Africa/Ndjamena', ['fr-TD', 'ar-TD', 'sre'],
1038 _KML.ANSI, 'Chad', None, 235),
1039 Region(
1040 'tc', 'xkb:tc::eng', 'America/Grand_Turk', 'en-TC', _KML.ANSI,
1041 'Turks and Caicos Islands', None, 236),
1042 Region(
1043 'ly', 'xkb:ly::ara', 'Africa/Tripoli', ['ar-LY', 'it', 'en'],
1044 _KML.ANSI, 'Libya', None, 237),
1045 Region(
1046 'va', 'xkb:va::lat', 'Europe/Vatican', ['la', 'it', 'fr'],
1047 _KML.ANSI, 'Vatican', None, 238),
1048 Region(
1049 'vc', 'xkb:vc::eng', 'America/St_Vincent', ['en-VC', 'fr'],
1050 _KML.ANSI, 'Saint Vincent and the Grenadines', None, 239),
1051 Region(
1052 'ad', 'xkb:ad::cat', 'Europe/Andorra', 'ca', _KML.ANSI, 'Andorra',
1053 None, 240),
1054 Region(
1055 'ag', 'xkb:ag::eng', 'America/Antigua', 'en-AG', _KML.ANSI,
1056 'Antigua and Barbuda', None, 241),
1057 Region(
1058 'af', 'xkb:af::fas', 'Asia/Kabul', ['fa-AF', 'ps', 'uz-AF', 'tk'],
1059 _KML.ANSI, 'Afghanistan', None, 242),
1060 Region(
1061 'ai', 'xkb:ai::eng', 'America/Anguilla', 'en-AI', _KML.ANSI,
1062 'Anguilla', None, 243),
1063 Region(
1064 'vi', 'xkb:vi::eng', 'America/St_Thomas', 'en-VI', _KML.ANSI,
1065 'U.S. Virgin Islands', None, 244),
1066 Region(
1067 'is', 'xkb:is::ice', 'Atlantic/Reykjavik',
1068 ['is', 'en-GB', 'da', 'de'], _KML.ISO, 'Iceland', None, 245),
1069 Region(
1070 'ir', 'xkb:ir::fas', 'Asia/Tehran', ['fa-IR', 'ku'], _KML.ANSI,
1071 'Iran', None, 246),
1072 Region(
1073 'am', 'xkb:am::hye', 'Asia/Yerevan', 'hy', _KML.ANSI, 'Armenia',
1074 None, 247),
1075 Region(
1076 'al', 'xkb:al::sqi', 'Europe/Tirane', ['sq', 'el'], _KML.ANSI,
1077 'Albania', None, 248),
1078 Region(
1079 'ao', 'xkb:ao::por', 'Africa/Luanda', 'pt-AO', _KML.ANSI,
1080 'Angola', None, 249),
1081 Region(
1082 'as', 'xkb:as::eng', 'Pacific/Pago_Pago', ['en-AS', 'sm', 'to'],
1083 _KML.ANSI, 'American Samoa', None, 250),
1084 Region(
1085 'ar', 'xkb:ar::spa',
1086 ['America/Argentina/Buenos_Aires', 'America/Argentina/Cordoba',
1087 'America/Argentina/Salta', 'America/Argentina/Jujuy',
1088 'America/Argentina/Tucuman', 'America/Argentina/Catamarca',
1089 'America/Argentina/La_Rioja', 'America/Argentina/San_Juan',
1090 'America/Argentina/Mendoza', 'America/Argentina/San_Luis',
1091 'America/Argentina/Rio_Gallegos', 'America/Argentina/Ushuaia'],
1092 ['es-AR', 'en', 'it', 'de', 'fr', 'gn'], _KML.ANSI, 'Argentina',
1093 None, 251),
1094 Region(
1095 'aw', 'xkb:aw::nld', 'America/Aruba', ['nl-AW', 'es', 'en'],
1096 _KML.ANSI, 'Aruba', None, 252),
1097 Region(
1098 'ax', 'xkb:ax::swe', 'Europe/Mariehamn', 'sv-AX', _KML.ANSI,
1099 'Aland Islands', None, 253),
1100 Region(
1101 'az', 'xkb:az::aze', 'Asia/Baku', ['az', 'ru', 'hy'], _KML.ANSI,
1102 'Azerbaijan', None, 254),
1103 Region(
1104 'ua', 'xkb:ua::ukr',
1105 ['Europe/Kiev', 'Europe/Uzhgorod', 'Europe/Zaporozhye'],
1106 ['uk', 'ru-UA', 'rom', 'pl', 'hu'], _KML.ANSI, 'Ukraine', None, 255),
1107 Region(
1108 'qa', 'xkb:qa::ara', 'Asia/Qatar', ['ar-QA', 'es'], _KML.ANSI,
1109 'Qatar', None, 256),
1110 Region(
1111 'mz', 'xkb:mz::por', 'Africa/Maputo', ['pt-MZ', 'vmw'],
1112 _KML.ANSI, 'Mozambique', None, 257)]
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001113"""A list of :py:class:`regions.Region` objects for
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +08001114**unconfirmed** regions. These may contain incorrect information (or not
1115supported by Chrome browser yet), and all fields must be reviewed before launch.
1116See http://goto/vpdsettings.
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001117
1118Currently, non-Latin keyboards must use an underlying Latin keyboard
1119for VPD. (This assumption should be revisited when moving items to
1120:py:data:`regions.Region.REGIONS_LIST`.) This is
1121currently being discussed on <http://crbug.com/325389>.
1122
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +08001123Some timezones or locales may be missing from ``timezone_settings.cc`` (see
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001124http://crosbug.com/p/23902). This must be rectified before moving
1125items to :py:data:`regions.Region.REGIONS_LIST`.
1126"""
1127
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001128
1129def ConsolidateRegions(regions):
1130 """Consolidates a list of regions into a dict.
1131
1132 Args:
1133 regions: A list of Region objects. All objects for any given
1134 region code must be identical or we will throw an exception.
1135 (We allow duplicates in case identical region objects are
1136 defined in both regions.py and the overlay, e.g., when moving
1137 items to the public overlay.)
1138
1139 Returns:
1140 A dict from region code to Region.
1141
1142 Raises:
1143 RegionException: If there are multiple regions defined for a given
1144 region, and the values for those regions differ.
1145 """
1146 # Build a dict from region_code to the first Region with that code.
1147 region_dict = {}
1148 for r in regions:
1149 existing_region = region_dict.get(r.region_code)
1150 if existing_region:
1151 if existing_region.GetFieldsDict() != r.GetFieldsDict():
1152 raise RegionException(
1153 'Conflicting definitions for region %r: %r, %r' %
1154 (r.region_code, existing_region.GetFieldsDict(),
1155 r.GetFieldsDict()))
1156 else:
1157 region_dict[r.region_code] = r
1158
1159 return region_dict
1160
1161
1162def BuildRegionsDict(include_all=False):
1163 """Builds a dictionary mapping from code to :py:class:`regions.Region` object.
1164
1165 The regions include:
1166
1167 * :py:data:`regions.REGIONS_LIST`
1168 * :py:data:`regions_overlay.REGIONS_LIST`
1169 * Only if ``include_all`` is true:
1170
1171 * :py:data:`regions.UNCONFIRMED_REGIONS_LIST`
1172 * :py:data:`regions.INCOMPLETE_REGIONS_LIST`
1173
1174 A region may only appear in one of the above lists, or this function
1175 will (deliberately) fail.
1176 """
1177 regions = list(REGIONS_LIST)
1178 if include_all:
Hung-Te Lin8f8e0c42015-04-13 11:42:42 +08001179 known_codes = [r.region_code for r in regions]
1180 regions += [r for r in UNCONFIRMED_REGIONS_LIST if r.region_code not in
1181 known_codes]
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001182
1183 # Build dictionary of region code to list of regions with that
1184 # region code. Check manually for duplicates, since the region may
1185 # be present both in the overlay and the public repo.
1186 return ConsolidateRegions(regions)
1187
1188
1189REGIONS = BuildRegionsDict()
1190
1191
1192def main(args=sys.argv[1:], out=None):
1193 parser = argparse.ArgumentParser(description=(
1194 'Display all known regions and their parameters. '))
1195 parser.add_argument('--format',
1196 choices=('human-readable', 'csv', 'json', 'yaml'),
1197 default='human-readable',
1198 help='Output format (default=%(default)s)')
1199 parser.add_argument('--all', action='store_true',
1200 help='Include unconfirmed and incomplete regions')
1201 parser.add_argument('--output', default=None,
1202 help='Specify output file')
Hung-Te Lin34f3d382015-04-10 18:18:23 +08001203 parser.add_argument('--overlay', default=None,
1204 help='Specify a Python file to overlay extra data')
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001205 args = parser.parse_args(args)
1206
Hung-Te Lin34f3d382015-04-10 18:18:23 +08001207 if args.overlay is not None:
1208 execfile(args.overlay)
1209
Hung-Te Lin1a14cc42015-04-14 01:23:34 +08001210 if args.all:
1211 # Add an additional 'confirmed' property to help identifying region status,
1212 # for autotests, unit tests and factory module.
1213 Region.FIELDS.insert(1, 'confirmed')
1214 for r in REGIONS_LIST:
1215 r.confirmed = True
1216 for r in UNCONFIRMED_REGIONS_LIST:
1217 r.confirmed = False
1218
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001219 regions_dict = BuildRegionsDict(args.all)
Hung-Te Lin34f3d382015-04-10 18:18:23 +08001220
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001221 if out is None:
1222 if args.output is None:
1223 out = sys.stdout
1224 else:
1225 out = open(args.output, 'w')
1226
1227 # Handle YAML and JSON output.
1228 if args.format == 'yaml' or args.format == 'json':
1229 data = {}
1230 for region in regions_dict.values():
1231 item = {}
1232 for field in Region.FIELDS:
1233 item[field] = getattr(region, field)
1234 data[region.region_code] = item
1235 if args.format == 'yaml':
1236 yaml.dump(data, out)
1237 else:
1238 json.dump(data, out)
1239 return
1240
1241 # Handle CSV or plain-text output: build a list of lines to print.
Hung-Te Lin1a14cc42015-04-14 01:23:34 +08001242 # The CSV format is for publishing discussion spreadsheet so 'notes' should be
1243 # added.
1244 if args.format == 'csv':
1245 Region.FIELDS += ['notes']
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001246 lines = [Region.FIELDS]
1247
1248 def CoerceToString(value):
1249 """Returns the arguments in simple string type.
1250
1251 If value is a list, concatenate its values with commas. Otherwise, just
1252 return value.
1253 """
1254 if isinstance(value, list):
1255 return ','.join(value)
1256 else:
1257 return str(value)
Hung-Te Lin1a14cc42015-04-14 01:23:34 +08001258
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001259 for region in sorted(regions_dict.values(), key=lambda v: v.region_code):
1260 lines.append([CoerceToString(getattr(region, field))
1261 for field in Region.FIELDS])
1262
1263 if args.format == 'csv':
Hung-Te Lin1a14cc42015-04-14 01:23:34 +08001264 # Just print the lines in CSV format. Note the values may include ',' so the
1265 # separator must be tab.
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001266 for l in lines:
Hung-Te Lin1a14cc42015-04-14 01:23:34 +08001267 print('\t'.join(l))
Hung-Te Lin76c55b22015-03-31 14:47:14 +08001268 elif args.format == 'human-readable':
1269 num_columns = len(lines[0])
1270
1271 # Calculate maximum length of each column.
1272 max_lengths = []
1273 for column_no in xrange(num_columns):
1274 max_lengths.append(max(len(line[column_no]) for line in lines))
1275
1276 # Print each line, padding as necessary to the max column length.
1277 for line in lines:
1278 for column_no in xrange(num_columns):
1279 out.write(line[column_no].ljust(max_lengths[column_no] + 2))
1280 out.write('\n')
1281 else:
1282 exit('Sorry, unknown format specified: %s' % args.format)
1283
1284
1285if __name__ == '__main__':
1286 main()