{
    "file_diffs": [
        {
            "old_file_content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"Translation methods for generating localized strings.\n\nTo load a locale and generate a translated string::\n\n    user_locale = tornado.locale.get(\"es_LA\")\n    print user_locale.translate(\"Sign out\")\n\n`tornado.locale.get()` returns the closest matching locale, not necessarily the\nspecific locale you requested. You can support pluralization with\nadditional arguments to `~Locale.translate()`, e.g.::\n\n    people = [...]\n    message = user_locale.translate(\n        \"%(list)s is online\", \"%(list)s are online\", len(people))\n    print message % {\"list\": user_locale.list(people)}\n\nThe first string is chosen if ``len(people) == 1``, otherwise the second\nstring is chosen.\n\nApplications should call one of `load_translations` (which uses a simple\nCSV format) or `load_gettext_translations` (which uses the ``.mo`` format\nsupported by `gettext` and related tools).  If neither method is called,\nthe `Locale.translate` method will simply return the original string.\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport csv\nimport datetime\nimport os\nimport re\n\nfrom tornado import escape\nfrom tornado.log import gen_log\nfrom tornado.util import u\n\n_default_locale = \"en_US\"\n_translations = {}\n_supported_locales = frozenset([_default_locale])\n_use_gettext = False\n\n\ndef get(*locale_codes):\n    \"\"\"Returns the closest match for the given locale codes.\n\n    We iterate over all given locale codes in order. If we have a tight\n    or a loose match for the code (e.g., \"en\" for \"en_US\"), we return\n    the locale. Otherwise we move to the next code in the list.\n\n    By default we return ``en_US`` if no translations are found for any of\n    the specified locales. You can change the default locale with\n    `set_default_locale()`.\n    \"\"\"\n    return Locale.get_closest(*locale_codes)\n\n\ndef set_default_locale(code):\n    \"\"\"Sets the default locale.\n\n    The default locale is assumed to be the language used for all strings\n    in the system. The translations loaded from disk are mappings from\n    the default locale to the destination locale. Consequently, you don't\n    need to create a translation file for the default locale.\n    \"\"\"\n    global _default_locale\n    global _supported_locales\n    _default_locale = code\n    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])\n\n\ndef load_translations(directory):\n    \"\"\"Loads translations from CSV files in a directory.\n\n    Translations are strings with optional Python-style named placeholders\n    (e.g., ``My name is %(name)s``) and their associated translations.\n\n    The directory should have translation files of the form ``LOCALE.csv``,\n    e.g. ``es_GT.csv``. The CSV files should have two or three columns: string,\n    translation, and an optional plural indicator. Plural indicators should\n    be one of \"plural\" or \"singular\". A given string can have both singular\n    and plural forms. For example ``%(name)s liked this`` may have a\n    different verb conjugation depending on whether %(name)s is one\n    name or a list of names. There should be two rows in the CSV file for\n    that string, one with plural indicator \"singular\", and one \"plural\".\n    For strings with no verbs that would change on translation, simply\n    use \"unknown\" or the empty string (or don't include the column at all).\n\n    The file is read using the `csv` module in the default \"excel\" dialect.\n    In this format there should not be spaces after the commas.\n\n    Example translation ``es_LA.csv``::\n\n        \"I love you\",\"Te amo\"\n        \"%(name)s liked this\",\"A %(name)s les gustó esto\",\"plural\"\n        \"%(name)s liked this\",\"A %(name)s le gustó esto\",\"singular\"\n\n    \"\"\"\n    global _translations\n    global _supported_locales\n    _translations = {}\n    for path in os.listdir(directory):\n        if not path.endswith(\".csv\"):\n            continue\n        locale, extension = path.split(\".\")\n        if not re.match(\"[a-z]+(_[A-Z]+)?$\", locale):\n            gen_log.error(\"Unrecognized locale %r (path: %s)\", locale,\n                          os.path.join(directory, path))\n            continue\n        full_path = os.path.join(directory, path)\n        try:\n            # python 3: csv.reader requires a file open in text mode.\n            # Force utf8 to avoid dependence on $LANG environment variable.\n            f = open(full_path, \"r\", encoding=\"utf-8\")\n        except TypeError:\n            # python 2: files return byte strings, which are decoded below.\n            f = open(full_path, \"r\")\n        _translations[locale] = {}\n        for i, row in enumerate(csv.reader(f)):\n            if not row or len(row) < 2:\n                continue\n            row = [escape.to_unicode(c).strip() for c in row]\n            english, translation = row[:2]\n            if len(row) > 2:\n                plural = row[2] or \"unknown\"\n            else:\n                plural = \"unknown\"\n            if plural not in (\"plural\", \"singular\", \"unknown\"):\n                gen_log.error(\"Unrecognized plural indicator %r in %s line %d\",\n                              plural, path, i + 1)\n                continue\n            _translations[locale].setdefault(plural, {})[english] = translation\n        f.close()\n    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])\n    gen_log.debug(\"Supported locales: %s\", sorted(_supported_locales))\n\n\ndef load_gettext_translations(directory, domain):\n    \"\"\"Loads translations from `gettext`'s locale tree\n\n    Locale tree is similar to system's ``/usr/share/locale``, like::\n\n        {directory}/{lang}/LC_MESSAGES/{domain}.mo\n\n    Three steps are required to have you app translated:\n\n    1. Generate POT translation file::\n\n        xgettext --language=Python --keyword=_:1,2 -d mydomain file1.py file2.html etc\n\n    2. Merge against existing POT file::\n\n        msgmerge old.po mydomain.po > new.po\n\n    3. Compile::\n\n        msgfmt mydomain.po -o {directory}/pt_BR/LC_MESSAGES/mydomain.mo\n    \"\"\"\n    import gettext\n    global _translations\n    global _supported_locales\n    global _use_gettext\n    _translations = {}\n    for lang in os.listdir(directory):\n        if lang.startswith('.'):\n            continue  # skip .svn, etc\n        if os.path.isfile(os.path.join(directory, lang)):\n            continue\n        try:\n            os.stat(os.path.join(directory, lang, \"LC_MESSAGES\", domain + \".mo\"))\n            _translations[lang] = gettext.translation(domain, directory,\n                                                      languages=[lang])\n        except Exception as e:\n            gen_log.error(\"Cannot load translation for '%s': %s\", lang, str(e))\n            continue\n    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])\n    _use_gettext = True\n    gen_log.debug(\"Supported locales: %s\", sorted(_supported_locales))\n\n\ndef get_supported_locales():\n    \"\"\"Returns a list of all the supported locale codes.\"\"\"\n    return _supported_locales\n\n\nclass Locale(object):\n    \"\"\"Object representing a locale.\n\n    After calling one of `load_translations` or `load_gettext_translations`,\n    call `get` or `get_closest` to get a Locale object.\n    \"\"\"\n    @classmethod\n    def get_closest(cls, *locale_codes):\n        \"\"\"Returns the closest match for the given locale code.\"\"\"\n        for code in locale_codes:\n            if not code:\n                continue\n            code = code.replace(\"-\", \"_\")\n            parts = code.split(\"_\")\n            if len(parts) > 2:\n                continue\n            elif len(parts) == 2:\n                code = parts[0].lower() + \"_\" + parts[1].upper()\n            if code in _supported_locales:\n                return cls.get(code)\n            if parts[0].lower() in _supported_locales:\n                return cls.get(parts[0].lower())\n        return cls.get(_default_locale)\n\n    @classmethod\n    def get(cls, code):\n        \"\"\"Returns the Locale for the given locale code.\n\n        If it is not supported, we raise an exception.\n        \"\"\"\n        if not hasattr(cls, \"_cache\"):\n            cls._cache = {}\n        if code not in cls._cache:\n            assert code in _supported_locales\n            translations = _translations.get(code, None)\n            if translations is None:\n                locale = CSVLocale(code, {})\n            elif _use_gettext:\n                locale = GettextLocale(code, translations)\n            else:\n                locale = CSVLocale(code, translations)\n            cls._cache[code] = locale\n        return cls._cache[code]\n\n    def __init__(self, code, translations):\n        self.code = code\n        self.name = LOCALE_NAMES.get(code, {}).get(\"name\", u(\"Unknown\"))\n        self.rtl = False\n        for prefix in [\"fa\", \"ar\", \"he\"]:\n            if self.code.startswith(prefix):\n                self.rtl = True\n                break\n        self.translations = translations\n\n        # Initialize strings for date formatting\n        _ = self.translate\n        self._months = [\n            _(\"January\"), _(\"February\"), _(\"March\"), _(\"April\"),\n            _(\"May\"), _(\"June\"), _(\"July\"), _(\"August\"),\n            _(\"September\"), _(\"October\"), _(\"November\"), _(\"December\")]\n        self._weekdays = [\n            _(\"Monday\"), _(\"Tuesday\"), _(\"Wednesday\"), _(\"Thursday\"),\n            _(\"Friday\"), _(\"Saturday\"), _(\"Sunday\")]\n\n    def translate(self, message, plural_message=None, count=None):\n        \"\"\"Returns the translation for the given message for this locale.\n\n        If ``plural_message`` is given, you must also provide\n        ``count``. We return ``plural_message`` when ``count != 1``,\n        and we return the singular form for the given message when\n        ``count == 1``.\n        \"\"\"\n        raise NotImplementedError()\n\n    def format_date(self, date, gmt_offset=0, relative=True, shorter=False,\n                    full_format=False):\n        \"\"\"Formats the given date (which should be GMT).\n\n        By default, we return a relative time (e.g., \"2 minutes ago\"). You\n        can return an absolute date string with ``relative=False``.\n\n        You can force a full format date (\"July 10, 1980\") with\n        ``full_format=True``.\n\n        This method is primarily intended for dates in the past.\n        For dates in the future, we fall back to full format.\n        \"\"\"\n        if self.code.startswith(\"ru\"):\n            relative = False\n        if type(date) in (int, long, float):\n            date = datetime.datetime.utcfromtimestamp(date)\n        now = datetime.datetime.utcnow()\n        if date > now:\n            if relative and (date - now).seconds < 60:\n                # Due to click skew, things are some things slightly\n                # in the future. Round timestamps in the immediate\n                # future down to now in relative mode.\n                date = now\n            else:\n                # Otherwise, future dates always use the full format.\n                full_format = True\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        local_now = now - datetime.timedelta(minutes=gmt_offset)\n        local_yesterday = local_now - datetime.timedelta(hours=24)\n        difference = now - date\n        seconds = difference.seconds\n        days = difference.days\n\n        _ = self.translate\n        format = None\n        if not full_format:\n            if relative and days == 0:\n                if seconds < 50:\n                    return _(\"1 second ago\", \"%(seconds)d seconds ago\",\n                             seconds) % {\"seconds\": seconds}\n\n                if seconds < 50 * 60:\n                    minutes = round(seconds / 60.0)\n                    return _(\"1 minute ago\", \"%(minutes)d minutes ago\",\n                             minutes) % {\"minutes\": minutes}\n\n                hours = round(seconds / (60.0 * 60))\n                return _(\"1 hour ago\", \"%(hours)d hours ago\",\n                         hours) % {\"hours\": hours}\n\n            if days == 0:\n                format = _(\"%(time)s\")\n            elif days == 1 and local_date.day == local_yesterday.day and \\\n                    relative:\n                format = _(\"yesterday\") if shorter else \\\n                    _(\"yesterday at %(time)s\")\n            elif days < 5:\n                format = _(\"%(weekday)s\") if shorter else \\\n                    _(\"%(weekday)s at %(time)s\")\n            elif days < 334:  # 11mo, since confusing for same month last year\n                format = _(\"%(month_name)s %(day)s\") if shorter else \\\n                    _(\"%(month_name)s %(day)s at %(time)s\")\n\n        if format is None:\n            format = _(\"%(month_name)s %(day)s, %(year)s\") if shorter else \\\n                _(\"%(month_name)s %(day)s, %(year)s at %(time)s\")\n\n        tfhour_clock = self.code not in (\"en\", \"en_US\", \"zh_CN\")\n        if tfhour_clock:\n            str_time = \"%d:%02d\" % (local_date.hour, local_date.minute)\n        elif self.code == \"zh_CN\":\n            str_time = \"%s%d:%02d\" % (\n                (u('\\u4e0a\\u5348'), u('\\u4e0b\\u5348'))[local_date.hour >= 12],\n                local_date.hour % 12 or 12, local_date.minute)\n        else:\n            str_time = \"%d:%02d %s\" % (\n                local_date.hour % 12 or 12, local_date.minute,\n                (\"am\", \"pm\")[local_date.hour >= 12])\n\n        return format % {\n            \"month_name\": self._months[local_date.month - 1],\n            \"weekday\": self._weekdays[local_date.weekday()],\n            \"day\": str(local_date.day),\n            \"year\": str(local_date.year),\n            \"time\": str_time\n        }\n\n    def format_day(self, date, gmt_offset=0, dow=True):\n        \"\"\"Formats the given date as a day of week.\n\n        Example: \"Monday, January 22\". You can remove the day of week with\n        ``dow=False``.\n        \"\"\"\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        _ = self.translate\n        if dow:\n            return _(\"%(weekday)s, %(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"weekday\": self._weekdays[local_date.weekday()],\n                \"day\": str(local_date.day),\n            }\n        else:\n            return _(\"%(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"day\": str(local_date.day),\n            }\n\n    def list(self, parts):\n        \"\"\"Returns a comma-separated list for the given list of parts.\n\n        The format is, e.g., \"A, B and C\", \"A and B\" or just \"A\" for lists\n        of size 1.\n        \"\"\"\n        _ = self.translate\n        if len(parts) == 0:\n            return \"\"\n        if len(parts) == 1:\n            return parts[0]\n        comma = u(' \\u0648 ') if self.code.startswith(\"fa\") else u(\", \")\n        return _(\"%(commas)s and %(last)s\") % {\n            \"commas\": comma.join(parts[:-1]),\n            \"last\": parts[len(parts) - 1],\n        }\n\n    def friendly_number(self, value):\n        \"\"\"Returns a comma-separated number for the given integer.\"\"\"\n        if self.code not in (\"en\", \"en_US\"):\n            return str(value)\n        value = str(value)\n        parts = []\n        while value:\n            parts.append(value[-3:])\n            value = value[:-3]\n        return \",\".join(reversed(parts))\n\n\nclass CSVLocale(Locale):\n    \"\"\"Locale implementation using tornado's CSV translation format.\"\"\"\n    def translate(self, message, plural_message=None, count=None):\n        if plural_message is not None:\n            assert count is not None\n            if count != 1:\n                message = plural_message\n                message_dict = self.translations.get(\"plural\", {})\n            else:\n                message_dict = self.translations.get(\"singular\", {})\n        else:\n            message_dict = self.translations.get(\"unknown\", {})\n        return message_dict.get(message, message)\n\n\nclass GettextLocale(Locale):\n    \"\"\"Locale implementation using the `gettext` module.\"\"\"\n    def __init__(self, code, translations):\n        try:\n            # python 2\n            self.ngettext = translations.ungettext\n            self.gettext = translations.ugettext\n        except AttributeError:\n            # python 3\n            self.ngettext = translations.ngettext\n            self.gettext = translations.gettext\n        # self.gettext must exist before __init__ is called, since it\n        # calls into self.translate\n        super(GettextLocale, self).__init__(code, translations)\n\n    def translate(self, message, plural_message=None, count=None):\n        if plural_message is not None:\n            assert count is not None\n            return self.ngettext(message, plural_message, count)\n        else:\n            return self.gettext(message)\n\nLOCALE_NAMES = {\n    \"af_ZA\": {\"name_en\": u(\"Afrikaans\"), \"name\": u(\"Afrikaans\")},\n    \"am_ET\": {\"name_en\": u(\"Amharic\"), \"name\": u('\\u12a0\\u121b\\u122d\\u129b')},\n    \"ar_AR\": {\"name_en\": u(\"Arabic\"), \"name\": u(\"\\u0627\\u0644\\u0639\\u0631\\u0628\\u064a\\u0629\")},\n    \"bg_BG\": {\"name_en\": u(\"Bulgarian\"), \"name\": u(\"\\u0411\\u044a\\u043b\\u0433\\u0430\\u0440\\u0441\\u043a\\u0438\")},\n    \"bn_IN\": {\"name_en\": u(\"Bengali\"), \"name\": u(\"\\u09ac\\u09be\\u0982\\u09b2\\u09be\")},\n    \"bs_BA\": {\"name_en\": u(\"Bosnian\"), \"name\": u(\"Bosanski\")},\n    \"ca_ES\": {\"name_en\": u(\"Catalan\"), \"name\": u(\"Catal\\xe0\")},\n    \"cs_CZ\": {\"name_en\": u(\"Czech\"), \"name\": u(\"\\u010ce\\u0161tina\")},\n    \"cy_GB\": {\"name_en\": u(\"Welsh\"), \"name\": u(\"Cymraeg\")},\n    \"da_DK\": {\"name_en\": u(\"Danish\"), \"name\": u(\"Dansk\")},\n    \"de_DE\": {\"name_en\": u(\"German\"), \"name\": u(\"Deutsch\")},\n    \"el_GR\": {\"name_en\": u(\"Greek\"), \"name\": u(\"\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac\")},\n    \"en_GB\": {\"name_en\": u(\"English (UK)\"), \"name\": u(\"English (UK)\")},\n    \"en_US\": {\"name_en\": u(\"English (US)\"), \"name\": u(\"English (US)\")},\n    \"es_ES\": {\"name_en\": u(\"Spanish (Spain)\"), \"name\": u(\"Espa\\xf1ol (Espa\\xf1a)\")},\n    \"es_LA\": {\"name_en\": u(\"Spanish\"), \"name\": u(\"Espa\\xf1ol\")},\n    \"et_EE\": {\"name_en\": u(\"Estonian\"), \"name\": u(\"Eesti\")},\n    \"eu_ES\": {\"name_en\": u(\"Basque\"), \"name\": u(\"Euskara\")},\n    \"fa_IR\": {\"name_en\": u(\"Persian\"), \"name\": u(\"\\u0641\\u0627\\u0631\\u0633\\u06cc\")},\n    \"fi_FI\": {\"name_en\": u(\"Finnish\"), \"name\": u(\"Suomi\")},\n    \"fr_CA\": {\"name_en\": u(\"French (Canada)\"), \"name\": u(\"Fran\\xe7ais (Canada)\")},\n    \"fr_FR\": {\"name_en\": u(\"French\"), \"name\": u(\"Fran\\xe7ais\")},\n    \"ga_IE\": {\"name_en\": u(\"Irish\"), \"name\": u(\"Gaeilge\")},\n    \"gl_ES\": {\"name_en\": u(\"Galician\"), \"name\": u(\"Galego\")},\n    \"he_IL\": {\"name_en\": u(\"Hebrew\"), \"name\": u(\"\\u05e2\\u05d1\\u05e8\\u05d9\\u05ea\")},\n    \"hi_IN\": {\"name_en\": u(\"Hindi\"), \"name\": u(\"\\u0939\\u093f\\u0928\\u094d\\u0926\\u0940\")},\n    \"hr_HR\": {\"name_en\": u(\"Croatian\"), \"name\": u(\"Hrvatski\")},\n    \"hu_HU\": {\"name_en\": u(\"Hungarian\"), \"name\": u(\"Magyar\")},\n    \"id_ID\": {\"name_en\": u(\"Indonesian\"), \"name\": u(\"Bahasa Indonesia\")},\n    \"is_IS\": {\"name_en\": u(\"Icelandic\"), \"name\": u(\"\\xcdslenska\")},\n    \"it_IT\": {\"name_en\": u(\"Italian\"), \"name\": u(\"Italiano\")},\n    \"ja_JP\": {\"name_en\": u(\"Japanese\"), \"name\": u(\"\\u65e5\\u672c\\u8a9e\")},\n    \"ko_KR\": {\"name_en\": u(\"Korean\"), \"name\": u(\"\\ud55c\\uad6d\\uc5b4\")},\n    \"lt_LT\": {\"name_en\": u(\"Lithuanian\"), \"name\": u(\"Lietuvi\\u0173\")},\n    \"lv_LV\": {\"name_en\": u(\"Latvian\"), \"name\": u(\"Latvie\\u0161u\")},\n    \"mk_MK\": {\"name_en\": u(\"Macedonian\"), \"name\": u(\"\\u041c\\u0430\\u043a\\u0435\\u0434\\u043e\\u043d\\u0441\\u043a\\u0438\")},\n    \"ml_IN\": {\"name_en\": u(\"Malayalam\"), \"name\": u(\"\\u0d2e\\u0d32\\u0d2f\\u0d3e\\u0d33\\u0d02\")},\n    \"ms_MY\": {\"name_en\": u(\"Malay\"), \"name\": u(\"Bahasa Melayu\")},\n    \"nb_NO\": {\"name_en\": u(\"Norwegian (bokmal)\"), \"name\": u(\"Norsk (bokm\\xe5l)\")},\n    \"nl_NL\": {\"name_en\": u(\"Dutch\"), \"name\": u(\"Nederlands\")},\n    \"nn_NO\": {\"name_en\": u(\"Norwegian (nynorsk)\"), \"name\": u(\"Norsk (nynorsk)\")},\n    \"pa_IN\": {\"name_en\": u(\"Punjabi\"), \"name\": u(\"\\u0a2a\\u0a70\\u0a1c\\u0a3e\\u0a2c\\u0a40\")},\n    \"pl_PL\": {\"name_en\": u(\"Polish\"), \"name\": u(\"Polski\")},\n    \"pt_BR\": {\"name_en\": u(\"Portuguese (Brazil)\"), \"name\": u(\"Portugu\\xeas (Brasil)\")},\n    \"pt_PT\": {\"name_en\": u(\"Portuguese (Portugal)\"), \"name\": u(\"Portugu\\xeas (Portugal)\")},\n    \"ro_RO\": {\"name_en\": u(\"Romanian\"), \"name\": u(\"Rom\\xe2n\\u0103\")},\n    \"ru_RU\": {\"name_en\": u(\"Russian\"), \"name\": u(\"\\u0420\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439\")},\n    \"sk_SK\": {\"name_en\": u(\"Slovak\"), \"name\": u(\"Sloven\\u010dina\")},\n    \"sl_SI\": {\"name_en\": u(\"Slovenian\"), \"name\": u(\"Sloven\\u0161\\u010dina\")},\n    \"sq_AL\": {\"name_en\": u(\"Albanian\"), \"name\": u(\"Shqip\")},\n    \"sr_RS\": {\"name_en\": u(\"Serbian\"), \"name\": u(\"\\u0421\\u0440\\u043f\\u0441\\u043a\\u0438\")},\n    \"sv_SE\": {\"name_en\": u(\"Swedish\"), \"name\": u(\"Svenska\")},\n    \"sw_KE\": {\"name_en\": u(\"Swahili\"), \"name\": u(\"Kiswahili\")},\n    \"ta_IN\": {\"name_en\": u(\"Tamil\"), \"name\": u(\"\\u0ba4\\u0bae\\u0bbf\\u0bb4\\u0bcd\")},\n    \"te_IN\": {\"name_en\": u(\"Telugu\"), \"name\": u(\"\\u0c24\\u0c46\\u0c32\\u0c41\\u0c17\\u0c41\")},\n    \"th_TH\": {\"name_en\": u(\"Thai\"), \"name\": u(\"\\u0e20\\u0e32\\u0e29\\u0e32\\u0e44\\u0e17\\u0e22\")},\n    \"tl_PH\": {\"name_en\": u(\"Filipino\"), \"name\": u(\"Filipino\")},\n    \"tr_TR\": {\"name_en\": u(\"Turkish\"), \"name\": u(\"T\\xfcrk\\xe7e\")},\n    \"uk_UA\": {\"name_en\": u(\"Ukraini \"), \"name\": u(\"\\u0423\\u043a\\u0440\\u0430\\u0457\\u043d\\u0441\\u044c\\u043a\\u0430\")},\n    \"vi_VN\": {\"name_en\": u(\"Vietnamese\"), \"name\": u(\"Ti\\u1ebfng Vi\\u1ec7t\")},\n    \"zh_CN\": {\"name_en\": u(\"Chinese (Simplified)\"), \"name\": u(\"\\u4e2d\\u6587(\\u7b80\\u4f53)\")},\n    \"zh_TW\": {\"name_en\": u(\"Chinese (Traditional)\"), \"name\": u(\"\\u4e2d\\u6587(\\u7e41\\u9ad4)\")},\n}\n",
            "new_file_content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"Translation methods for generating localized strings.\n\nTo load a locale and generate a translated string::\n\n    user_locale = tornado.locale.get(\"es_LA\")\n    print user_locale.translate(\"Sign out\")\n\n`tornado.locale.get()` returns the closest matching locale, not necessarily the\nspecific locale you requested. You can support pluralization with\nadditional arguments to `~Locale.translate()`, e.g.::\n\n    people = [...]\n    message = user_locale.translate(\n        \"%(list)s is online\", \"%(list)s are online\", len(people))\n    print message % {\"list\": user_locale.list(people)}\n\nThe first string is chosen if ``len(people) == 1``, otherwise the second\nstring is chosen.\n\nApplications should call one of `load_translations` (which uses a simple\nCSV format) or `load_gettext_translations` (which uses the ``.mo`` format\nsupported by `gettext` and related tools).  If neither method is called,\nthe `Locale.translate` method will simply return the original string.\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport csv\nimport datetime\nimport numbers\nimport os\nimport re\n\nfrom tornado import escape\nfrom tornado.log import gen_log\nfrom tornado.util import u\n\n_default_locale = \"en_US\"\n_translations = {}\n_supported_locales = frozenset([_default_locale])\n_use_gettext = False\n\n\ndef get(*locale_codes):\n    \"\"\"Returns the closest match for the given locale codes.\n\n    We iterate over all given locale codes in order. If we have a tight\n    or a loose match for the code (e.g., \"en\" for \"en_US\"), we return\n    the locale. Otherwise we move to the next code in the list.\n\n    By default we return ``en_US`` if no translations are found for any of\n    the specified locales. You can change the default locale with\n    `set_default_locale()`.\n    \"\"\"\n    return Locale.get_closest(*locale_codes)\n\n\ndef set_default_locale(code):\n    \"\"\"Sets the default locale.\n\n    The default locale is assumed to be the language used for all strings\n    in the system. The translations loaded from disk are mappings from\n    the default locale to the destination locale. Consequently, you don't\n    need to create a translation file for the default locale.\n    \"\"\"\n    global _default_locale\n    global _supported_locales\n    _default_locale = code\n    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])\n\n\ndef load_translations(directory):\n    \"\"\"Loads translations from CSV files in a directory.\n\n    Translations are strings with optional Python-style named placeholders\n    (e.g., ``My name is %(name)s``) and their associated translations.\n\n    The directory should have translation files of the form ``LOCALE.csv``,\n    e.g. ``es_GT.csv``. The CSV files should have two or three columns: string,\n    translation, and an optional plural indicator. Plural indicators should\n    be one of \"plural\" or \"singular\". A given string can have both singular\n    and plural forms. For example ``%(name)s liked this`` may have a\n    different verb conjugation depending on whether %(name)s is one\n    name or a list of names. There should be two rows in the CSV file for\n    that string, one with plural indicator \"singular\", and one \"plural\".\n    For strings with no verbs that would change on translation, simply\n    use \"unknown\" or the empty string (or don't include the column at all).\n\n    The file is read using the `csv` module in the default \"excel\" dialect.\n    In this format there should not be spaces after the commas.\n\n    Example translation ``es_LA.csv``::\n\n        \"I love you\",\"Te amo\"\n        \"%(name)s liked this\",\"A %(name)s les gustó esto\",\"plural\"\n        \"%(name)s liked this\",\"A %(name)s le gustó esto\",\"singular\"\n\n    \"\"\"\n    global _translations\n    global _supported_locales\n    _translations = {}\n    for path in os.listdir(directory):\n        if not path.endswith(\".csv\"):\n            continue\n        locale, extension = path.split(\".\")\n        if not re.match(\"[a-z]+(_[A-Z]+)?$\", locale):\n            gen_log.error(\"Unrecognized locale %r (path: %s)\", locale,\n                          os.path.join(directory, path))\n            continue\n        full_path = os.path.join(directory, path)\n        try:\n            # python 3: csv.reader requires a file open in text mode.\n            # Force utf8 to avoid dependence on $LANG environment variable.\n            f = open(full_path, \"r\", encoding=\"utf-8\")\n        except TypeError:\n            # python 2: files return byte strings, which are decoded below.\n            f = open(full_path, \"r\")\n        _translations[locale] = {}\n        for i, row in enumerate(csv.reader(f)):\n            if not row or len(row) < 2:\n                continue\n            row = [escape.to_unicode(c).strip() for c in row]\n            english, translation = row[:2]\n            if len(row) > 2:\n                plural = row[2] or \"unknown\"\n            else:\n                plural = \"unknown\"\n            if plural not in (\"plural\", \"singular\", \"unknown\"):\n                gen_log.error(\"Unrecognized plural indicator %r in %s line %d\",\n                              plural, path, i + 1)\n                continue\n            _translations[locale].setdefault(plural, {})[english] = translation\n        f.close()\n    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])\n    gen_log.debug(\"Supported locales: %s\", sorted(_supported_locales))\n\n\ndef load_gettext_translations(directory, domain):\n    \"\"\"Loads translations from `gettext`'s locale tree\n\n    Locale tree is similar to system's ``/usr/share/locale``, like::\n\n        {directory}/{lang}/LC_MESSAGES/{domain}.mo\n\n    Three steps are required to have you app translated:\n\n    1. Generate POT translation file::\n\n        xgettext --language=Python --keyword=_:1,2 -d mydomain file1.py file2.html etc\n\n    2. Merge against existing POT file::\n\n        msgmerge old.po mydomain.po > new.po\n\n    3. Compile::\n\n        msgfmt mydomain.po -o {directory}/pt_BR/LC_MESSAGES/mydomain.mo\n    \"\"\"\n    import gettext\n    global _translations\n    global _supported_locales\n    global _use_gettext\n    _translations = {}\n    for lang in os.listdir(directory):\n        if lang.startswith('.'):\n            continue  # skip .svn, etc\n        if os.path.isfile(os.path.join(directory, lang)):\n            continue\n        try:\n            os.stat(os.path.join(directory, lang, \"LC_MESSAGES\", domain + \".mo\"))\n            _translations[lang] = gettext.translation(domain, directory,\n                                                      languages=[lang])\n        except Exception as e:\n            gen_log.error(\"Cannot load translation for '%s': %s\", lang, str(e))\n            continue\n    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])\n    _use_gettext = True\n    gen_log.debug(\"Supported locales: %s\", sorted(_supported_locales))\n\n\ndef get_supported_locales():\n    \"\"\"Returns a list of all the supported locale codes.\"\"\"\n    return _supported_locales\n\n\nclass Locale(object):\n    \"\"\"Object representing a locale.\n\n    After calling one of `load_translations` or `load_gettext_translations`,\n    call `get` or `get_closest` to get a Locale object.\n    \"\"\"\n    @classmethod\n    def get_closest(cls, *locale_codes):\n        \"\"\"Returns the closest match for the given locale code.\"\"\"\n        for code in locale_codes:\n            if not code:\n                continue\n            code = code.replace(\"-\", \"_\")\n            parts = code.split(\"_\")\n            if len(parts) > 2:\n                continue\n            elif len(parts) == 2:\n                code = parts[0].lower() + \"_\" + parts[1].upper()\n            if code in _supported_locales:\n                return cls.get(code)\n            if parts[0].lower() in _supported_locales:\n                return cls.get(parts[0].lower())\n        return cls.get(_default_locale)\n\n    @classmethod\n    def get(cls, code):\n        \"\"\"Returns the Locale for the given locale code.\n\n        If it is not supported, we raise an exception.\n        \"\"\"\n        if not hasattr(cls, \"_cache\"):\n            cls._cache = {}\n        if code not in cls._cache:\n            assert code in _supported_locales\n            translations = _translations.get(code, None)\n            if translations is None:\n                locale = CSVLocale(code, {})\n            elif _use_gettext:\n                locale = GettextLocale(code, translations)\n            else:\n                locale = CSVLocale(code, translations)\n            cls._cache[code] = locale\n        return cls._cache[code]\n\n    def __init__(self, code, translations):\n        self.code = code\n        self.name = LOCALE_NAMES.get(code, {}).get(\"name\", u(\"Unknown\"))\n        self.rtl = False\n        for prefix in [\"fa\", \"ar\", \"he\"]:\n            if self.code.startswith(prefix):\n                self.rtl = True\n                break\n        self.translations = translations\n\n        # Initialize strings for date formatting\n        _ = self.translate\n        self._months = [\n            _(\"January\"), _(\"February\"), _(\"March\"), _(\"April\"),\n            _(\"May\"), _(\"June\"), _(\"July\"), _(\"August\"),\n            _(\"September\"), _(\"October\"), _(\"November\"), _(\"December\")]\n        self._weekdays = [\n            _(\"Monday\"), _(\"Tuesday\"), _(\"Wednesday\"), _(\"Thursday\"),\n            _(\"Friday\"), _(\"Saturday\"), _(\"Sunday\")]\n\n    def translate(self, message, plural_message=None, count=None):\n        \"\"\"Returns the translation for the given message for this locale.\n\n        If ``plural_message`` is given, you must also provide\n        ``count``. We return ``plural_message`` when ``count != 1``,\n        and we return the singular form for the given message when\n        ``count == 1``.\n        \"\"\"\n        raise NotImplementedError()\n\n    def format_date(self, date, gmt_offset=0, relative=True, shorter=False,\n                    full_format=False):\n        \"\"\"Formats the given date (which should be GMT).\n\n        By default, we return a relative time (e.g., \"2 minutes ago\"). You\n        can return an absolute date string with ``relative=False``.\n\n        You can force a full format date (\"July 10, 1980\") with\n        ``full_format=True``.\n\n        This method is primarily intended for dates in the past.\n        For dates in the future, we fall back to full format.\n        \"\"\"\n        if self.code.startswith(\"ru\"):\n            relative = False\n        if isinstance(date, numbers.Real):\n            date = datetime.datetime.utcfromtimestamp(date)\n        now = datetime.datetime.utcnow()\n        if date > now:\n            if relative and (date - now).seconds < 60:\n                # Due to click skew, things are some things slightly\n                # in the future. Round timestamps in the immediate\n                # future down to now in relative mode.\n                date = now\n            else:\n                # Otherwise, future dates always use the full format.\n                full_format = True\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        local_now = now - datetime.timedelta(minutes=gmt_offset)\n        local_yesterday = local_now - datetime.timedelta(hours=24)\n        difference = now - date\n        seconds = difference.seconds\n        days = difference.days\n\n        _ = self.translate\n        format = None\n        if not full_format:\n            if relative and days == 0:\n                if seconds < 50:\n                    return _(\"1 second ago\", \"%(seconds)d seconds ago\",\n                             seconds) % {\"seconds\": seconds}\n\n                if seconds < 50 * 60:\n                    minutes = round(seconds / 60.0)\n                    return _(\"1 minute ago\", \"%(minutes)d minutes ago\",\n                             minutes) % {\"minutes\": minutes}\n\n                hours = round(seconds / (60.0 * 60))\n                return _(\"1 hour ago\", \"%(hours)d hours ago\",\n                         hours) % {\"hours\": hours}\n\n            if days == 0:\n                format = _(\"%(time)s\")\n            elif days == 1 and local_date.day == local_yesterday.day and \\\n                    relative:\n                format = _(\"yesterday\") if shorter else \\\n                    _(\"yesterday at %(time)s\")\n            elif days < 5:\n                format = _(\"%(weekday)s\") if shorter else \\\n                    _(\"%(weekday)s at %(time)s\")\n            elif days < 334:  # 11mo, since confusing for same month last year\n                format = _(\"%(month_name)s %(day)s\") if shorter else \\\n                    _(\"%(month_name)s %(day)s at %(time)s\")\n\n        if format is None:\n            format = _(\"%(month_name)s %(day)s, %(year)s\") if shorter else \\\n                _(\"%(month_name)s %(day)s, %(year)s at %(time)s\")\n\n        tfhour_clock = self.code not in (\"en\", \"en_US\", \"zh_CN\")\n        if tfhour_clock:\n            str_time = \"%d:%02d\" % (local_date.hour, local_date.minute)\n        elif self.code == \"zh_CN\":\n            str_time = \"%s%d:%02d\" % (\n                (u('\\u4e0a\\u5348'), u('\\u4e0b\\u5348'))[local_date.hour >= 12],\n                local_date.hour % 12 or 12, local_date.minute)\n        else:\n            str_time = \"%d:%02d %s\" % (\n                local_date.hour % 12 or 12, local_date.minute,\n                (\"am\", \"pm\")[local_date.hour >= 12])\n\n        return format % {\n            \"month_name\": self._months[local_date.month - 1],\n            \"weekday\": self._weekdays[local_date.weekday()],\n            \"day\": str(local_date.day),\n            \"year\": str(local_date.year),\n            \"time\": str_time\n        }\n\n    def format_day(self, date, gmt_offset=0, dow=True):\n        \"\"\"Formats the given date as a day of week.\n\n        Example: \"Monday, January 22\". You can remove the day of week with\n        ``dow=False``.\n        \"\"\"\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        _ = self.translate\n        if dow:\n            return _(\"%(weekday)s, %(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"weekday\": self._weekdays[local_date.weekday()],\n                \"day\": str(local_date.day),\n            }\n        else:\n            return _(\"%(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"day\": str(local_date.day),\n            }\n\n    def list(self, parts):\n        \"\"\"Returns a comma-separated list for the given list of parts.\n\n        The format is, e.g., \"A, B and C\", \"A and B\" or just \"A\" for lists\n        of size 1.\n        \"\"\"\n        _ = self.translate\n        if len(parts) == 0:\n            return \"\"\n        if len(parts) == 1:\n            return parts[0]\n        comma = u(' \\u0648 ') if self.code.startswith(\"fa\") else u(\", \")\n        return _(\"%(commas)s and %(last)s\") % {\n            \"commas\": comma.join(parts[:-1]),\n            \"last\": parts[len(parts) - 1],\n        }\n\n    def friendly_number(self, value):\n        \"\"\"Returns a comma-separated number for the given integer.\"\"\"\n        if self.code not in (\"en\", \"en_US\"):\n            return str(value)\n        value = str(value)\n        parts = []\n        while value:\n            parts.append(value[-3:])\n            value = value[:-3]\n        return \",\".join(reversed(parts))\n\n\nclass CSVLocale(Locale):\n    \"\"\"Locale implementation using tornado's CSV translation format.\"\"\"\n    def translate(self, message, plural_message=None, count=None):\n        if plural_message is not None:\n            assert count is not None\n            if count != 1:\n                message = plural_message\n                message_dict = self.translations.get(\"plural\", {})\n            else:\n                message_dict = self.translations.get(\"singular\", {})\n        else:\n            message_dict = self.translations.get(\"unknown\", {})\n        return message_dict.get(message, message)\n\n\nclass GettextLocale(Locale):\n    \"\"\"Locale implementation using the `gettext` module.\"\"\"\n    def __init__(self, code, translations):\n        try:\n            # python 2\n            self.ngettext = translations.ungettext\n            self.gettext = translations.ugettext\n        except AttributeError:\n            # python 3\n            self.ngettext = translations.ngettext\n            self.gettext = translations.gettext\n        # self.gettext must exist before __init__ is called, since it\n        # calls into self.translate\n        super(GettextLocale, self).__init__(code, translations)\n\n    def translate(self, message, plural_message=None, count=None):\n        if plural_message is not None:\n            assert count is not None\n            return self.ngettext(message, plural_message, count)\n        else:\n            return self.gettext(message)\n\nLOCALE_NAMES = {\n    \"af_ZA\": {\"name_en\": u(\"Afrikaans\"), \"name\": u(\"Afrikaans\")},\n    \"am_ET\": {\"name_en\": u(\"Amharic\"), \"name\": u('\\u12a0\\u121b\\u122d\\u129b')},\n    \"ar_AR\": {\"name_en\": u(\"Arabic\"), \"name\": u(\"\\u0627\\u0644\\u0639\\u0631\\u0628\\u064a\\u0629\")},\n    \"bg_BG\": {\"name_en\": u(\"Bulgarian\"), \"name\": u(\"\\u0411\\u044a\\u043b\\u0433\\u0430\\u0440\\u0441\\u043a\\u0438\")},\n    \"bn_IN\": {\"name_en\": u(\"Bengali\"), \"name\": u(\"\\u09ac\\u09be\\u0982\\u09b2\\u09be\")},\n    \"bs_BA\": {\"name_en\": u(\"Bosnian\"), \"name\": u(\"Bosanski\")},\n    \"ca_ES\": {\"name_en\": u(\"Catalan\"), \"name\": u(\"Catal\\xe0\")},\n    \"cs_CZ\": {\"name_en\": u(\"Czech\"), \"name\": u(\"\\u010ce\\u0161tina\")},\n    \"cy_GB\": {\"name_en\": u(\"Welsh\"), \"name\": u(\"Cymraeg\")},\n    \"da_DK\": {\"name_en\": u(\"Danish\"), \"name\": u(\"Dansk\")},\n    \"de_DE\": {\"name_en\": u(\"German\"), \"name\": u(\"Deutsch\")},\n    \"el_GR\": {\"name_en\": u(\"Greek\"), \"name\": u(\"\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac\")},\n    \"en_GB\": {\"name_en\": u(\"English (UK)\"), \"name\": u(\"English (UK)\")},\n    \"en_US\": {\"name_en\": u(\"English (US)\"), \"name\": u(\"English (US)\")},\n    \"es_ES\": {\"name_en\": u(\"Spanish (Spain)\"), \"name\": u(\"Espa\\xf1ol (Espa\\xf1a)\")},\n    \"es_LA\": {\"name_en\": u(\"Spanish\"), \"name\": u(\"Espa\\xf1ol\")},\n    \"et_EE\": {\"name_en\": u(\"Estonian\"), \"name\": u(\"Eesti\")},\n    \"eu_ES\": {\"name_en\": u(\"Basque\"), \"name\": u(\"Euskara\")},\n    \"fa_IR\": {\"name_en\": u(\"Persian\"), \"name\": u(\"\\u0641\\u0627\\u0631\\u0633\\u06cc\")},\n    \"fi_FI\": {\"name_en\": u(\"Finnish\"), \"name\": u(\"Suomi\")},\n    \"fr_CA\": {\"name_en\": u(\"French (Canada)\"), \"name\": u(\"Fran\\xe7ais (Canada)\")},\n    \"fr_FR\": {\"name_en\": u(\"French\"), \"name\": u(\"Fran\\xe7ais\")},\n    \"ga_IE\": {\"name_en\": u(\"Irish\"), \"name\": u(\"Gaeilge\")},\n    \"gl_ES\": {\"name_en\": u(\"Galician\"), \"name\": u(\"Galego\")},\n    \"he_IL\": {\"name_en\": u(\"Hebrew\"), \"name\": u(\"\\u05e2\\u05d1\\u05e8\\u05d9\\u05ea\")},\n    \"hi_IN\": {\"name_en\": u(\"Hindi\"), \"name\": u(\"\\u0939\\u093f\\u0928\\u094d\\u0926\\u0940\")},\n    \"hr_HR\": {\"name_en\": u(\"Croatian\"), \"name\": u(\"Hrvatski\")},\n    \"hu_HU\": {\"name_en\": u(\"Hungarian\"), \"name\": u(\"Magyar\")},\n    \"id_ID\": {\"name_en\": u(\"Indonesian\"), \"name\": u(\"Bahasa Indonesia\")},\n    \"is_IS\": {\"name_en\": u(\"Icelandic\"), \"name\": u(\"\\xcdslenska\")},\n    \"it_IT\": {\"name_en\": u(\"Italian\"), \"name\": u(\"Italiano\")},\n    \"ja_JP\": {\"name_en\": u(\"Japanese\"), \"name\": u(\"\\u65e5\\u672c\\u8a9e\")},\n    \"ko_KR\": {\"name_en\": u(\"Korean\"), \"name\": u(\"\\ud55c\\uad6d\\uc5b4\")},\n    \"lt_LT\": {\"name_en\": u(\"Lithuanian\"), \"name\": u(\"Lietuvi\\u0173\")},\n    \"lv_LV\": {\"name_en\": u(\"Latvian\"), \"name\": u(\"Latvie\\u0161u\")},\n    \"mk_MK\": {\"name_en\": u(\"Macedonian\"), \"name\": u(\"\\u041c\\u0430\\u043a\\u0435\\u0434\\u043e\\u043d\\u0441\\u043a\\u0438\")},\n    \"ml_IN\": {\"name_en\": u(\"Malayalam\"), \"name\": u(\"\\u0d2e\\u0d32\\u0d2f\\u0d3e\\u0d33\\u0d02\")},\n    \"ms_MY\": {\"name_en\": u(\"Malay\"), \"name\": u(\"Bahasa Melayu\")},\n    \"nb_NO\": {\"name_en\": u(\"Norwegian (bokmal)\"), \"name\": u(\"Norsk (bokm\\xe5l)\")},\n    \"nl_NL\": {\"name_en\": u(\"Dutch\"), \"name\": u(\"Nederlands\")},\n    \"nn_NO\": {\"name_en\": u(\"Norwegian (nynorsk)\"), \"name\": u(\"Norsk (nynorsk)\")},\n    \"pa_IN\": {\"name_en\": u(\"Punjabi\"), \"name\": u(\"\\u0a2a\\u0a70\\u0a1c\\u0a3e\\u0a2c\\u0a40\")},\n    \"pl_PL\": {\"name_en\": u(\"Polish\"), \"name\": u(\"Polski\")},\n    \"pt_BR\": {\"name_en\": u(\"Portuguese (Brazil)\"), \"name\": u(\"Portugu\\xeas (Brasil)\")},\n    \"pt_PT\": {\"name_en\": u(\"Portuguese (Portugal)\"), \"name\": u(\"Portugu\\xeas (Portugal)\")},\n    \"ro_RO\": {\"name_en\": u(\"Romanian\"), \"name\": u(\"Rom\\xe2n\\u0103\")},\n    \"ru_RU\": {\"name_en\": u(\"Russian\"), \"name\": u(\"\\u0420\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439\")},\n    \"sk_SK\": {\"name_en\": u(\"Slovak\"), \"name\": u(\"Sloven\\u010dina\")},\n    \"sl_SI\": {\"name_en\": u(\"Slovenian\"), \"name\": u(\"Sloven\\u0161\\u010dina\")},\n    \"sq_AL\": {\"name_en\": u(\"Albanian\"), \"name\": u(\"Shqip\")},\n    \"sr_RS\": {\"name_en\": u(\"Serbian\"), \"name\": u(\"\\u0421\\u0440\\u043f\\u0441\\u043a\\u0438\")},\n    \"sv_SE\": {\"name_en\": u(\"Swedish\"), \"name\": u(\"Svenska\")},\n    \"sw_KE\": {\"name_en\": u(\"Swahili\"), \"name\": u(\"Kiswahili\")},\n    \"ta_IN\": {\"name_en\": u(\"Tamil\"), \"name\": u(\"\\u0ba4\\u0bae\\u0bbf\\u0bb4\\u0bcd\")},\n    \"te_IN\": {\"name_en\": u(\"Telugu\"), \"name\": u(\"\\u0c24\\u0c46\\u0c32\\u0c41\\u0c17\\u0c41\")},\n    \"th_TH\": {\"name_en\": u(\"Thai\"), \"name\": u(\"\\u0e20\\u0e32\\u0e29\\u0e32\\u0e44\\u0e17\\u0e22\")},\n    \"tl_PH\": {\"name_en\": u(\"Filipino\"), \"name\": u(\"Filipino\")},\n    \"tr_TR\": {\"name_en\": u(\"Turkish\"), \"name\": u(\"T\\xfcrk\\xe7e\")},\n    \"uk_UA\": {\"name_en\": u(\"Ukraini \"), \"name\": u(\"\\u0423\\u043a\\u0440\\u0430\\u0457\\u043d\\u0441\\u044c\\u043a\\u0430\")},\n    \"vi_VN\": {\"name_en\": u(\"Vietnamese\"), \"name\": u(\"Ti\\u1ebfng Vi\\u1ec7t\")},\n    \"zh_CN\": {\"name_en\": u(\"Chinese (Simplified)\"), \"name\": u(\"\\u4e2d\\u6587(\\u7b80\\u4f53)\")},\n    \"zh_TW\": {\"name_en\": u(\"Chinese (Traditional)\"), \"name\": u(\"\\u4e2d\\u6587(\\u7e41\\u9ad4)\")},\n}\n",
            "header": {
                "file": {
                    "path": "tornado/locale.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "66e9ff6d",
                "new_commit_hash": "310a5178",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/locale.py"
            },
            "plus_file": {
                "path": "b/tornado/locale.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 43,
                            "length": 6
                        },
                        "new_range": {
                            "start": 43,
                            "length": 7
                        },
                        "section": "from __future__ import absolute_import, division, print_function, with_statement"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "import csv",
                                "type": "context"
                            },
                            {
                                "content": "import datetime",
                                "type": "context"
                            },
                            {
                                "content": "import numbers",
                                "type": "added"
                            },
                            {
                                "content": "import os",
                                "type": "context"
                            },
                            {
                                "content": "import re",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tornado/locale.py",
                            "type": "import",
                            "name": "numbers",
                            "content": "import numbers",
                            "ast_type_str": "Import",
                            "start_lineno": 46,
                            "end_lineno": 46,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 287,
                            "length": 7
                        },
                        "new_range": {
                            "start": 288,
                            "length": 7
                        },
                        "section": "class Locale(object):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        \"\"\"",
                                "type": "context"
                            },
                            {
                                "content": "        if self.code.startswith(\"ru\"):",
                                "type": "context"
                            },
                            {
                                "content": "            relative = False",
                                "type": "context"
                            },
                            {
                                "content": "        if type(date) in (int, long, float):",
                                "type": "deleted"
                            },
                            {
                                "content": "        if isinstance(date, numbers.Real):",
                                "type": "added"
                            },
                            {
                                "content": "            date = datetime.datetime.utcfromtimestamp(date)",
                                "type": "context"
                            },
                            {
                                "content": "        now = datetime.datetime.utcnow()",
                                "type": "context"
                            },
                            {
                                "content": "        if date > now:",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [
                        {
                            "file_name": "tornado/locale.py",
                            "type": "method",
                            "name": "Locale.format_date",
                            "content": "class Locale(object):\n    \"\"\"Object representing a locale.\n\n    After calling one of `load_translations` or `load_gettext_translations`,\n    call `get` or `get_closest` to get a Locale object.\n    \"\"\"\n    @classmethod\n    def get_closest(cls, *locale_codes):\n        \"\"\"Returns the closest match for the given locale code.\"\"\"\n        for code in locale_codes:\n            if not code:\n                continue\n            code = code.replace(\"-\", \"_\")\n            parts = code.split(\"_\")\n            if len(parts) > 2:\n                continue\n            elif len(parts) == 2:\n                code = parts[0].lower() + \"_\" + parts[1].upper()\n            if code in _supported_locales:\n                return cls.get(code)\n            if parts[0].lower() in _supported_locales:\n                return cls.get(parts[0].lower())\n        return cls.get(_default_locale)\n\n    @classmethod\n    def get(cls, code):\n        \"\"\"Returns the Locale for the given locale code.\n\n        If it is not supported, we raise an exception.\n        \"\"\"\n        if not hasattr(cls, \"_cache\"):\n            cls._cache = {}\n        if code not in cls._cache:\n            assert code in _supported_locales\n            translations = _translations.get(code, None)\n            if translations is None:\n                locale = CSVLocale(code, {})\n            elif _use_gettext:\n                locale = GettextLocale(code, translations)\n            else:\n                locale = CSVLocale(code, translations)\n            cls._cache[code] = locale\n        return cls._cache[code]\n\n    def __init__(self, code, translations):\n        self.code = code\n        self.name = LOCALE_NAMES.get(code, {}).get(\"name\", u(\"Unknown\"))\n        self.rtl = False\n        for prefix in [\"fa\", \"ar\", \"he\"]:\n            if self.code.startswith(prefix):\n                self.rtl = True\n                break\n        self.translations = translations\n\n        # Initialize strings for date formatting\n        _ = self.translate\n        self._months = [\n            _(\"January\"), _(\"February\"), _(\"March\"), _(\"April\"),\n            _(\"May\"), _(\"June\"), _(\"July\"), _(\"August\"),\n            _(\"September\"), _(\"October\"), _(\"November\"), _(\"December\")]\n        self._weekdays = [\n            _(\"Monday\"), _(\"Tuesday\"), _(\"Wednesday\"), _(\"Thursday\"),\n            _(\"Friday\"), _(\"Saturday\"), _(\"Sunday\")]\n\n    def translate(self, message, plural_message=None, count=None):\n        \"\"\"Returns the translation for the given message for this locale.\n\n        If ``plural_message`` is given, you must also provide\n        ``count``. We return ``plural_message`` when ``count != 1``,\n        and we return the singular form for the given message when\n        ``count == 1``.\n        \"\"\"\n        raise NotImplementedError()\n\n    def format_date(self, date, gmt_offset=0, relative=True, shorter=False,\n                    full_format=False):\n        \"\"\"Formats the given date (which should be GMT).\n\n        By default, we return a relative time (e.g., \"2 minutes ago\"). You\n        can return an absolute date string with ``relative=False``.\n\n        You can force a full format date (\"July 10, 1980\") with\n        ``full_format=True``.\n\n        This method is primarily intended for dates in the past.\n        For dates in the future, we fall back to full format.\n        \"\"\"\n        if self.code.startswith(\"ru\"):\n            relative = False\n        if type(date) in (int, long, float):\n            date = datetime.datetime.utcfromtimestamp(date)\n        now = datetime.datetime.utcnow()\n        if date > now:\n            if relative and (date - now).seconds < 60:\n                # Due to click skew, things are some things slightly\n                # in the future. Round timestamps in the immediate\n                # future down to now in relative mode.\n                date = now\n            else:\n                # Otherwise, future dates always use the full format.\n                full_format = True\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        local_now = now - datetime.timedelta(minutes=gmt_offset)\n        local_yesterday = local_now - datetime.timedelta(hours=24)\n        difference = now - date\n        seconds = difference.seconds\n        days = difference.days\n\n        _ = self.translate\n        format = None\n        if not full_format:\n            if relative and days == 0:\n                if seconds < 50:\n                    return _(\"1 second ago\", \"%(seconds)d seconds ago\",\n                             seconds) % {\"seconds\": seconds}\n\n                if seconds < 50 * 60:\n                    minutes = round(seconds / 60.0)\n                    return _(\"1 minute ago\", \"%(minutes)d minutes ago\",\n                             minutes) % {\"minutes\": minutes}\n\n                hours = round(seconds / (60.0 * 60))\n                return _(\"1 hour ago\", \"%(hours)d hours ago\",\n                         hours) % {\"hours\": hours}\n\n            if days == 0:\n                format = _(\"%(time)s\")\n            elif days == 1 and local_date.day == local_yesterday.day and \\\n                    relative:\n                format = _(\"yesterday\") if shorter else \\\n                    _(\"yesterday at %(time)s\")\n            elif days < 5:\n                format = _(\"%(weekday)s\") if shorter else \\\n                    _(\"%(weekday)s at %(time)s\")\n            elif days < 334:  # 11mo, since confusing for same month last year\n                format = _(\"%(month_name)s %(day)s\") if shorter else \\\n                    _(\"%(month_name)s %(day)s at %(time)s\")\n\n        if format is None:\n            format = _(\"%(month_name)s %(day)s, %(year)s\") if shorter else \\\n                _(\"%(month_name)s %(day)s, %(year)s at %(time)s\")\n\n        tfhour_clock = self.code not in (\"en\", \"en_US\", \"zh_CN\")\n        if tfhour_clock:\n            str_time = \"%d:%02d\" % (local_date.hour, local_date.minute)\n        elif self.code == \"zh_CN\":\n            str_time = \"%s%d:%02d\" % (\n                (u('\\u4e0a\\u5348'), u('\\u4e0b\\u5348'))[local_date.hour >= 12],\n                local_date.hour % 12 or 12, local_date.minute)\n        else:\n            str_time = \"%d:%02d %s\" % (\n                local_date.hour % 12 or 12, local_date.minute,\n                (\"am\", \"pm\")[local_date.hour >= 12])\n\n        return format % {\n            \"month_name\": self._months[local_date.month - 1],\n            \"weekday\": self._weekdays[local_date.weekday()],\n            \"day\": str(local_date.day),\n            \"year\": str(local_date.year),\n            \"time\": str_time\n        }\n\n    def format_day(self, date, gmt_offset=0, dow=True):\n        \"\"\"Formats the given date as a day of week.\n\n        Example: \"Monday, January 22\". You can remove the day of week with\n        ``dow=False``.\n        \"\"\"\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        _ = self.translate\n        if dow:\n            return _(\"%(weekday)s, %(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"weekday\": self._weekdays[local_date.weekday()],\n                \"day\": str(local_date.day),\n            }\n        else:\n            return _(\"%(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"day\": str(local_date.day),\n            }\n\n    def list(self, parts):\n        \"\"\"Returns a comma-separated list for the given list of parts.\n\n        The format is, e.g., \"A, B and C\", \"A and B\" or just \"A\" for lists\n        of size 1.\n        \"\"\"\n        _ = self.translate\n        if len(parts) == 0:\n            return \"\"\n        if len(parts) == 1:\n            return parts[0]\n        comma = u(' \\u0648 ') if self.code.startswith(\"fa\") else u(\", \")\n        return _(\"%(commas)s and %(last)s\") % {\n            \"commas\": comma.join(parts[:-1]),\n            \"last\": parts[len(parts) - 1],\n        }\n\n    def friendly_number(self, value):\n        \"\"\"Returns a comma-separated number for the given integer.\"\"\"\n        if self.code not in (\"en\", \"en_US\"):\n            return str(value)\n        value = str(value)\n        parts = []\n        while value:\n            parts.append(value[-3:])\n            value = value[:-3]\n        return \",\".join(reversed(parts))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 275,
                            "end_lineno": 361,
                            "parent": {
                                "file_name": "tornado/locale.py",
                                "type": "class",
                                "name": "Locale",
                                "content": "class Locale(object):\n    \"\"\"Object representing a locale.\n\n    After calling one of `load_translations` or `load_gettext_translations`,\n    call `get` or `get_closest` to get a Locale object.\n    \"\"\"\n    @classmethod\n    def get_closest(cls, *locale_codes):\n        \"\"\"Returns the closest match for the given locale code.\"\"\"\n        for code in locale_codes:\n            if not code:\n                continue\n            code = code.replace(\"-\", \"_\")\n            parts = code.split(\"_\")\n            if len(parts) > 2:\n                continue\n            elif len(parts) == 2:\n                code = parts[0].lower() + \"_\" + parts[1].upper()\n            if code in _supported_locales:\n                return cls.get(code)\n            if parts[0].lower() in _supported_locales:\n                return cls.get(parts[0].lower())\n        return cls.get(_default_locale)\n\n    @classmethod\n    def get(cls, code):\n        \"\"\"Returns the Locale for the given locale code.\n\n        If it is not supported, we raise an exception.\n        \"\"\"\n        if not hasattr(cls, \"_cache\"):\n            cls._cache = {}\n        if code not in cls._cache:\n            assert code in _supported_locales\n            translations = _translations.get(code, None)\n            if translations is None:\n                locale = CSVLocale(code, {})\n            elif _use_gettext:\n                locale = GettextLocale(code, translations)\n            else:\n                locale = CSVLocale(code, translations)\n            cls._cache[code] = locale\n        return cls._cache[code]\n\n    def __init__(self, code, translations):\n        self.code = code\n        self.name = LOCALE_NAMES.get(code, {}).get(\"name\", u(\"Unknown\"))\n        self.rtl = False\n        for prefix in [\"fa\", \"ar\", \"he\"]:\n            if self.code.startswith(prefix):\n                self.rtl = True\n                break\n        self.translations = translations\n\n        # Initialize strings for date formatting\n        _ = self.translate\n        self._months = [\n            _(\"January\"), _(\"February\"), _(\"March\"), _(\"April\"),\n            _(\"May\"), _(\"June\"), _(\"July\"), _(\"August\"),\n            _(\"September\"), _(\"October\"), _(\"November\"), _(\"December\")]\n        self._weekdays = [\n            _(\"Monday\"), _(\"Tuesday\"), _(\"Wednesday\"), _(\"Thursday\"),\n            _(\"Friday\"), _(\"Saturday\"), _(\"Sunday\")]\n\n    def translate(self, message, plural_message=None, count=None):\n        \"\"\"Returns the translation for the given message for this locale.\n\n        If ``plural_message`` is given, you must also provide\n        ``count``. We return ``plural_message`` when ``count != 1``,\n        and we return the singular form for the given message when\n        ``count == 1``.\n        \"\"\"\n        raise NotImplementedError()\n\n    def format_date(self, date, gmt_offset=0, relative=True, shorter=False,\n                    full_format=False):\n        \"\"\"Formats the given date (which should be GMT).\n\n        By default, we return a relative time (e.g., \"2 minutes ago\"). You\n        can return an absolute date string with ``relative=False``.\n\n        You can force a full format date (\"July 10, 1980\") with\n        ``full_format=True``.\n\n        This method is primarily intended for dates in the past.\n        For dates in the future, we fall back to full format.\n        \"\"\"\n        if self.code.startswith(\"ru\"):\n            relative = False\n        if type(date) in (int, long, float):\n            date = datetime.datetime.utcfromtimestamp(date)\n        now = datetime.datetime.utcnow()\n        if date > now:\n            if relative and (date - now).seconds < 60:\n                # Due to click skew, things are some things slightly\n                # in the future. Round timestamps in the immediate\n                # future down to now in relative mode.\n                date = now\n            else:\n                # Otherwise, future dates always use the full format.\n                full_format = True\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        local_now = now - datetime.timedelta(minutes=gmt_offset)\n        local_yesterday = local_now - datetime.timedelta(hours=24)\n        difference = now - date\n        seconds = difference.seconds\n        days = difference.days\n\n        _ = self.translate\n        format = None\n        if not full_format:\n            if relative and days == 0:\n                if seconds < 50:\n                    return _(\"1 second ago\", \"%(seconds)d seconds ago\",\n                             seconds) % {\"seconds\": seconds}\n\n                if seconds < 50 * 60:\n                    minutes = round(seconds / 60.0)\n                    return _(\"1 minute ago\", \"%(minutes)d minutes ago\",\n                             minutes) % {\"minutes\": minutes}\n\n                hours = round(seconds / (60.0 * 60))\n                return _(\"1 hour ago\", \"%(hours)d hours ago\",\n                         hours) % {\"hours\": hours}\n\n            if days == 0:\n                format = _(\"%(time)s\")\n            elif days == 1 and local_date.day == local_yesterday.day and \\\n                    relative:\n                format = _(\"yesterday\") if shorter else \\\n                    _(\"yesterday at %(time)s\")\n            elif days < 5:\n                format = _(\"%(weekday)s\") if shorter else \\\n                    _(\"%(weekday)s at %(time)s\")\n            elif days < 334:  # 11mo, since confusing for same month last year\n                format = _(\"%(month_name)s %(day)s\") if shorter else \\\n                    _(\"%(month_name)s %(day)s at %(time)s\")\n\n        if format is None:\n            format = _(\"%(month_name)s %(day)s, %(year)s\") if shorter else \\\n                _(\"%(month_name)s %(day)s, %(year)s at %(time)s\")\n\n        tfhour_clock = self.code not in (\"en\", \"en_US\", \"zh_CN\")\n        if tfhour_clock:\n            str_time = \"%d:%02d\" % (local_date.hour, local_date.minute)\n        elif self.code == \"zh_CN\":\n            str_time = \"%s%d:%02d\" % (\n                (u('\\u4e0a\\u5348'), u('\\u4e0b\\u5348'))[local_date.hour >= 12],\n                local_date.hour % 12 or 12, local_date.minute)\n        else:\n            str_time = \"%d:%02d %s\" % (\n                local_date.hour % 12 or 12, local_date.minute,\n                (\"am\", \"pm\")[local_date.hour >= 12])\n\n        return format % {\n            \"month_name\": self._months[local_date.month - 1],\n            \"weekday\": self._weekdays[local_date.weekday()],\n            \"day\": str(local_date.day),\n            \"year\": str(local_date.year),\n            \"time\": str_time\n        }\n\n    def format_day(self, date, gmt_offset=0, dow=True):\n        \"\"\"Formats the given date as a day of week.\n\n        Example: \"Monday, January 22\". You can remove the day of week with\n        ``dow=False``.\n        \"\"\"\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        _ = self.translate\n        if dow:\n            return _(\"%(weekday)s, %(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"weekday\": self._weekdays[local_date.weekday()],\n                \"day\": str(local_date.day),\n            }\n        else:\n            return _(\"%(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"day\": str(local_date.day),\n            }\n\n    def list(self, parts):\n        \"\"\"Returns a comma-separated list for the given list of parts.\n\n        The format is, e.g., \"A, B and C\", \"A and B\" or just \"A\" for lists\n        of size 1.\n        \"\"\"\n        _ = self.translate\n        if len(parts) == 0:\n            return \"\"\n        if len(parts) == 1:\n            return parts[0]\n        comma = u(' \\u0648 ') if self.code.startswith(\"fa\") else u(\", \")\n        return _(\"%(commas)s and %(last)s\") % {\n            \"commas\": comma.join(parts[:-1]),\n            \"last\": parts[len(parts) - 1],\n        }\n\n    def friendly_number(self, value):\n        \"\"\"Returns a comma-separated number for the given integer.\"\"\"\n        if self.code not in (\"en\", \"en_US\"):\n            return str(value)\n        value = str(value)\n        parts = []\n        while value:\n            parts.append(value[-3:])\n            value = value[:-3]\n        return \",\".join(reversed(parts))",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 201,
                                "end_lineno": 409,
                                "parent": null
                            }
                        },
                        {
                            "file_name": "tornado/locale.py",
                            "type": "class",
                            "name": "Locale",
                            "content": "class Locale(object):\n    \"\"\"Object representing a locale.\n\n    After calling one of `load_translations` or `load_gettext_translations`,\n    call `get` or `get_closest` to get a Locale object.\n    \"\"\"\n    @classmethod\n    def get_closest(cls, *locale_codes):\n        \"\"\"Returns the closest match for the given locale code.\"\"\"\n        for code in locale_codes:\n            if not code:\n                continue\n            code = code.replace(\"-\", \"_\")\n            parts = code.split(\"_\")\n            if len(parts) > 2:\n                continue\n            elif len(parts) == 2:\n                code = parts[0].lower() + \"_\" + parts[1].upper()\n            if code in _supported_locales:\n                return cls.get(code)\n            if parts[0].lower() in _supported_locales:\n                return cls.get(parts[0].lower())\n        return cls.get(_default_locale)\n\n    @classmethod\n    def get(cls, code):\n        \"\"\"Returns the Locale for the given locale code.\n\n        If it is not supported, we raise an exception.\n        \"\"\"\n        if not hasattr(cls, \"_cache\"):\n            cls._cache = {}\n        if code not in cls._cache:\n            assert code in _supported_locales\n            translations = _translations.get(code, None)\n            if translations is None:\n                locale = CSVLocale(code, {})\n            elif _use_gettext:\n                locale = GettextLocale(code, translations)\n            else:\n                locale = CSVLocale(code, translations)\n            cls._cache[code] = locale\n        return cls._cache[code]\n\n    def __init__(self, code, translations):\n        self.code = code\n        self.name = LOCALE_NAMES.get(code, {}).get(\"name\", u(\"Unknown\"))\n        self.rtl = False\n        for prefix in [\"fa\", \"ar\", \"he\"]:\n            if self.code.startswith(prefix):\n                self.rtl = True\n                break\n        self.translations = translations\n\n        # Initialize strings for date formatting\n        _ = self.translate\n        self._months = [\n            _(\"January\"), _(\"February\"), _(\"March\"), _(\"April\"),\n            _(\"May\"), _(\"June\"), _(\"July\"), _(\"August\"),\n            _(\"September\"), _(\"October\"), _(\"November\"), _(\"December\")]\n        self._weekdays = [\n            _(\"Monday\"), _(\"Tuesday\"), _(\"Wednesday\"), _(\"Thursday\"),\n            _(\"Friday\"), _(\"Saturday\"), _(\"Sunday\")]\n\n    def translate(self, message, plural_message=None, count=None):\n        \"\"\"Returns the translation for the given message for this locale.\n\n        If ``plural_message`` is given, you must also provide\n        ``count``. We return ``plural_message`` when ``count != 1``,\n        and we return the singular form for the given message when\n        ``count == 1``.\n        \"\"\"\n        raise NotImplementedError()\n\n    def format_date(self, date, gmt_offset=0, relative=True, shorter=False,\n                    full_format=False):\n        \"\"\"Formats the given date (which should be GMT).\n\n        By default, we return a relative time (e.g., \"2 minutes ago\"). You\n        can return an absolute date string with ``relative=False``.\n\n        You can force a full format date (\"July 10, 1980\") with\n        ``full_format=True``.\n\n        This method is primarily intended for dates in the past.\n        For dates in the future, we fall back to full format.\n        \"\"\"\n        if self.code.startswith(\"ru\"):\n            relative = False\n        if type(date) in (int, long, float):\n            date = datetime.datetime.utcfromtimestamp(date)\n        now = datetime.datetime.utcnow()\n        if date > now:\n            if relative and (date - now).seconds < 60:\n                # Due to click skew, things are some things slightly\n                # in the future. Round timestamps in the immediate\n                # future down to now in relative mode.\n                date = now\n            else:\n                # Otherwise, future dates always use the full format.\n                full_format = True\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        local_now = now - datetime.timedelta(minutes=gmt_offset)\n        local_yesterday = local_now - datetime.timedelta(hours=24)\n        difference = now - date\n        seconds = difference.seconds\n        days = difference.days\n\n        _ = self.translate\n        format = None\n        if not full_format:\n            if relative and days == 0:\n                if seconds < 50:\n                    return _(\"1 second ago\", \"%(seconds)d seconds ago\",\n                             seconds) % {\"seconds\": seconds}\n\n                if seconds < 50 * 60:\n                    minutes = round(seconds / 60.0)\n                    return _(\"1 minute ago\", \"%(minutes)d minutes ago\",\n                             minutes) % {\"minutes\": minutes}\n\n                hours = round(seconds / (60.0 * 60))\n                return _(\"1 hour ago\", \"%(hours)d hours ago\",\n                         hours) % {\"hours\": hours}\n\n            if days == 0:\n                format = _(\"%(time)s\")\n            elif days == 1 and local_date.day == local_yesterday.day and \\\n                    relative:\n                format = _(\"yesterday\") if shorter else \\\n                    _(\"yesterday at %(time)s\")\n            elif days < 5:\n                format = _(\"%(weekday)s\") if shorter else \\\n                    _(\"%(weekday)s at %(time)s\")\n            elif days < 334:  # 11mo, since confusing for same month last year\n                format = _(\"%(month_name)s %(day)s\") if shorter else \\\n                    _(\"%(month_name)s %(day)s at %(time)s\")\n\n        if format is None:\n            format = _(\"%(month_name)s %(day)s, %(year)s\") if shorter else \\\n                _(\"%(month_name)s %(day)s, %(year)s at %(time)s\")\n\n        tfhour_clock = self.code not in (\"en\", \"en_US\", \"zh_CN\")\n        if tfhour_clock:\n            str_time = \"%d:%02d\" % (local_date.hour, local_date.minute)\n        elif self.code == \"zh_CN\":\n            str_time = \"%s%d:%02d\" % (\n                (u('\\u4e0a\\u5348'), u('\\u4e0b\\u5348'))[local_date.hour >= 12],\n                local_date.hour % 12 or 12, local_date.minute)\n        else:\n            str_time = \"%d:%02d %s\" % (\n                local_date.hour % 12 or 12, local_date.minute,\n                (\"am\", \"pm\")[local_date.hour >= 12])\n\n        return format % {\n            \"month_name\": self._months[local_date.month - 1],\n            \"weekday\": self._weekdays[local_date.weekday()],\n            \"day\": str(local_date.day),\n            \"year\": str(local_date.year),\n            \"time\": str_time\n        }\n\n    def format_day(self, date, gmt_offset=0, dow=True):\n        \"\"\"Formats the given date as a day of week.\n\n        Example: \"Monday, January 22\". You can remove the day of week with\n        ``dow=False``.\n        \"\"\"\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        _ = self.translate\n        if dow:\n            return _(\"%(weekday)s, %(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"weekday\": self._weekdays[local_date.weekday()],\n                \"day\": str(local_date.day),\n            }\n        else:\n            return _(\"%(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"day\": str(local_date.day),\n            }\n\n    def list(self, parts):\n        \"\"\"Returns a comma-separated list for the given list of parts.\n\n        The format is, e.g., \"A, B and C\", \"A and B\" or just \"A\" for lists\n        of size 1.\n        \"\"\"\n        _ = self.translate\n        if len(parts) == 0:\n            return \"\"\n        if len(parts) == 1:\n            return parts[0]\n        comma = u(' \\u0648 ') if self.code.startswith(\"fa\") else u(\", \")\n        return _(\"%(commas)s and %(last)s\") % {\n            \"commas\": comma.join(parts[:-1]),\n            \"last\": parts[len(parts) - 1],\n        }\n\n    def friendly_number(self, value):\n        \"\"\"Returns a comma-separated number for the given integer.\"\"\"\n        if self.code not in (\"en\", \"en_US\"):\n            return str(value)\n        value = str(value)\n        parts = []\n        while value:\n            parts.append(value[-3:])\n            value = value[:-3]\n        return \",\".join(reversed(parts))",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 201,
                            "end_lineno": 409,
                            "parent": null
                        }
                    ],
                    "added_entities": [],
                    "deleted_entities": []
                }
            ]
        },
        {
            "old_file_content": "from __future__ import absolute_import, division, print_function, with_statement\n\nimport os\nimport tornado.locale\nfrom tornado.escape import utf8\nfrom tornado.test.util import unittest\nfrom tornado.util import u, unicode_type\n\n\nclass TranslationLoaderTest(unittest.TestCase):\n    # TODO: less hacky way to get isolated tests\n    SAVE_VARS = ['_translations', '_supported_locales', '_use_gettext']\n\n    def clear_locale_cache(self):\n        if hasattr(tornado.locale.Locale, '_cache'):\n            del tornado.locale.Locale._cache\n\n    def setUp(self):\n        self.saved = {}\n        for var in TranslationLoaderTest.SAVE_VARS:\n            self.saved[var] = getattr(tornado.locale, var)\n        self.clear_locale_cache()\n\n    def tearDown(self):\n        for k, v in self.saved.items():\n            setattr(tornado.locale, k, v)\n        self.clear_locale_cache()\n\n    def test_csv(self):\n        tornado.locale.load_translations(\n            os.path.join(os.path.dirname(__file__), 'csv_translations'))\n        locale = tornado.locale.get(\"fr_FR\")\n        self.assertTrue(isinstance(locale, tornado.locale.CSVLocale))\n        self.assertEqual(locale.translate(\"school\"), u(\"\\u00e9cole\"))\n\n    def test_gettext(self):\n        tornado.locale.load_gettext_translations(\n            os.path.join(os.path.dirname(__file__), 'gettext_translations'),\n            \"tornado_test\")\n        locale = tornado.locale.get(\"fr_FR\")\n        self.assertTrue(isinstance(locale, tornado.locale.GettextLocale))\n        self.assertEqual(locale.translate(\"school\"), u(\"\\u00e9cole\"))\n\n\nclass LocaleDataTest(unittest.TestCase):\n    def test_non_ascii_name(self):\n        name = tornado.locale.LOCALE_NAMES['es_LA']['name']\n        self.assertTrue(isinstance(name, unicode_type))\n        self.assertEqual(name, u('Espa\\u00f1ol'))\n        self.assertEqual(utf8(name), b'Espa\\xc3\\xb1ol')\n",
            "new_file_content": "from __future__ import absolute_import, division, print_function, with_statement\n\nimport datetime\nimport os\nimport tornado.locale\nfrom tornado.escape import utf8\nfrom tornado.test.util import unittest\nfrom tornado.util import u, unicode_type\n\n\nclass TranslationLoaderTest(unittest.TestCase):\n    # TODO: less hacky way to get isolated tests\n    SAVE_VARS = ['_translations', '_supported_locales', '_use_gettext']\n\n    def clear_locale_cache(self):\n        if hasattr(tornado.locale.Locale, '_cache'):\n            del tornado.locale.Locale._cache\n\n    def setUp(self):\n        self.saved = {}\n        for var in TranslationLoaderTest.SAVE_VARS:\n            self.saved[var] = getattr(tornado.locale, var)\n        self.clear_locale_cache()\n\n    def tearDown(self):\n        for k, v in self.saved.items():\n            setattr(tornado.locale, k, v)\n        self.clear_locale_cache()\n\n    def test_csv(self):\n        tornado.locale.load_translations(\n            os.path.join(os.path.dirname(__file__), 'csv_translations'))\n        locale = tornado.locale.get(\"fr_FR\")\n        self.assertTrue(isinstance(locale, tornado.locale.CSVLocale))\n        self.assertEqual(locale.translate(\"school\"), u(\"\\u00e9cole\"))\n\n    def test_gettext(self):\n        tornado.locale.load_gettext_translations(\n            os.path.join(os.path.dirname(__file__), 'gettext_translations'),\n            \"tornado_test\")\n        locale = tornado.locale.get(\"fr_FR\")\n        self.assertTrue(isinstance(locale, tornado.locale.GettextLocale))\n        self.assertEqual(locale.translate(\"school\"), u(\"\\u00e9cole\"))\n\n\nclass LocaleDataTest(unittest.TestCase):\n    def test_non_ascii_name(self):\n        name = tornado.locale.LOCALE_NAMES['es_LA']['name']\n        self.assertTrue(isinstance(name, unicode_type))\n        self.assertEqual(name, u('Espa\\u00f1ol'))\n        self.assertEqual(utf8(name), b'Espa\\xc3\\xb1ol')\n\n\nclass EnglishTest(unittest.TestCase):\n    def test_format_date(self):\n        locale = tornado.locale.get('en_US')\n        date = datetime.datetime(2013, 4, 28, 18, 35)\n        self.assertEqual(locale.format_date(date, full_format=True),\n                         'April 28, 2013 at 6:35 pm')\n",
            "header": {
                "file": {
                    "path": "tornado/test/locale_test.py"
                },
                "misc_line": null
            },
            "index_line": {
                "old_commit_hash": "043f5d27",
                "new_commit_hash": "948228f1",
                "mode": "100644"
            },
            "is_binary_file": false,
            "binary_line": null,
            "minus_file": {
                "path": "a/tornado/test/locale_test.py"
            },
            "plus_file": {
                "path": "b/tornado/test/locale_test.py"
            },
            "hunks": [
                {
                    "descriptor": {
                        "old_range": {
                            "start": 1,
                            "length": 5
                        },
                        "new_range": {
                            "start": 1,
                            "length": 6
                        },
                        "section": ""
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "from __future__ import absolute_import, division, print_function, with_statement",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "context"
                            },
                            {
                                "content": "import datetime",
                                "type": "added"
                            },
                            {
                                "content": "import os",
                                "type": "context"
                            },
                            {
                                "content": "import tornado.locale",
                                "type": "context"
                            },
                            {
                                "content": "from tornado.escape import utf8",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tornado/test/locale_test.py",
                            "type": "import",
                            "name": "datetime",
                            "content": "import datetime",
                            "ast_type_str": "Import",
                            "start_lineno": 3,
                            "end_lineno": 3,
                            "parent": null
                        }
                    ],
                    "deleted_entities": []
                },
                {
                    "descriptor": {
                        "old_range": {
                            "start": 48,
                            "length": 3
                        },
                        "new_range": {
                            "start": 49,
                            "length": 11
                        },
                        "section": "class LocaleDataTest(unittest.TestCase):"
                    },
                    "line_group": {
                        "all_lines": [
                            {
                                "content": "        self.assertTrue(isinstance(name, unicode_type))",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(name, u('Espa\\u00f1ol'))",
                                "type": "context"
                            },
                            {
                                "content": "        self.assertEqual(utf8(name), b'Espa\\xc3\\xb1ol')",
                                "type": "context"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "added"
                            },
                            {
                                "content": "class EnglishTest(unittest.TestCase):",
                                "type": "added"
                            },
                            {
                                "content": "    def test_format_date(self):",
                                "type": "added"
                            },
                            {
                                "content": "        locale = tornado.locale.get('en_US')",
                                "type": "added"
                            },
                            {
                                "content": "        date = datetime.datetime(2013, 4, 28, 18, 35)",
                                "type": "added"
                            },
                            {
                                "content": "        self.assertEqual(locale.format_date(date, full_format=True),",
                                "type": "added"
                            },
                            {
                                "content": "                         'April 28, 2013 at 6:35 pm')",
                                "type": "added"
                            },
                            {
                                "content": "",
                                "type": "context"
                            }
                        ]
                    },
                    "modified_entities": [],
                    "added_entities": [
                        {
                            "file_name": "tornado/test/locale_test.py",
                            "type": "class",
                            "name": "EnglishTest",
                            "content": "class EnglishTest(unittest.TestCase):\n    def test_format_date(self):\n        locale = tornado.locale.get('en_US')\n        date = datetime.datetime(2013, 4, 28, 18, 35)\n        self.assertEqual(locale.format_date(date, full_format=True),\n                         'April 28, 2013 at 6:35 pm')",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 54,
                            "end_lineno": 59,
                            "parent": null
                        },
                        {
                            "file_name": "tornado/test/locale_test.py",
                            "type": "method",
                            "name": "EnglishTest.test_format_date",
                            "content": "class EnglishTest(unittest.TestCase):\n    def test_format_date(self):\n        locale = tornado.locale.get('en_US')\n        date = datetime.datetime(2013, 4, 28, 18, 35)\n        self.assertEqual(locale.format_date(date, full_format=True),\n                         'April 28, 2013 at 6:35 pm')",
                            "ast_type_str": "ClassDef",
                            "start_lineno": 55,
                            "end_lineno": 59,
                            "parent": {
                                "file_name": "tornado/test/locale_test.py",
                                "type": "class",
                                "name": "EnglishTest",
                                "content": "class EnglishTest(unittest.TestCase):\n    def test_format_date(self):\n        locale = tornado.locale.get('en_US')\n        date = datetime.datetime(2013, 4, 28, 18, 35)\n        self.assertEqual(locale.format_date(date, full_format=True),\n                         'April 28, 2013 at 6:35 pm')",
                                "ast_type_str": "ClassDef",
                                "start_lineno": 54,
                                "end_lineno": 59,
                                "parent": null
                            }
                        }
                    ],
                    "deleted_entities": []
                }
            ]
        }
    ],
    "old_commit_hash": "8fdd57d272cb0885e3803d923f480ad483bc43d1^",
    "new_commit_hash": "8fdd57d272cb0885e3803d923f480ad483bc43d1",
    "commit_message": "Fix locale.format_date on python 3.\n\nThere's probably more work to be done on this largely-untested code,\nbut this was the case I could find by grepping for stray references\nto `long`.",
    "commit_date": "2013-04-28T18:40:31-04:00",
    "metadata": {}
}
{
    "repo_name": "tornado",
    "new_commit_hash": "8fdd57d272cb0885e3803d923f480ad483bc43d1",
    "test_file_codes": [
        "from __future__ import absolute_import, division, print_function, with_statement\n\nimport datetime\nimport os\nimport tornado.locale\nfrom tornado.escape import utf8\nfrom tornado.test.util import unittest\nfrom tornado.util import u, unicode_type\n\n\nclass TranslationLoaderTest(unittest.TestCase):\n    # TODO: less hacky way to get isolated tests\n    SAVE_VARS = ['_translations', '_supported_locales', '_use_gettext']\n\n    def clear_locale_cache(self):\n        if hasattr(tornado.locale.Locale, '_cache'):\n            del tornado.locale.Locale._cache\n\n    def setUp(self):\n        self.saved = {}\n        for var in TranslationLoaderTest.SAVE_VARS:\n            self.saved[var] = getattr(tornado.locale, var)\n        self.clear_locale_cache()\n\n    def tearDown(self):\n        for k, v in self.saved.items():\n            setattr(tornado.locale, k, v)\n        self.clear_locale_cache()\n\n    def test_csv(self):\n        tornado.locale.load_translations(\n            os.path.join(os.path.dirname(__file__), 'csv_translations'))\n        locale = tornado.locale.get(\"fr_FR\")\n        self.assertTrue(isinstance(locale, tornado.locale.CSVLocale))\n        self.assertEqual(locale.translate(\"school\"), u(\"\\u00e9cole\"))\n\n    def test_gettext(self):\n        tornado.locale.load_gettext_translations(\n            os.path.join(os.path.dirname(__file__), 'gettext_translations'),\n            \"tornado_test\")\n        locale = tornado.locale.get(\"fr_FR\")\n        self.assertTrue(isinstance(locale, tornado.locale.GettextLocale))\n        self.assertEqual(locale.translate(\"school\"), u(\"\\u00e9cole\"))\n\n\nclass LocaleDataTest(unittest.TestCase):\n    def test_non_ascii_name(self):\n        name = tornado.locale.LOCALE_NAMES['es_LA']['name']\n        self.assertTrue(isinstance(name, unicode_type))\n        self.assertEqual(name, u('Espa\\u00f1ol'))\n        self.assertEqual(utf8(name), b'Espa\\xc3\\xb1ol')\n\n\nclass EnglishTest(unittest.TestCase):\n    def test_format_date(self):\n        locale = tornado.locale.get('en_US')\n        date = datetime.datetime(2013, 4, 28, 18, 35)\n        self.assertEqual(locale.format_date(date, full_format=True),\n                         'April 28, 2013 at 6:35 pm')\n",
        "#!/usr/bin/env python\nimport unittest\nimport sys\nimport time\nimport traceback\nimport platform\nimport os\n\n\nclass PytestLikeResult(unittest.TestResult):\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.start_time = None\n        # Store (test, outcome, info) for each test:\n        #   outcome ∈ { \"passed\", \"failed\", \"error\", \"skipped\" }\n        #   info can hold the exception or skip reason, etc.\n        self.results = []\n\n    def startTestRun(self):\n        \"\"\"Called once before all tests.\"\"\"\n        self.start_time = time.time()\n        # Print a header similar to pytest\n        print(\"=\" * 29 + \" test session starts \" + \"=\" * 29)\n        # You can customize the platform/versions/paths as you like:\n        print(\n            f\"platform {platform.system().lower()} -- Python {platform.python_version()}\"\n        )\n        print(f\"rootdir: {os.path.abspath(os.curdir)}\")\n\n    def stopTestRun(self):\n        \"\"\"Called once after all tests are done.\"\"\"\n        elapsed = time.time() - self.start_time\n        print()  # blank line after final dot\n\n        # Summarize\n        ntests = len(self.results)\n        print(f\"collected {ntests} items\")\n\n        # Show details of failures/errors\n        failures = [r for r in self.results if r[1] == \"failed\"]\n        errors = [r for r in self.results if r[1] == \"error\"]\n\n        if failures:\n            print(\"\\n\" + \"=\" * 35 + \" FAILURES \" + \"=\" * 35)\n            for test, outcome, err_info in failures:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n        if errors:\n            print(\"\\n\" + \"=\" * 35 + \" ERRORS \" + \"=\" * 37)\n            for test, outcome, err_info in errors:\n                test = test.split(\"::\")\n                if len(test) == 3:\n                    test = f\"{test[1]}.{test[2]}\"\n                else:\n                    test = f\"{test[1]}\"\n                print(f\"__________ {test} __________\")\n                self._print_traceback(err_info)\n\n        # Optional short summary lines for passes/fails/skips\n        print(\"\\n==================== short test summary info ====================\")\n        for test, outcome, info in self.results:\n            if outcome in (\"passed\", \"failed\", \"error\", \"skipped\"):\n                print(f\"{outcome.upper()} {test}\")\n\n        # Final one-line summary: “1 failed, 1 errors, 10 passed in 2.04s”\n        passed_count = sum(1 for r in self.results if r[1] == \"passed\")\n        failed_count = len(failures)\n        error_count = len(errors)\n        skipped_count = sum(1 for r in self.results if r[1] == \"skipped\")\n\n        summary_bits = []\n        if failed_count:\n            summary_bits.append(f\"{failed_count} failed\")\n        if error_count:\n            summary_bits.append(f\"{error_count} error{'s' if error_count != 1 else ''}\")\n        if passed_count:\n            summary_bits.append(f\"{passed_count} passed\")\n        if skipped_count:\n            summary_bits.append(f\"{skipped_count} skipped\")\n\n        summary_str = \", \".join(summary_bits) if summary_bits else \"no tests run\"\n        print(\n            f\"=================== {summary_str} in {elapsed:.2f}s ===================\"\n        )\n\n    def startTest(self, test):\n        \"\"\"Called right before each test method.\"\"\"\n        super().startTest(test)\n        # Print a dot or some indicator\n        print(\".\", end=\"\", flush=True)\n\n    def addSuccess(self, test):\n        super().addSuccess(test)\n        self.results.append((self._test_id(test), \"passed\", None))\n\n    def addFailure(self, test, err):\n        super().addFailure(test, err)\n        self.results.append((self._test_id(test), \"failed\", err))\n\n    def addError(self, test, err):\n        super().addError(test, err)\n        self.results.append((self._test_id(test), \"error\", err))\n\n    def addSkip(self, test, reason):\n        super().addSkip(test, reason)\n        self.results.append((self._test_id(test), \"skipped\", reason))\n\n    def _print_traceback(self, err_info):\n        \"\"\"Helper to print the traceback like pytest does.\"\"\"\n        if isinstance(err_info, tuple) and len(err_info) == 3:\n            exc_type, exc_value, tb = err_info\n            traceback.print_exception(exc_type, exc_value, tb, file=sys.stdout)\n        else:\n            print(str(err_info))\n\n    def _test_id(self, test):\n        try:\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}::{test._testMethodName}\"\n        except AttributeError:\n            # Fallback for _ErrorHolder objects\n            return f\"{test.__class__.__module__}::{test.__class__.__name__}\"\n\n\nclass PytestLikeRunner(unittest.TextTestRunner):\n    \"\"\"A custom TextTestRunner that uses the PytestLikeResult.\"\"\"\n\n    resultclass = PytestLikeResult\n\n    def run(self, test):\n        result = self._makeResult()\n        # Overriding run to ensure we call startTestRun/stopTestRun\n        result.startTestRun()\n        test(result)\n        result.stopTestRun()\n        return result\n\n    def tearDown(self):\n        # Reset signal handlers\n        from twisted.internet import reactor\n\n        reactor.removeAll()\n        reactor.stop()\n        super().tearDown()\n\n\ndef main():\n    loader = unittest.TestLoader()\n    suite = loader.discover(\".\", pattern=\"test_*.py\")  # discover tests in r2e_tests/\n    runner = PytestLikeRunner(verbosity=0)\n    result = runner.run(suite)\n    # Exit with code 0 if all tests passed/skipped, 1 if there were fails/errors\n    sys.exit(not result.wasSuccessful())\n\n\nif __name__ == \"__main__\":\n    main()\n"
    ],
    "test_file_names": [
        "test_1.py",
        "tornado_unittest_runner.py"
    ],
    "setup_res_code": 0,
    "setup_res_stdout": "",
    "setup_res_stderr": "Using CPython 3.9.21\nCreating virtual environment at: .venv\nActivate with: source .venv/bin/activate\nResolved 1 package in 760ms\nPrepared 1 package in 810ms\nInstalled 1 package in 0.76ms\n + tornado==3.1.dev2 (from file:///home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1)\nResolved 29 packages in 15ms\nInstalled 29 packages in 64ms\n + attrs==24.3.0\n + automat==24.8.1\n + cachetools==5.5.0\n + cffi==1.17.1\n + chardet==5.2.0\n + colorama==0.4.6\n + constantly==23.10.4\n + distlib==0.3.9\n + exceptiongroup==1.2.2\n + filelock==3.16.1\n + hyperlink==21.0.0\n + idna==3.10\n + incremental==24.7.2\n + iniconfig==2.0.0\n + packaging==24.2\n + platformdirs==4.3.6\n + pluggy==1.5.0\n + pycares==4.5.0\n + pycparser==2.22\n + pycurl==7.45.4\n + pyproject-api==1.8.0\n + pytest==8.3.4\n + setuptools==75.6.0\n + tomli==2.2.1\n + tox==4.23.2\n + twisted==24.11.0\n + typing-extensions==4.12.2\n + virtualenv==20.28.0\n + zope-interface==7.2\n",
    "new_commit_res_code": 1,
    "new_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1\n....\ncollected 4 items\n\n=================================== ERRORS =====================================\n__________ TranslationLoaderTest.test_csv __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/r2e_tests/test_1.py\", line 31, in test_csv\n    tornado.locale.load_translations(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/tornado/locale.py\", line 118, in load_translations\n    for path in os.listdir(directory):\nFileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/r2e_tests/csv_translations'\n__________ TranslationLoaderTest.test_gettext __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/r2e_tests/test_1.py\", line 38, in test_gettext\n    tornado.locale.load_gettext_translations(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/tornado/locale.py\", line 180, in load_gettext_translations\n    for lang in os.listdir(directory):\nFileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/r2e_tests/gettext_translations'\n\n==================== short test summary info ====================\nPASSED r2e_tests.test_1::EnglishTest::test_format_date\nPASSED r2e_tests.test_1::LocaleDataTest::test_non_ascii_name\nERROR r2e_tests.test_1::TranslationLoaderTest::test_csv\nERROR r2e_tests.test_1::TranslationLoaderTest::test_gettext\n=================== 2 errors, 2 passed in 0.00s ===================\n",
    "new_commit_res_stderr": "",
    "old_commit_res_code": 1,
    "old_commit_res_stdout": "============================= test session starts =============================\nplatform linux -- Python 3.9.21\nrootdir: /home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1\n....\ncollected 4 items\n\n=================================== ERRORS =====================================\n__________ EnglishTest.test_format_date __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/r2e_tests/test_1.py\", line 58, in test_format_date\n    self.assertEqual(locale.format_date(date, full_format=True),\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/tornado/locale.py\", line 290, in format_date\n    if type(date) in (int, long, float):\nNameError: name 'long' is not defined\n__________ TranslationLoaderTest.test_csv __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/r2e_tests/test_1.py\", line 31, in test_csv\n    tornado.locale.load_translations(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/tornado/locale.py\", line 117, in load_translations\n    for path in os.listdir(directory):\nFileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/r2e_tests/csv_translations'\n__________ TranslationLoaderTest.test_gettext __________\nTraceback (most recent call last):\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 59, in testPartExecutor\n    yield\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 592, in run\n    self._callTestMethod(testMethod)\n  File \"/home/gcpuser/.local/share/uv/python/cpython-3.9.21-linux-x86_64-gnu/lib/python3.9/unittest/case.py\", line 550, in _callTestMethod\n    method()\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/r2e_tests/test_1.py\", line 38, in test_gettext\n    tornado.locale.load_gettext_translations(\n  File \"/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/tornado/locale.py\", line 179, in load_gettext_translations\n    for lang in os.listdir(directory):\nFileNotFoundError: [Errno 2] No such file or directory: '/home/gcpuser/buckets/local_repoeval_bucket/repos/tornado_8fdd57d272cb0885e3803d923f480ad483bc43d1/r2e_tests/gettext_translations'\n\n==================== short test summary info ====================\nERROR r2e_tests.test_1::EnglishTest::test_format_date\nPASSED r2e_tests.test_1::LocaleDataTest::test_non_ascii_name\nERROR r2e_tests.test_1::TranslationLoaderTest::test_csv\nERROR r2e_tests.test_1::TranslationLoaderTest::test_gettext\n=================== 3 errors, 1 passed in 0.00s ===================\n",
    "old_commit_res_stderr": ""
}
tornado/locale.py tornado/test/locale_test.py
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** `locale.format_date` Raises `NameError` for `long` Type in Python 3

**Description:**
When using the `format_date` method from the `locale` module with a numeric timestamp, a `NameError` is raised in Python 3 due to the use of the undefined `long` type.

**Example Code:**
```python
import tornado.locale
import datetime

locale = tornado.locale.get('en_US')
timestamp = 1617181723.0  # Example timestamp as a float
formatted_date = locale.format_date(timestamp, full_format=True)
```

**Expected Behavior:**
The `format_date` method should correctly convert the numeric timestamp to a `datetime` object and return the formatted date string without errors.

**Actual Behavior:**
A `NameError` is raised indicating that `'long'` is not defined:
```
NameError: name 'long' is not defined
```
[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/locale.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""Translation methods for generating localized strings.

To load a locale and generate a translated string::

    user_locale = tornado.locale.get("es_LA")
    print user_locale.translate("Sign out")

`tornado.locale.get()` returns the closest matching locale, not necessarily the
specific locale you requested. You can support pluralization with
additional arguments to `~Locale.translate()`, e.g.::

    people = [...]
    message = user_locale.translate(
        "%(list)s is online", "%(list)s are online", len(people))
    print message % {"list": user_locale.list(people)}

The first string is chosen if ``len(people) == 1``, otherwise the second
string is chosen.

Applications should call one of `load_translations` (which uses a simple
CSV format) or `load_gettext_translations` (which uses the ``.mo`` format
supported by `gettext` and related tools).  If neither method is called,
the `Locale.translate` method will simply return the original string.
"""

from __future__ import absolute_import, division, print_function, with_statement

import csv
import datetime
import os
import re

from tornado import escape
from tornado.log import gen_log
from tornado.util import u

_default_locale = "en_US"
_translations = {}
_supported_locales = frozenset([_default_locale])
_use_gettext = False


def get(*locale_codes):
    """Returns the closest match for the given locale codes.

    We iterate over all given locale codes in order. If we have a tight
    or a loose match for the code (e.g., "en" for "en_US"), we return
    the locale. Otherwise we move to the next code in the list.

    By default we return ``en_US`` if no translations are found for any of
    the specified locales. You can change the default locale with
    `set_default_locale()`.
    """
    return Locale.get_closest(*locale_codes)


def set_default_locale(code):
    """Sets the default locale.

    The default locale is assumed to be the language used for all strings
    in the system. The translations loaded from disk are mappings from
    the default locale to the destination locale. Consequently, you don't
    need to create a translation file for the default locale.
    """
    global _default_locale
    global _supported_locales
    _default_locale = code
    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])


def load_translations(directory):
    """Loads translations from CSV files in a directory.

    Translations are strings with optional Python-style named placeholders
    (e.g., ``My name is %(name)s``) and their associated translations.

    The directory should have translation files of the form ``LOCALE.csv``,
    e.g. ``es_GT.csv``. The CSV files should have two or three columns: string,
    translation, and an optional plural indicator. Plural indicators should
    be one of "plural" or "singular". A given string can have both singular
    and plural forms. For example ``%(name)s liked this`` may have a
    different verb conjugation depending on whether %(name)s is one
    name or a list of names. There should be two rows in the CSV file for
    that string, one with plural indicator "singular", and one "plural".
    For strings with no verbs that would change on translation, simply
    use "unknown" or the empty string (or don't include the column at all).

    The file is read using the `csv` module in the default "excel" dialect.
    In this format there should not be spaces after the commas.

    Example translation ``es_LA.csv``::

        "I love you","Te amo"
        "%(name)s liked this","A %(name)s les gustó esto","plural"
        "%(name)s liked this","A %(name)s le gustó esto","singular"

    """
    global _translations
    global _supported_locales
    _translations = {}
    for path in os.listdir(directory):
        if not path.endswith(".csv"):
            continue
        locale, extension = path.split(".")
        if not re.match("[a-z]+(_[A-Z]+)?$", locale):
            gen_log.error("Unrecognized locale %r (path: %s)", locale,
                          os.path.join(directory, path))
            continue
        full_path = os.path.join(directory, path)
        try:
            # python 3: csv.reader requires a file open in text mode.
            # Force utf8 to avoid dependence on $LANG environment variable.
            f = open(full_path, "r", encoding="utf-8")
        except TypeError:
            # python 2: files return byte strings, which are decoded below.
            f = open(full_path, "r")
        _translations[locale] = {}
        for i, row in enumerate(csv.reader(f)):
            if not row or len(row) < 2:
                continue
            row = [escape.to_unicode(c).strip() for c in row]
            english, translation = row[:2]
            if len(row) > 2:
                plural = row[2] or "unknown"
            else:
                plural = "unknown"
            if plural not in ("plural", "singular", "unknown"):
                gen_log.error("Unrecognized plural indicator %r in %s line %d",
                              plural, path, i + 1)
                continue
            _translations[locale].setdefault(plural, {})[english] = translation
        f.close()
    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])
    gen_log.debug("Supported locales: %s", sorted(_supported_locales))


def load_gettext_translations(directory, domain):
    """Loads translations from `gettext`'s locale tree

    Locale tree is similar to system's ``/usr/share/locale``, like::

        {directory}/{lang}/LC_MESSAGES/{domain}.mo

    Three steps are required to have you app translated:

    1. Generate POT translation file::

        xgettext --language=Python --keyword=_:1,2 -d mydomain file1.py file2.html etc

    2. Merge against existing POT file::

        msgmerge old.po mydomain.po > new.po

    3. Compile::

        msgfmt mydomain.po -o {directory}/pt_BR/LC_MESSAGES/mydomain.mo
    """
    import gettext
    global _translations
    global _supported_locales
    global _use_gettext
    _translations = {}
    for lang in os.listdir(directory):
        if lang.startswith('.'):
            continue  # skip .svn, etc
        if os.path.isfile(os.path.join(directory, lang)):
            continue
        try:
            os.stat(os.path.join(directory, lang, "LC_MESSAGES", domain + ".mo"))
            _translations[lang] = gettext.translation(domain, directory,
                                                      languages=[lang])
        except Exception as e:
            gen_log.error("Cannot load translation for '%s': %s", lang, str(e))
            continue
    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])
    _use_gettext = True
    gen_log.debug("Supported locales: %s", sorted(_supported_locales))


def get_supported_locales():
    """Returns a list of all the supported locale codes."""
    return _supported_locales


class Locale(object):
    """Object representing a locale.

    After calling one of `load_translations` or `load_gettext_translations`,
    call `get` or `get_closest` to get a Locale object.
    """
    @classmethod
    def get_closest(cls, *locale_codes):
        """Returns the closest match for the given locale code."""
        for code in locale_codes:
            if not code:
                continue
            code = code.replace("-", "_")
            parts = code.split("_")
            if len(parts) > 2:
                continue
            elif len(parts) == 2:
                code = parts[0].lower() + "_" + parts[1].upper()
            if code in _supported_locales:
                return cls.get(code)
            if parts[0].lower() in _supported_locales:
                return cls.get(parts[0].lower())
        return cls.get(_default_locale)

    @classmethod
    def get(cls, code):
        """Returns the Locale for the given locale code.

        If it is not supported, we raise an exception.
        """
        if not hasattr(cls, "_cache"):
            cls._cache = {}
        if code not in cls._cache:
            assert code in _supported_locales
            translations = _translations.get(code, None)
            if translations is None:
                locale = CSVLocale(code, {})
            elif _use_gettext:
                locale = GettextLocale(code, translations)
            else:
                locale = CSVLocale(code, translations)
            cls._cache[code] = locale
        return cls._cache[code]

    def __init__(self, code, translations):
        self.code = code
        self.name = LOCALE_NAMES.get(code, {}).get("name", u("Unknown"))
        self.rtl = False
        for prefix in ["fa", "ar", "he"]:
            if self.code.startswith(prefix):
                self.rtl = True
                break
        self.translations = translations

        # Initialize strings for date formatting
        _ = self.translate
        self._months = [
            _("January"), _("February"), _("March"), _("April"),
            _("May"), _("June"), _("July"), _("August"),
            _("September"), _("October"), _("November"), _("December")]
        self._weekdays = [
            _("Monday"), _("Tuesday"), _("Wednesday"), _("Thursday"),
            _("Friday"), _("Saturday"), _("Sunday")]

    def translate(self, message, plural_message=None, count=None):
        """Returns the translation for the given message for this locale.

        If ``plural_message`` is given, you must also provide
        ``count``. We return ``plural_message`` when ``count != 1``,
        and we return the singular form for the given message when
        ``count == 1``.
        """
        raise NotImplementedError()

    def format_date(self, date, gmt_offset=0, relative=True, shorter=False,
                    full_format=False):
        """Formats the given date (which should be GMT).

        By default, we return a relative time (e.g., "2 minutes ago"). You
        can return an absolute date string with ``relative=False``.

        You can force a full format date ("July 10, 1980") with
        ``full_format=True``.

        This method is primarily intended for dates in the past.
        For dates in the future, we fall back to full format.
        """
        if self.code.startswith("ru"):
            relative = False
        if type(date) in (int, long, float):
            date = datetime.datetime.utcfromtimestamp(date)
        now = datetime.datetime.utcnow()
        if date > now:
            if relative and (date - now).seconds < 60:
                # Due to click skew, things are some things slightly
                # in the future. Round timestamps in the immediate
                # future down to now in relative mode.
                date = now
            else:
                # Otherwise, future dates always use the full format.
                full_format = True
        local_date = date - datetime.timedelta(minutes=gmt_offset)
        local_now = now - datetime.timedelta(minutes=gmt_offset)
        local_yesterday = local_now - datetime.timedelta(hours=24)
        difference = now - date
        seconds = difference.seconds
        days = difference.days

        _ = self.translate
        format = None
        if not full_format:
            if relative and days == 0:
                if seconds < 50:
                    return _("1 second ago", "%(seconds)d seconds ago",
                             seconds) % {"seconds": seconds}

                if seconds < 50 * 60:
                    minutes = round(seconds / 60.0)
                    return _("1 minute ago", "%(minutes)d minutes ago",
                             minutes) % {"minutes": minutes}

                hours = round(seconds / (60.0 * 60))
                return _("1 hour ago", "%(hours)d hours ago",
                         hours) % {"hours": hours}

            if days == 0:
                format = _("%(time)s")
            elif days == 1 and local_date.day == local_yesterday.day and \
                    relative:
                format = _("yesterday") if shorter else \
                    _("yesterday at %(time)s")
            elif days < 5:
                format = _("%(weekday)s") if shorter else \
                    _("%(weekday)s at %(time)s")
            elif days < 334:  # 11mo, since confusing for same month last year
                format = _("%(month_name)s %(day)s") if shorter else \
                    _("%(month_name)s %(day)s at %(time)s")

        if format is None:
            format = _("%(month_name)s %(day)s, %(year)s") if shorter else \
                _("%(month_name)s %(day)s, %(year)s at %(time)s")

        tfhour_clock = self.code not in ("en", "en_US", "zh_CN")
        if tfhour_clock:
            str_time = "%d:%02d" % (local_date.hour, local_date.minute)
        elif self.code == "zh_CN":
            str_time = "%s%d:%02d" % (
                (u('\u4e0a\u5348'), u('\u4e0b\u5348'))[local_date.hour >= 12],
                local_date.hour % 12 or 12, local_date.minute)
        else:
            str_time = "%d:%02d %s" % (
                local_date.hour % 12 or 12, local_date.minute,
                ("am", "pm")[local_date.hour >= 12])

        return format % {
            "month_name": self._months[local_date.month - 1],
            "weekday": self._weekdays[local_date.weekday()],
            "day": str(local_date.day),
            "year": str(local_date.year),
            "time": str_time
        }

    def format_day(self, date, gmt_offset=0, dow=True):
        """Formats the given date as a day of week.

        Example: "Monday, January 22". You can remove the day of week with
        ``dow=False``.
        """
        local_date = date - datetime.timedelta(minutes=gmt_offset)
        _ = self.translate
        if dow:
            return _("%(weekday)s, %(month_name)s %(day)s") % {
                "month_name": self._months[local_date.month - 1],
                "weekday": self._weekdays[local_date.weekday()],
                "day": str(local_date.day),
            }
        else:
            return _("%(month_name)s %(day)s") % {
                "month_name": self._months[local_date.month - 1],
                "day": str(local_date.day),
            }

    def list(self, parts):
        """Returns a comma-separated list for the given list of parts.

        The format is, e.g., "A, B and C", "A and B" or just "A" for lists
        of size 1.
        """
        _ = self.translate
        if len(parts) == 0:
            return ""
        if len(parts) == 1:
            return parts[0]
        comma = u(' \u0648 ') if self.code.startswith("fa") else u(", ")
        return _("%(commas)s and %(last)s") % {
            "commas": comma.join(parts[:-1]),
            "last": parts[len(parts) - 1],
        }

    def friendly_number(self, value):
        """Returns a comma-separated number for the given integer."""
        if self.code not in ("en", "en_US"):
            return str(value)
        value = str(value)
        parts = []
        while value:
            parts.append(value[-3:])
            value = value[:-3]
        return ",".join(reversed(parts))


class CSVLocale(Locale):
    """Locale implementation using tornado's CSV translation format."""
    def translate(self, message, plural_message=None, count=None):
        if plural_message is not None:
            assert count is not None
            if count != 1:
                message = plural_message
                message_dict = self.translations.get("plural", {})
            else:
                message_dict = self.translations.get("singular", {})
        else:
            message_dict = self.translations.get("unknown", {})
        return message_dict.get(message, message)


class GettextLocale(Locale):
    """Locale implementation using the `gettext` module."""
    def __init__(self, code, translations):
        try:
            # python 2
            self.ngettext = translations.ungettext
            self.gettext = translations.ugettext
        except AttributeError:
            # python 3
            self.ngettext = translations.ngettext
            self.gettext = translations.gettext
        # self.gettext must exist before __init__ is called, since it
        # calls into self.translate
        super(GettextLocale, self).__init__(code, translations)

    def translate(self, message, plural_message=None, count=None):
        if plural_message is not None:
            assert count is not None
            return self.ngettext(message, plural_message, count)
        else:
            return self.gettext(message)

LOCALE_NAMES = {
    "af_ZA": {"name_en": u("Afrikaans"), "name": u("Afrikaans")},
    "am_ET": {"name_en": u("Amharic"), "name": u('\u12a0\u121b\u122d\u129b')},
    "ar_AR": {"name_en": u("Arabic"), "name": u("\u0627\u0644\u0639\u0631\u0628\u064a\u0629")},
    "bg_BG": {"name_en": u("Bulgarian"), "name": u("\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438")},
    "bn_IN": {"name_en": u("Bengali"), "name": u("\u09ac\u09be\u0982\u09b2\u09be")},
    "bs_BA": {"name_en": u("Bosnian"), "name": u("Bosanski")},
    "ca_ES": {"name_en": u("Catalan"), "name": u("Catal\xe0")},
    "cs_CZ": {"name_en": u("Czech"), "name": u("\u010ce\u0161tina")},
    "cy_GB": {"name_en": u("Welsh"), "name": u("Cymraeg")},
    "da_DK": {"name_en": u("Danish"), "name": u("Dansk")},
    "de_DE": {"name_en": u("German"), "name": u("Deutsch")},
    "el_GR": {"name_en": u("Greek"), "name": u("\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac")},
    "en_GB": {"name_en": u("English (UK)"), "name": u("English (UK)")},
    "en_US": {"name_en": u("English (US)"), "name": u("English (US)")},
    "es_ES": {"name_en": u("Spanish (Spain)"), "name": u("Espa\xf1ol (Espa\xf1a)")},
    "es_LA": {"name_en": u("Spanish"), "name": u("Espa\xf1ol")},
    "et_EE": {"name_en": u("Estonian"), "name": u("Eesti")},
    "eu_ES": {"name_en": u("Basque"), "name": u("Euskara")},
    "fa_IR": {"name_en": u("Persian"), "name": u("\u0641\u0627\u0631\u0633\u06cc")},
    "fi_FI": {"name_en": u("Finnish"), "name": u("Suomi")},
    "fr_CA": {"name_en": u("French (Canada)"), "name": u("Fran\xe7ais (Canada)")},
    "fr_FR": {"name_en": u("French"), "name": u("Fran\xe7ais")},
    "ga_IE": {"name_en": u("Irish"), "name": u("Gaeilge")},
    "gl_ES": {"name_en": u("Galician"), "name": u("Galego")},
    "he_IL": {"name_en": u("Hebrew"), "name": u("\u05e2\u05d1\u05e8\u05d9\u05ea")},
    "hi_IN": {"name_en": u("Hindi"), "name": u("\u0939\u093f\u0928\u094d\u0926\u0940")},
    "hr_HR": {"name_en": u("Croatian"), "name": u("Hrvatski")},
    "hu_HU": {"name_en": u("Hungarian"), "name": u("Magyar")},
    "id_ID": {"name_en": u("Indonesian"), "name": u("Bahasa Indonesia")},
    "is_IS": {"name_en": u("Icelandic"), "name": u("\xcdslenska")},
    "it_IT": {"name_en": u("Italian"), "name": u("Italiano")},
    "ja_JP": {"name_en": u("Japanese"), "name": u("\u65e5\u672c\u8a9e")},
    "ko_KR": {"name_en": u("Korean"), "name": u("\ud55c\uad6d\uc5b4")},
    "lt_LT": {"name_en": u("Lithuanian"), "name": u("Lietuvi\u0173")},
    "lv_LV": {"name_en": u("Latvian"), "name": u("Latvie\u0161u")},
    "mk_MK": {"name_en": u("Macedonian"), "name": u("\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438")},
    "ml_IN": {"name_en": u("Malayalam"), "name": u("\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02")},
    "ms_MY": {"name_en": u("Malay"), "name": u("Bahasa Melayu")},
    "nb_NO": {"name_en": u("Norwegian (bokmal)"), "name": u("Norsk (bokm\xe5l)")},
    "nl_NL": {"name_en": u("Dutch"), "name": u("Nederlands")},
    "nn_NO": {"name_en": u("Norwegian (nynorsk)"), "name": u("Norsk (nynorsk)")},
    "pa_IN": {"name_en": u("Punjabi"), "name": u("\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40")},
    "pl_PL": {"name_en": u("Polish"), "name": u("Polski")},
    "pt_BR": {"name_en": u("Portuguese (Brazil)"), "name": u("Portugu\xeas (Brasil)")},
    "pt_PT": {"name_en": u("Portuguese (Portugal)"), "name": u("Portugu\xeas (Portugal)")},
    "ro_RO": {"name_en": u("Romanian"), "name": u("Rom\xe2n\u0103")},
    "ru_RU": {"name_en": u("Russian"), "name": u("\u0420\u0443\u0441\u0441\u043a\u0438\u0439")},
    "sk_SK": {"name_en": u("Slovak"), "name": u("Sloven\u010dina")},
    "sl_SI": {"name_en": u("Slovenian"), "name": u("Sloven\u0161\u010dina")},
    "sq_AL": {"name_en": u("Albanian"), "name": u("Shqip")},
    "sr_RS": {"name_en": u("Serbian"), "name": u("\u0421\u0440\u043f\u0441\u043a\u0438")},
    "sv_SE": {"name_en": u("Swedish"), "name": u("Svenska")},
    "sw_KE": {"name_en": u("Swahili"), "name": u("Kiswahili")},
    "ta_IN": {"name_en": u("Tamil"), "name": u("\u0ba4\u0bae\u0bbf\u0bb4\u0bcd")},
    "te_IN": {"name_en": u("Telugu"), "name": u("\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41")},
    "th_TH": {"name_en": u("Thai"), "name": u("\u0e20\u0e32\u0e29\u0e32\u0e44\u0e17\u0e22")},
    "tl_PH": {"name_en": u("Filipino"), "name": u("Filipino")},
    "tr_TR": {"name_en": u("Turkish"), "name": u("T\xfcrk\xe7e")},
    "uk_UA": {"name_en": u("Ukraini "), "name": u("\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430")},
    "vi_VN": {"name_en": u("Vietnamese"), "name": u("Ti\u1ebfng Vi\u1ec7t")},
    "zh_CN": {"name_en": u("Chinese (Simplified)"), "name": u("\u4e2d\u6587(\u7b80\u4f53)")},
    "zh_TW": {"name_en": u("Chinese (Traditional)"), "name": u("\u4e2d\u6587(\u7e41\u9ad4)")},
}

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
[ISSUE]
**Title:** `locale.format_date` Raises `NameError` for `long` Type in Python 3

**Description:**
When using the `format_date` method from the `locale` module with a numeric timestamp, a `NameError` is raised in Python 3 due to the use of the undefined `long` type.

**Example Code:**
```python
import tornado.locale
import datetime

locale = tornado.locale.get('en_US')
timestamp = 1617181723.0  # Example timestamp as a float
formatted_date = locale.format_date(timestamp, full_format=True)
```

**Expected Behavior:**
The `format_date` method should correctly convert the numeric timestamp to a `datetime` object and return the formatted date string without errors.

**Actual Behavior:**
A `NameError` is raised indicating that `'long'` is not defined:
```
NameError: name 'long' is not defined
```
[/ISSUE]
{
    "EnglishTest.test_format_date": "PASSED",
    "LocaleDataTest.test_non_ascii_name": "PASSED",
    "TranslationLoaderTest.test_csv": "ERROR",
    "TranslationLoaderTest.test_gettext": "ERROR"
}
diff --git a/tornado/locale.py b/tornado/locale.py
index 66e9ff6d..310a5178 100644
--- a/tornado/locale.py
+++ b/tornado/locale.py
@@ -43,6 +43,7 @@ from __future__ import absolute_import, division, print_function, with_statement
 
 import csv
 import datetime
+import numbers
 import os
 import re
 
@@ -287,7 +288,7 @@ class Locale(object):
         """
         if self.code.startswith("ru"):
             relative = False
-        if type(date) in (int, long, float):
+        if isinstance(date, numbers.Real):
             date = datetime.datetime.utcfromtimestamp(date)
         now = datetime.datetime.utcnow()
         if date > now:

{"tornado/locale.py": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright 2009 Facebook\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n\n\"\"\"Translation methods for generating localized strings.\n\nTo load a locale and generate a translated string::\n\n    user_locale = tornado.locale.get(\"es_LA\")\n    print user_locale.translate(\"Sign out\")\n\n`tornado.locale.get()` returns the closest matching locale, not necessarily the\nspecific locale you requested. You can support pluralization with\nadditional arguments to `~Locale.translate()`, e.g.::\n\n    people = [...]\n    message = user_locale.translate(\n        \"%(list)s is online\", \"%(list)s are online\", len(people))\n    print message % {\"list\": user_locale.list(people)}\n\nThe first string is chosen if ``len(people) == 1``, otherwise the second\nstring is chosen.\n\nApplications should call one of `load_translations` (which uses a simple\nCSV format) or `load_gettext_translations` (which uses the ``.mo`` format\nsupported by `gettext` and related tools).  If neither method is called,\nthe `Locale.translate` method will simply return the original string.\n\"\"\"\n\nfrom __future__ import absolute_import, division, print_function, with_statement\n\nimport csv\nimport datetime\nimport os\nimport re\n\nfrom tornado import escape\nfrom tornado.log import gen_log\nfrom tornado.util import u\n\n_default_locale = \"en_US\"\n_translations = {}\n_supported_locales = frozenset([_default_locale])\n_use_gettext = False\n\n\ndef get(*locale_codes):\n    \"\"\"Returns the closest match for the given locale codes.\n\n    We iterate over all given locale codes in order. If we have a tight\n    or a loose match for the code (e.g., \"en\" for \"en_US\"), we return\n    the locale. Otherwise we move to the next code in the list.\n\n    By default we return ``en_US`` if no translations are found for any of\n    the specified locales. You can change the default locale with\n    `set_default_locale()`.\n    \"\"\"\n    return Locale.get_closest(*locale_codes)\n\n\ndef set_default_locale(code):\n    \"\"\"Sets the default locale.\n\n    The default locale is assumed to be the language used for all strings\n    in the system. The translations loaded from disk are mappings from\n    the default locale to the destination locale. Consequently, you don't\n    need to create a translation file for the default locale.\n    \"\"\"\n    global _default_locale\n    global _supported_locales\n    _default_locale = code\n    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])\n\n\ndef load_translations(directory):\n    \"\"\"Loads translations from CSV files in a directory.\n\n    Translations are strings with optional Python-style named placeholders\n    (e.g., ``My name is %(name)s``) and their associated translations.\n\n    The directory should have translation files of the form ``LOCALE.csv``,\n    e.g. ``es_GT.csv``. The CSV files should have two or three columns: string,\n    translation, and an optional plural indicator. Plural indicators should\n    be one of \"plural\" or \"singular\". A given string can have both singular\n    and plural forms. For example ``%(name)s liked this`` may have a\n    different verb conjugation depending on whether %(name)s is one\n    name or a list of names. There should be two rows in the CSV file for\n    that string, one with plural indicator \"singular\", and one \"plural\".\n    For strings with no verbs that would change on translation, simply\n    use \"unknown\" or the empty string (or don't include the column at all).\n\n    The file is read using the `csv` module in the default \"excel\" dialect.\n    In this format there should not be spaces after the commas.\n\n    Example translation ``es_LA.csv``::\n\n        \"I love you\",\"Te amo\"\n        \"%(name)s liked this\",\"A %(name)s les gust\u00f3 esto\",\"plural\"\n        \"%(name)s liked this\",\"A %(name)s le gust\u00f3 esto\",\"singular\"\n\n    \"\"\"\n    global _translations\n    global _supported_locales\n    _translations = {}\n    for path in os.listdir(directory):\n        if not path.endswith(\".csv\"):\n            continue\n        locale, extension = path.split(\".\")\n        if not re.match(\"[a-z]+(_[A-Z]+)?$\", locale):\n            gen_log.error(\"Unrecognized locale %r (path: %s)\", locale,\n                          os.path.join(directory, path))\n            continue\n        full_path = os.path.join(directory, path)\n        try:\n            # python 3: csv.reader requires a file open in text mode.\n            # Force utf8 to avoid dependence on $LANG environment variable.\n            f = open(full_path, \"r\", encoding=\"utf-8\")\n        except TypeError:\n            # python 2: files return byte strings, which are decoded below.\n            f = open(full_path, \"r\")\n        _translations[locale] = {}\n        for i, row in enumerate(csv.reader(f)):\n            if not row or len(row) < 2:\n                continue\n            row = [escape.to_unicode(c).strip() for c in row]\n            english, translation = row[:2]\n            if len(row) > 2:\n                plural = row[2] or \"unknown\"\n            else:\n                plural = \"unknown\"\n            if plural not in (\"plural\", \"singular\", \"unknown\"):\n                gen_log.error(\"Unrecognized plural indicator %r in %s line %d\",\n                              plural, path, i + 1)\n                continue\n            _translations[locale].setdefault(plural, {})[english] = translation\n        f.close()\n    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])\n    gen_log.debug(\"Supported locales: %s\", sorted(_supported_locales))\n\n\ndef load_gettext_translations(directory, domain):\n    \"\"\"Loads translations from `gettext`'s locale tree\n\n    Locale tree is similar to system's ``/usr/share/locale``, like::\n\n        {directory}/{lang}/LC_MESSAGES/{domain}.mo\n\n    Three steps are required to have you app translated:\n\n    1. Generate POT translation file::\n\n        xgettext --language=Python --keyword=_:1,2 -d mydomain file1.py file2.html etc\n\n    2. Merge against existing POT file::\n\n        msgmerge old.po mydomain.po > new.po\n\n    3. Compile::\n\n        msgfmt mydomain.po -o {directory}/pt_BR/LC_MESSAGES/mydomain.mo\n    \"\"\"\n    import gettext\n    global _translations\n    global _supported_locales\n    global _use_gettext\n    _translations = {}\n    for lang in os.listdir(directory):\n        if lang.startswith('.'):\n            continue  # skip .svn, etc\n        if os.path.isfile(os.path.join(directory, lang)):\n            continue\n        try:\n            os.stat(os.path.join(directory, lang, \"LC_MESSAGES\", domain + \".mo\"))\n            _translations[lang] = gettext.translation(domain, directory,\n                                                      languages=[lang])\n        except Exception as e:\n            gen_log.error(\"Cannot load translation for '%s': %s\", lang, str(e))\n            continue\n    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])\n    _use_gettext = True\n    gen_log.debug(\"Supported locales: %s\", sorted(_supported_locales))\n\n\ndef get_supported_locales():\n    \"\"\"Returns a list of all the supported locale codes.\"\"\"\n    return _supported_locales\n\n\nclass Locale(object):\n    \"\"\"Object representing a locale.\n\n    After calling one of `load_translations` or `load_gettext_translations`,\n    call `get` or `get_closest` to get a Locale object.\n    \"\"\"\n    @classmethod\n    def get_closest(cls, *locale_codes):\n        \"\"\"Returns the closest match for the given locale code.\"\"\"\n        for code in locale_codes:\n            if not code:\n                continue\n            code = code.replace(\"-\", \"_\")\n            parts = code.split(\"_\")\n            if len(parts) > 2:\n                continue\n            elif len(parts) == 2:\n                code = parts[0].lower() + \"_\" + parts[1].upper()\n            if code in _supported_locales:\n                return cls.get(code)\n            if parts[0].lower() in _supported_locales:\n                return cls.get(parts[0].lower())\n        return cls.get(_default_locale)\n\n    @classmethod\n    def get(cls, code):\n        \"\"\"Returns the Locale for the given locale code.\n\n        If it is not supported, we raise an exception.\n        \"\"\"\n        if not hasattr(cls, \"_cache\"):\n            cls._cache = {}\n        if code not in cls._cache:\n            assert code in _supported_locales\n            translations = _translations.get(code, None)\n            if translations is None:\n                locale = CSVLocale(code, {})\n            elif _use_gettext:\n                locale = GettextLocale(code, translations)\n            else:\n                locale = CSVLocale(code, translations)\n            cls._cache[code] = locale\n        return cls._cache[code]\n\n    def __init__(self, code, translations):\n        self.code = code\n        self.name = LOCALE_NAMES.get(code, {}).get(\"name\", u(\"Unknown\"))\n        self.rtl = False\n        for prefix in [\"fa\", \"ar\", \"he\"]:\n            if self.code.startswith(prefix):\n                self.rtl = True\n                break\n        self.translations = translations\n\n        # Initialize strings for date formatting\n        _ = self.translate\n        self._months = [\n            _(\"January\"), _(\"February\"), _(\"March\"), _(\"April\"),\n            _(\"May\"), _(\"June\"), _(\"July\"), _(\"August\"),\n            _(\"September\"), _(\"October\"), _(\"November\"), _(\"December\")]\n        self._weekdays = [\n            _(\"Monday\"), _(\"Tuesday\"), _(\"Wednesday\"), _(\"Thursday\"),\n            _(\"Friday\"), _(\"Saturday\"), _(\"Sunday\")]\n\n    def translate(self, message, plural_message=None, count=None):\n        \"\"\"Returns the translation for the given message for this locale.\n\n        If ``plural_message`` is given, you must also provide\n        ``count``. We return ``plural_message`` when ``count != 1``,\n        and we return the singular form for the given message when\n        ``count == 1``.\n        \"\"\"\n        raise NotImplementedError()\n\n    def format_date(self, date, gmt_offset=0, relative=True, shorter=False,\n                    full_format=False):\n        \"\"\"Formats the given date (which should be GMT).\n\n        By default, we return a relative time (e.g., \"2 minutes ago\"). You\n        can return an absolute date string with ``relative=False``.\n\n        You can force a full format date (\"July 10, 1980\") with\n        ``full_format=True``.\n\n        This method is primarily intended for dates in the past.\n        For dates in the future, we fall back to full format.\n        \"\"\"\n        if self.code.startswith(\"ru\"):\n            relative = False\n        if type(date) in (int, long, float):\n            date = datetime.datetime.utcfromtimestamp(date)\n        now = datetime.datetime.utcnow()\n        if date > now:\n            if relative and (date - now).seconds < 60:\n                # Due to click skew, things are some things slightly\n                # in the future. Round timestamps in the immediate\n                # future down to now in relative mode.\n                date = now\n            else:\n                # Otherwise, future dates always use the full format.\n                full_format = True\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        local_now = now - datetime.timedelta(minutes=gmt_offset)\n        local_yesterday = local_now - datetime.timedelta(hours=24)\n        difference = now - date\n        seconds = difference.seconds\n        days = difference.days\n\n        _ = self.translate\n        format = None\n        if not full_format:\n            if relative and days == 0:\n                if seconds < 50:\n                    return _(\"1 second ago\", \"%(seconds)d seconds ago\",\n                             seconds) % {\"seconds\": seconds}\n\n                if seconds < 50 * 60:\n                    minutes = round(seconds / 60.0)\n                    return _(\"1 minute ago\", \"%(minutes)d minutes ago\",\n                             minutes) % {\"minutes\": minutes}\n\n                hours = round(seconds / (60.0 * 60))\n                return _(\"1 hour ago\", \"%(hours)d hours ago\",\n                         hours) % {\"hours\": hours}\n\n            if days == 0:\n                format = _(\"%(time)s\")\n            elif days == 1 and local_date.day == local_yesterday.day and \\\n                    relative:\n                format = _(\"yesterday\") if shorter else \\\n                    _(\"yesterday at %(time)s\")\n            elif days < 5:\n                format = _(\"%(weekday)s\") if shorter else \\\n                    _(\"%(weekday)s at %(time)s\")\n            elif days < 334:  # 11mo, since confusing for same month last year\n                format = _(\"%(month_name)s %(day)s\") if shorter else \\\n                    _(\"%(month_name)s %(day)s at %(time)s\")\n\n        if format is None:\n            format = _(\"%(month_name)s %(day)s, %(year)s\") if shorter else \\\n                _(\"%(month_name)s %(day)s, %(year)s at %(time)s\")\n\n        tfhour_clock = self.code not in (\"en\", \"en_US\", \"zh_CN\")\n        if tfhour_clock:\n            str_time = \"%d:%02d\" % (local_date.hour, local_date.minute)\n        elif self.code == \"zh_CN\":\n            str_time = \"%s%d:%02d\" % (\n                (u('\\u4e0a\\u5348'), u('\\u4e0b\\u5348'))[local_date.hour >= 12],\n                local_date.hour % 12 or 12, local_date.minute)\n        else:\n            str_time = \"%d:%02d %s\" % (\n                local_date.hour % 12 or 12, local_date.minute,\n                (\"am\", \"pm\")[local_date.hour >= 12])\n\n        return format % {\n            \"month_name\": self._months[local_date.month - 1],\n            \"weekday\": self._weekdays[local_date.weekday()],\n            \"day\": str(local_date.day),\n            \"year\": str(local_date.year),\n            \"time\": str_time\n        }\n\n    def format_day(self, date, gmt_offset=0, dow=True):\n        \"\"\"Formats the given date as a day of week.\n\n        Example: \"Monday, January 22\". You can remove the day of week with\n        ``dow=False``.\n        \"\"\"\n        local_date = date - datetime.timedelta(minutes=gmt_offset)\n        _ = self.translate\n        if dow:\n            return _(\"%(weekday)s, %(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"weekday\": self._weekdays[local_date.weekday()],\n                \"day\": str(local_date.day),\n            }\n        else:\n            return _(\"%(month_name)s %(day)s\") % {\n                \"month_name\": self._months[local_date.month - 1],\n                \"day\": str(local_date.day),\n            }\n\n    def list(self, parts):\n        \"\"\"Returns a comma-separated list for the given list of parts.\n\n        The format is, e.g., \"A, B and C\", \"A and B\" or just \"A\" for lists\n        of size 1.\n        \"\"\"\n        _ = self.translate\n        if len(parts) == 0:\n            return \"\"\n        if len(parts) == 1:\n            return parts[0]\n        comma = u(' \\u0648 ') if self.code.startswith(\"fa\") else u(\", \")\n        return _(\"%(commas)s and %(last)s\") % {\n            \"commas\": comma.join(parts[:-1]),\n            \"last\": parts[len(parts) - 1],\n        }\n\n    def friendly_number(self, value):\n        \"\"\"Returns a comma-separated number for the given integer.\"\"\"\n        if self.code not in (\"en\", \"en_US\"):\n            return str(value)\n        value = str(value)\n        parts = []\n        while value:\n            parts.append(value[-3:])\n            value = value[:-3]\n        return \",\".join(reversed(parts))\n\n\nclass CSVLocale(Locale):\n    \"\"\"Locale implementation using tornado's CSV translation format.\"\"\"\n    def translate(self, message, plural_message=None, count=None):\n        if plural_message is not None:\n            assert count is not None\n            if count != 1:\n                message = plural_message\n                message_dict = self.translations.get(\"plural\", {})\n            else:\n                message_dict = self.translations.get(\"singular\", {})\n        else:\n            message_dict = self.translations.get(\"unknown\", {})\n        return message_dict.get(message, message)\n\n\nclass GettextLocale(Locale):\n    \"\"\"Locale implementation using the `gettext` module.\"\"\"\n    def __init__(self, code, translations):\n        try:\n            # python 2\n            self.ngettext = translations.ungettext\n            self.gettext = translations.ugettext\n        except AttributeError:\n            # python 3\n            self.ngettext = translations.ngettext\n            self.gettext = translations.gettext\n        # self.gettext must exist before __init__ is called, since it\n        # calls into self.translate\n        super(GettextLocale, self).__init__(code, translations)\n\n    def translate(self, message, plural_message=None, count=None):\n        if plural_message is not None:\n            assert count is not None\n            return self.ngettext(message, plural_message, count)\n        else:\n            return self.gettext(message)\n\nLOCALE_NAMES = {\n    \"af_ZA\": {\"name_en\": u(\"Afrikaans\"), \"name\": u(\"Afrikaans\")},\n    \"am_ET\": {\"name_en\": u(\"Amharic\"), \"name\": u('\\u12a0\\u121b\\u122d\\u129b')},\n    \"ar_AR\": {\"name_en\": u(\"Arabic\"), \"name\": u(\"\\u0627\\u0644\\u0639\\u0631\\u0628\\u064a\\u0629\")},\n    \"bg_BG\": {\"name_en\": u(\"Bulgarian\"), \"name\": u(\"\\u0411\\u044a\\u043b\\u0433\\u0430\\u0440\\u0441\\u043a\\u0438\")},\n    \"bn_IN\": {\"name_en\": u(\"Bengali\"), \"name\": u(\"\\u09ac\\u09be\\u0982\\u09b2\\u09be\")},\n    \"bs_BA\": {\"name_en\": u(\"Bosnian\"), \"name\": u(\"Bosanski\")},\n    \"ca_ES\": {\"name_en\": u(\"Catalan\"), \"name\": u(\"Catal\\xe0\")},\n    \"cs_CZ\": {\"name_en\": u(\"Czech\"), \"name\": u(\"\\u010ce\\u0161tina\")},\n    \"cy_GB\": {\"name_en\": u(\"Welsh\"), \"name\": u(\"Cymraeg\")},\n    \"da_DK\": {\"name_en\": u(\"Danish\"), \"name\": u(\"Dansk\")},\n    \"de_DE\": {\"name_en\": u(\"German\"), \"name\": u(\"Deutsch\")},\n    \"el_GR\": {\"name_en\": u(\"Greek\"), \"name\": u(\"\\u0395\\u03bb\\u03bb\\u03b7\\u03bd\\u03b9\\u03ba\\u03ac\")},\n    \"en_GB\": {\"name_en\": u(\"English (UK)\"), \"name\": u(\"English (UK)\")},\n    \"en_US\": {\"name_en\": u(\"English (US)\"), \"name\": u(\"English (US)\")},\n    \"es_ES\": {\"name_en\": u(\"Spanish (Spain)\"), \"name\": u(\"Espa\\xf1ol (Espa\\xf1a)\")},\n    \"es_LA\": {\"name_en\": u(\"Spanish\"), \"name\": u(\"Espa\\xf1ol\")},\n    \"et_EE\": {\"name_en\": u(\"Estonian\"), \"name\": u(\"Eesti\")},\n    \"eu_ES\": {\"name_en\": u(\"Basque\"), \"name\": u(\"Euskara\")},\n    \"fa_IR\": {\"name_en\": u(\"Persian\"), \"name\": u(\"\\u0641\\u0627\\u0631\\u0633\\u06cc\")},\n    \"fi_FI\": {\"name_en\": u(\"Finnish\"), \"name\": u(\"Suomi\")},\n    \"fr_CA\": {\"name_en\": u(\"French (Canada)\"), \"name\": u(\"Fran\\xe7ais (Canada)\")},\n    \"fr_FR\": {\"name_en\": u(\"French\"), \"name\": u(\"Fran\\xe7ais\")},\n    \"ga_IE\": {\"name_en\": u(\"Irish\"), \"name\": u(\"Gaeilge\")},\n    \"gl_ES\": {\"name_en\": u(\"Galician\"), \"name\": u(\"Galego\")},\n    \"he_IL\": {\"name_en\": u(\"Hebrew\"), \"name\": u(\"\\u05e2\\u05d1\\u05e8\\u05d9\\u05ea\")},\n    \"hi_IN\": {\"name_en\": u(\"Hindi\"), \"name\": u(\"\\u0939\\u093f\\u0928\\u094d\\u0926\\u0940\")},\n    \"hr_HR\": {\"name_en\": u(\"Croatian\"), \"name\": u(\"Hrvatski\")},\n    \"hu_HU\": {\"name_en\": u(\"Hungarian\"), \"name\": u(\"Magyar\")},\n    \"id_ID\": {\"name_en\": u(\"Indonesian\"), \"name\": u(\"Bahasa Indonesia\")},\n    \"is_IS\": {\"name_en\": u(\"Icelandic\"), \"name\": u(\"\\xcdslenska\")},\n    \"it_IT\": {\"name_en\": u(\"Italian\"), \"name\": u(\"Italiano\")},\n    \"ja_JP\": {\"name_en\": u(\"Japanese\"), \"name\": u(\"\\u65e5\\u672c\\u8a9e\")},\n    \"ko_KR\": {\"name_en\": u(\"Korean\"), \"name\": u(\"\\ud55c\\uad6d\\uc5b4\")},\n    \"lt_LT\": {\"name_en\": u(\"Lithuanian\"), \"name\": u(\"Lietuvi\\u0173\")},\n    \"lv_LV\": {\"name_en\": u(\"Latvian\"), \"name\": u(\"Latvie\\u0161u\")},\n    \"mk_MK\": {\"name_en\": u(\"Macedonian\"), \"name\": u(\"\\u041c\\u0430\\u043a\\u0435\\u0434\\u043e\\u043d\\u0441\\u043a\\u0438\")},\n    \"ml_IN\": {\"name_en\": u(\"Malayalam\"), \"name\": u(\"\\u0d2e\\u0d32\\u0d2f\\u0d3e\\u0d33\\u0d02\")},\n    \"ms_MY\": {\"name_en\": u(\"Malay\"), \"name\": u(\"Bahasa Melayu\")},\n    \"nb_NO\": {\"name_en\": u(\"Norwegian (bokmal)\"), \"name\": u(\"Norsk (bokm\\xe5l)\")},\n    \"nl_NL\": {\"name_en\": u(\"Dutch\"), \"name\": u(\"Nederlands\")},\n    \"nn_NO\": {\"name_en\": u(\"Norwegian (nynorsk)\"), \"name\": u(\"Norsk (nynorsk)\")},\n    \"pa_IN\": {\"name_en\": u(\"Punjabi\"), \"name\": u(\"\\u0a2a\\u0a70\\u0a1c\\u0a3e\\u0a2c\\u0a40\")},\n    \"pl_PL\": {\"name_en\": u(\"Polish\"), \"name\": u(\"Polski\")},\n    \"pt_BR\": {\"name_en\": u(\"Portuguese (Brazil)\"), \"name\": u(\"Portugu\\xeas (Brasil)\")},\n    \"pt_PT\": {\"name_en\": u(\"Portuguese (Portugal)\"), \"name\": u(\"Portugu\\xeas (Portugal)\")},\n    \"ro_RO\": {\"name_en\": u(\"Romanian\"), \"name\": u(\"Rom\\xe2n\\u0103\")},\n    \"ru_RU\": {\"name_en\": u(\"Russian\"), \"name\": u(\"\\u0420\\u0443\\u0441\\u0441\\u043a\\u0438\\u0439\")},\n    \"sk_SK\": {\"name_en\": u(\"Slovak\"), \"name\": u(\"Sloven\\u010dina\")},\n    \"sl_SI\": {\"name_en\": u(\"Slovenian\"), \"name\": u(\"Sloven\\u0161\\u010dina\")},\n    \"sq_AL\": {\"name_en\": u(\"Albanian\"), \"name\": u(\"Shqip\")},\n    \"sr_RS\": {\"name_en\": u(\"Serbian\"), \"name\": u(\"\\u0421\\u0440\\u043f\\u0441\\u043a\\u0438\")},\n    \"sv_SE\": {\"name_en\": u(\"Swedish\"), \"name\": u(\"Svenska\")},\n    \"sw_KE\": {\"name_en\": u(\"Swahili\"), \"name\": u(\"Kiswahili\")},\n    \"ta_IN\": {\"name_en\": u(\"Tamil\"), \"name\": u(\"\\u0ba4\\u0bae\\u0bbf\\u0bb4\\u0bcd\")},\n    \"te_IN\": {\"name_en\": u(\"Telugu\"), \"name\": u(\"\\u0c24\\u0c46\\u0c32\\u0c41\\u0c17\\u0c41\")},\n    \"th_TH\": {\"name_en\": u(\"Thai\"), \"name\": u(\"\\u0e20\\u0e32\\u0e29\\u0e32\\u0e44\\u0e17\\u0e22\")},\n    \"tl_PH\": {\"name_en\": u(\"Filipino\"), \"name\": u(\"Filipino\")},\n    \"tr_TR\": {\"name_en\": u(\"Turkish\"), \"name\": u(\"T\\xfcrk\\xe7e\")},\n    \"uk_UA\": {\"name_en\": u(\"Ukraini \"), \"name\": u(\"\\u0423\\u043a\\u0440\\u0430\\u0457\\u043d\\u0441\\u044c\\u043a\\u0430\")},\n    \"vi_VN\": {\"name_en\": u(\"Vietnamese\"), \"name\": u(\"Ti\\u1ebfng Vi\\u1ec7t\")},\n    \"zh_CN\": {\"name_en\": u(\"Chinese (Simplified)\"), \"name\": u(\"\\u4e2d\\u6587(\\u7b80\\u4f53)\")},\n    \"zh_TW\": {\"name_en\": u(\"Chinese (Traditional)\"), \"name\": u(\"\\u4e2d\\u6587(\\u7e41\\u9ad4)\")},\n}\n"}
A user will ask you to solve a task. You should first draft your thinking process (inner monologue). Then, generate the solution.

Your response format must follow the template below:
<think>
Your thoughts or/and draft, like working through an exercise on scratch paper. Be as casual and as long as you want until you are confident to generate a correct solution.
</think>
<solution>
Final solution presented to the user.
</solution>
system
We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[ISSUE]
**Title:** `locale.format_date` Raises `NameError` for `long` Type in Python 3

**Description:**
When using the `format_date` method from the `locale` module with a numeric timestamp, a `NameError` is raised in Python 3 due to the use of the undefined `long` type.

**Example Code:**
```python
import tornado.locale
import datetime

locale = tornado.locale.get('en_US')
timestamp = 1617181723.0  # Example timestamp as a float
formatted_date = locale.format_date(timestamp, full_format=True)
```

**Expected Behavior:**
The `format_date` method should correctly convert the numeric timestamp to a `datetime` object and return the formatted date string without errors.

**Actual Behavior:**
A `NameError` is raised indicating that `'long'` is not defined:
```
NameError: name 'long' is not defined
```
[/ISSUE]
--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.

--- BEGIN FILE ---
```
### tornado/locale.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2009 Facebook
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""Translation methods for generating localized strings.

To load a locale and generate a translated string::

    user_locale = tornado.locale.get("es_LA")
    print user_locale.translate("Sign out")

`tornado.locale.get()` returns the closest matching locale, not necessarily the
specific locale you requested. You can support pluralization with
additional arguments to `~Locale.translate()`, e.g.::

    people = [...]
    message = user_locale.translate(
        "%(list)s is online", "%(list)s are online", len(people))
    print message % {"list": user_locale.list(people)}

The first string is chosen if ``len(people) == 1``, otherwise the second
string is chosen.

Applications should call one of `load_translations` (which uses a simple
CSV format) or `load_gettext_translations` (which uses the ``.mo`` format
supported by `gettext` and related tools).  If neither method is called,
the `Locale.translate` method will simply return the original string.
"""

from __future__ import absolute_import, division, print_function, with_statement

import csv
import datetime
import os
import re

from tornado import escape
from tornado.log import gen_log
from tornado.util import u

_default_locale = "en_US"
_translations = {}
_supported_locales = frozenset([_default_locale])
_use_gettext = False


def get(*locale_codes):
    """Returns the closest match for the given locale codes.

    We iterate over all given locale codes in order. If we have a tight
    or a loose match for the code (e.g., "en" for "en_US"), we return
    the locale. Otherwise we move to the next code in the list.

    By default we return ``en_US`` if no translations are found for any of
    the specified locales. You can change the default locale with
    `set_default_locale()`.
    """
    return Locale.get_closest(*locale_codes)


def set_default_locale(code):
    """Sets the default locale.

    The default locale is assumed to be the language used for all strings
    in the system. The translations loaded from disk are mappings from
    the default locale to the destination locale. Consequently, you don't
    need to create a translation file for the default locale.
    """
    global _default_locale
    global _supported_locales
    _default_locale = code
    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])


def load_translations(directory):
    """Loads translations from CSV files in a directory.

    Translations are strings with optional Python-style named placeholders
    (e.g., ``My name is %(name)s``) and their associated translations.

    The directory should have translation files of the form ``LOCALE.csv``,
    e.g. ``es_GT.csv``. The CSV files should have two or three columns: string,
    translation, and an optional plural indicator. Plural indicators should
    be one of "plural" or "singular". A given string can have both singular
    and plural forms. For example ``%(name)s liked this`` may have a
    different verb conjugation depending on whether %(name)s is one
    name or a list of names. There should be two rows in the CSV file for
    that string, one with plural indicator "singular", and one "plural".
    For strings with no verbs that would change on translation, simply
    use "unknown" or the empty string (or don't include the column at all).

    The file is read using the `csv` module in the default "excel" dialect.
    In this format there should not be spaces after the commas.

    Example translation ``es_LA.csv``::

        "I love you","Te amo"
        "%(name)s liked this","A %(name)s les gustó esto","plural"
        "%(name)s liked this","A %(name)s le gustó esto","singular"

    """
    global _translations
    global _supported_locales
    _translations = {}
    for path in os.listdir(directory):
        if not path.endswith(".csv"):
            continue
        locale, extension = path.split(".")
        if not re.match("[a-z]+(_[A-Z]+)?$", locale):
            gen_log.error("Unrecognized locale %r (path: %s)", locale,
                          os.path.join(directory, path))
            continue
        full_path = os.path.join(directory, path)
        try:
            # python 3: csv.reader requires a file open in text mode.
            # Force utf8 to avoid dependence on $LANG environment variable.
            f = open(full_path, "r", encoding="utf-8")
        except TypeError:
            # python 2: files return byte strings, which are decoded below.
            f = open(full_path, "r")
        _translations[locale] = {}
        for i, row in enumerate(csv.reader(f)):
            if not row or len(row) < 2:
                continue
            row = [escape.to_unicode(c).strip() for c in row]
            english, translation = row[:2]
            if len(row) > 2:
                plural = row[2] or "unknown"
            else:
                plural = "unknown"
            if plural not in ("plural", "singular", "unknown"):
                gen_log.error("Unrecognized plural indicator %r in %s line %d",
                              plural, path, i + 1)
                continue
            _translations[locale].setdefault(plural, {})[english] = translation
        f.close()
    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])
    gen_log.debug("Supported locales: %s", sorted(_supported_locales))


def load_gettext_translations(directory, domain):
    """Loads translations from `gettext`'s locale tree

    Locale tree is similar to system's ``/usr/share/locale``, like::

        {directory}/{lang}/LC_MESSAGES/{domain}.mo

    Three steps are required to have you app translated:

    1. Generate POT translation file::

        xgettext --language=Python --keyword=_:1,2 -d mydomain file1.py file2.html etc

    2. Merge against existing POT file::

        msgmerge old.po mydomain.po > new.po

    3. Compile::

        msgfmt mydomain.po -o {directory}/pt_BR/LC_MESSAGES/mydomain.mo
    """
    import gettext
    global _translations
    global _supported_locales
    global _use_gettext
    _translations = {}
    for lang in os.listdir(directory):
        if lang.startswith('.'):
            continue  # skip .svn, etc
        if os.path.isfile(os.path.join(directory, lang)):
            continue
        try:
            os.stat(os.path.join(directory, lang, "LC_MESSAGES", domain + ".mo"))
            _translations[lang] = gettext.translation(domain, directory,
                                                      languages=[lang])
        except Exception as e:
            gen_log.error("Cannot load translation for '%s': %s", lang, str(e))
            continue
    _supported_locales = frozenset(list(_translations.keys()) + [_default_locale])
    _use_gettext = True
    gen_log.debug("Supported locales: %s", sorted(_supported_locales))


def get_supported_locales():
    """Returns a list of all the supported locale codes."""
    return _supported_locales


class Locale(object):
    """Object representing a locale.

    After calling one of `load_translations` or `load_gettext_translations`,
    call `get` or `get_closest` to get a Locale object.
    """
    @classmethod
    def get_closest(cls, *locale_codes):
        """Returns the closest match for the given locale code."""
        for code in locale_codes:
            if not code:
                continue
            code = code.replace("-", "_")
            parts = code.split("_")
            if len(parts) > 2:
                continue
            elif len(parts) == 2:
                code = parts[0].lower() + "_" + parts[1].upper()
            if code in _supported_locales:
                return cls.get(code)
            if parts[0].lower() in _supported_locales:
                return cls.get(parts[0].lower())
        return cls.get(_default_locale)

    @classmethod
    def get(cls, code):
        """Returns the Locale for the given locale code.

        If it is not supported, we raise an exception.
        """
        if not hasattr(cls, "_cache"):
            cls._cache = {}
        if code not in cls._cache:
            assert code in _supported_locales
            translations = _translations.get(code, None)
            if translations is None:
                locale = CSVLocale(code, {})
            elif _use_gettext:
                locale = GettextLocale(code, translations)
            else:
                locale = CSVLocale(code, translations)
            cls._cache[code] = locale
        return cls._cache[code]

    def __init__(self, code, translations):
        self.code = code
        self.name = LOCALE_NAMES.get(code, {}).get("name", u("Unknown"))
        self.rtl = False
        for prefix in ["fa", "ar", "he"]:
            if self.code.startswith(prefix):
                self.rtl = True
                break
        self.translations = translations

        # Initialize strings for date formatting
        _ = self.translate
        self._months = [
            _("January"), _("February"), _("March"), _("April"),
            _("May"), _("June"), _("July"), _("August"),
            _("September"), _("October"), _("November"), _("December")]
        self._weekdays = [
            _("Monday"), _("Tuesday"), _("Wednesday"), _("Thursday"),
            _("Friday"), _("Saturday"), _("Sunday")]

    def translate(self, message, plural_message=None, count=None):
        """Returns the translation for the given message for this locale.

        If ``plural_message`` is given, you must also provide
        ``count``. We return ``plural_message`` when ``count != 1``,
        and we return the singular form for the given message when
        ``count == 1``.
        """
        raise NotImplementedError()

    def format_date(self, date, gmt_offset=0, relative=True, shorter=False,
                    full_format=False):
        """Formats the given date (which should be GMT).

        By default, we return a relative time (e.g., "2 minutes ago"). You
        can return an absolute date string with ``relative=False``.

        You can force a full format date ("July 10, 1980") with
        ``full_format=True``.

        This method is primarily intended for dates in the past.
        For dates in the future, we fall back to full format.
        """
        if self.code.startswith("ru"):
            relative = False
        if type(date) in (int, long, float):
            date = datetime.datetime.utcfromtimestamp(date)
        now = datetime.datetime.utcnow()
        if date > now:
            if relative and (date - now).seconds < 60:
                # Due to click skew, things are some things slightly
                # in the future. Round timestamps in the immediate
                # future down to now in relative mode.
                date = now
            else:
                # Otherwise, future dates always use the full format.
                full_format = True
        local_date = date - datetime.timedelta(minutes=gmt_offset)
        local_now = now - datetime.timedelta(minutes=gmt_offset)
        local_yesterday = local_now - datetime.timedelta(hours=24)
        difference = now - date
        seconds = difference.seconds
        days = difference.days

        _ = self.translate
        format = None
        if not full_format:
            if relative and days == 0:
                if seconds < 50:
                    return _("1 second ago", "%(seconds)d seconds ago",
                             seconds) % {"seconds": seconds}

                if seconds < 50 * 60:
                    minutes = round(seconds / 60.0)
                    return _("1 minute ago", "%(minutes)d minutes ago",
                             minutes) % {"minutes": minutes}

                hours = round(seconds / (60.0 * 60))
                return _("1 hour ago", "%(hours)d hours ago",
                         hours) % {"hours": hours}

            if days == 0:
                format = _("%(time)s")
            elif days == 1 and local_date.day == local_yesterday.day and \
                    relative:
                format = _("yesterday") if shorter else \
                    _("yesterday at %(time)s")
            elif days < 5:
                format = _("%(weekday)s") if shorter else \
                    _("%(weekday)s at %(time)s")
            elif days < 334:  # 11mo, since confusing for same month last year
                format = _("%(month_name)s %(day)s") if shorter else \
                    _("%(month_name)s %(day)s at %(time)s")

        if format is None:
            format = _("%(month_name)s %(day)s, %(year)s") if shorter else \
                _("%(month_name)s %(day)s, %(year)s at %(time)s")

        tfhour_clock = self.code not in ("en", "en_US", "zh_CN")
        if tfhour_clock:
            str_time = "%d:%02d" % (local_date.hour, local_date.minute)
        elif self.code == "zh_CN":
            str_time = "%s%d:%02d" % (
                (u('\u4e0a\u5348'), u('\u4e0b\u5348'))[local_date.hour >= 12],
                local_date.hour % 12 or 12, local_date.minute)
        else:
            str_time = "%d:%02d %s" % (
                local_date.hour % 12 or 12, local_date.minute,
                ("am", "pm")[local_date.hour >= 12])

        return format % {
            "month_name": self._months[local_date.month - 1],
            "weekday": self._weekdays[local_date.weekday()],
            "day": str(local_date.day),
            "year": str(local_date.year),
            "time": str_time
        }

    def format_day(self, date, gmt_offset=0, dow=True):
        """Formats the given date as a day of week.

        Example: "Monday, January 22". You can remove the day of week with
        ``dow=False``.
        """
        local_date = date - datetime.timedelta(minutes=gmt_offset)
        _ = self.translate
        if dow:
            return _("%(weekday)s, %(month_name)s %(day)s") % {
                "month_name": self._months[local_date.month - 1],
                "weekday": self._weekdays[local_date.weekday()],
                "day": str(local_date.day),
            }
        else:
            return _("%(month_name)s %(day)s") % {
                "month_name": self._months[local_date.month - 1],
                "day": str(local_date.day),
            }

    def list(self, parts):
        """Returns a comma-separated list for the given list of parts.

        The format is, e.g., "A, B and C", "A and B" or just "A" for lists
        of size 1.
        """
        _ = self.translate
        if len(parts) == 0:
            return ""
        if len(parts) == 1:
            return parts[0]
        comma = u(' \u0648 ') if self.code.startswith("fa") else u(", ")
        return _("%(commas)s and %(last)s") % {
            "commas": comma.join(parts[:-1]),
            "last": parts[len(parts) - 1],
        }

    def friendly_number(self, value):
        """Returns a comma-separated number for the given integer."""
        if self.code not in ("en", "en_US"):
            return str(value)
        value = str(value)
        parts = []
        while value:
            parts.append(value[-3:])
            value = value[:-3]
        return ",".join(reversed(parts))


class CSVLocale(Locale):
    """Locale implementation using tornado's CSV translation format."""
    def translate(self, message, plural_message=None, count=None):
        if plural_message is not None:
            assert count is not None
            if count != 1:
                message = plural_message
                message_dict = self.translations.get("plural", {})
            else:
                message_dict = self.translations.get("singular", {})
        else:
            message_dict = self.translations.get("unknown", {})
        return message_dict.get(message, message)


class GettextLocale(Locale):
    """Locale implementation using the `gettext` module."""
    def __init__(self, code, translations):
        try:
            # python 2
            self.ngettext = translations.ungettext
            self.gettext = translations.ugettext
        except AttributeError:
            # python 3
            self.ngettext = translations.ngettext
            self.gettext = translations.gettext
        # self.gettext must exist before __init__ is called, since it
        # calls into self.translate
        super(GettextLocale, self).__init__(code, translations)

    def translate(self, message, plural_message=None, count=None):
        if plural_message is not None:
            assert count is not None
            return self.ngettext(message, plural_message, count)
        else:
            return self.gettext(message)

LOCALE_NAMES = {
    "af_ZA": {"name_en": u("Afrikaans"), "name": u("Afrikaans")},
    "am_ET": {"name_en": u("Amharic"), "name": u('\u12a0\u121b\u122d\u129b')},
    "ar_AR": {"name_en": u("Arabic"), "name": u("\u0627\u0644\u0639\u0631\u0628\u064a\u0629")},
    "bg_BG": {"name_en": u("Bulgarian"), "name": u("\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438")},
    "bn_IN": {"name_en": u("Bengali"), "name": u("\u09ac\u09be\u0982\u09b2\u09be")},
    "bs_BA": {"name_en": u("Bosnian"), "name": u("Bosanski")},
    "ca_ES": {"name_en": u("Catalan"), "name": u("Catal\xe0")},
    "cs_CZ": {"name_en": u("Czech"), "name": u("\u010ce\u0161tina")},
    "cy_GB": {"name_en": u("Welsh"), "name": u("Cymraeg")},
    "da_DK": {"name_en": u("Danish"), "name": u("Dansk")},
    "de_DE": {"name_en": u("German"), "name": u("Deutsch")},
    "el_GR": {"name_en": u("Greek"), "name": u("\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac")},
    "en_GB": {"name_en": u("English (UK)"), "name": u("English (UK)")},
    "en_US": {"name_en": u("English (US)"), "name": u("English (US)")},
    "es_ES": {"name_en": u("Spanish (Spain)"), "name": u("Espa\xf1ol (Espa\xf1a)")},
    "es_LA": {"name_en": u("Spanish"), "name": u("Espa\xf1ol")},
    "et_EE": {"name_en": u("Estonian"), "name": u("Eesti")},
    "eu_ES": {"name_en": u("Basque"), "name": u("Euskara")},
    "fa_IR": {"name_en": u("Persian"), "name": u("\u0641\u0627\u0631\u0633\u06cc")},
    "fi_FI": {"name_en": u("Finnish"), "name": u("Suomi")},
    "fr_CA": {"name_en": u("French (Canada)"), "name": u("Fran\xe7ais (Canada)")},
    "fr_FR": {"name_en": u("French"), "name": u("Fran\xe7ais")},
    "ga_IE": {"name_en": u("Irish"), "name": u("Gaeilge")},
    "gl_ES": {"name_en": u("Galician"), "name": u("Galego")},
    "he_IL": {"name_en": u("Hebrew"), "name": u("\u05e2\u05d1\u05e8\u05d9\u05ea")},
    "hi_IN": {"name_en": u("Hindi"), "name": u("\u0939\u093f\u0928\u094d\u0926\u0940")},
    "hr_HR": {"name_en": u("Croatian"), "name": u("Hrvatski")},
    "hu_HU": {"name_en": u("Hungarian"), "name": u("Magyar")},
    "id_ID": {"name_en": u("Indonesian"), "name": u("Bahasa Indonesia")},
    "is_IS": {"name_en": u("Icelandic"), "name": u("\xcdslenska")},
    "it_IT": {"name_en": u("Italian"), "name": u("Italiano")},
    "ja_JP": {"name_en": u("Japanese"), "name": u("\u65e5\u672c\u8a9e")},
    "ko_KR": {"name_en": u("Korean"), "name": u("\ud55c\uad6d\uc5b4")},
    "lt_LT": {"name_en": u("Lithuanian"), "name": u("Lietuvi\u0173")},
    "lv_LV": {"name_en": u("Latvian"), "name": u("Latvie\u0161u")},
    "mk_MK": {"name_en": u("Macedonian"), "name": u("\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438")},
    "ml_IN": {"name_en": u("Malayalam"), "name": u("\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02")},
    "ms_MY": {"name_en": u("Malay"), "name": u("Bahasa Melayu")},
    "nb_NO": {"name_en": u("Norwegian (bokmal)"), "name": u("Norsk (bokm\xe5l)")},
    "nl_NL": {"name_en": u("Dutch"), "name": u("Nederlands")},
    "nn_NO": {"name_en": u("Norwegian (nynorsk)"), "name": u("Norsk (nynorsk)")},
    "pa_IN": {"name_en": u("Punjabi"), "name": u("\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40")},
    "pl_PL": {"name_en": u("Polish"), "name": u("Polski")},
    "pt_BR": {"name_en": u("Portuguese (Brazil)"), "name": u("Portugu\xeas (Brasil)")},
    "pt_PT": {"name_en": u("Portuguese (Portugal)"), "name": u("Portugu\xeas (Portugal)")},
    "ro_RO": {"name_en": u("Romanian"), "name": u("Rom\xe2n\u0103")},
    "ru_RU": {"name_en": u("Russian"), "name": u("\u0420\u0443\u0441\u0441\u043a\u0438\u0439")},
    "sk_SK": {"name_en": u("Slovak"), "name": u("Sloven\u010dina")},
    "sl_SI": {"name_en": u("Slovenian"), "name": u("Sloven\u0161\u010dina")},
    "sq_AL": {"name_en": u("Albanian"), "name": u("Shqip")},
    "sr_RS": {"name_en": u("Serbian"), "name": u("\u0421\u0440\u043f\u0441\u043a\u0438")},
    "sv_SE": {"name_en": u("Swedish"), "name": u("Svenska")},
    "sw_KE": {"name_en": u("Swahili"), "name": u("Kiswahili")},
    "ta_IN": {"name_en": u("Tamil"), "name": u("\u0ba4\u0bae\u0bbf\u0bb4\u0bcd")},
    "te_IN": {"name_en": u("Telugu"), "name": u("\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41")},
    "th_TH": {"name_en": u("Thai"), "name": u("\u0e20\u0e32\u0e29\u0e32\u0e44\u0e17\u0e22")},
    "tl_PH": {"name_en": u("Filipino"), "name": u("Filipino")},
    "tr_TR": {"name_en": u("Turkish"), "name": u("T\xfcrk\xe7e")},
    "uk_UA": {"name_en": u("Ukraini "), "name": u("\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430")},
    "vi_VN": {"name_en": u("Vietnamese"), "name": u("Ti\u1ebfng Vi\u1ec7t")},
    "zh_CN": {"name_en": u("Chinese (Simplified)"), "name": u("\u4e2d\u6587(\u7b80\u4f53)")},
    "zh_TW": {"name_en": u("Chinese (Traditional)"), "name": u("\u4e2d\u6587(\u7e41\u9ad4)")},
}

```
--- END FILE ---

Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.

Every *SEARCH/REPLACE* edit must use this format:
1. The file path
2. The start of search block: <<<<<<< SEARCH
3. A contiguous chunk of lines to search for in the existing source code
4. The dividing line: =======
5. The lines to replace into the source code
6. The end of the replace block: >>>>>>> REPLACE

Here is an example:

```python
### mathweb/flask/app.py
<<<<<<< SEARCH
from flask import Flask
=======
import math
from flask import Flask
>>>>>>> REPLACE
```
</solution>

Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
Wrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.
user