Repository: tornadoweb/tornado

Issue:
"Cannot load translation for ..." error messages
I am providing a service with only some languages. When my translations lie in the regular directory `/usr/share/locale/` every time starting the service 217 error messages are logged:
```
…
Cannot load translation for 'ps': [Errno 2] No such file or directory: '/usr/share/locale/ps/LC_MESSAGES/foo.mo'
Cannot load translation for 'is': [Errno 2] No such file or directory: '/usr/share/locale/is/LC_MESSAGES/foo.mo'
Cannot load translation for 'az': [Errno 2] No such file or directory: '/usr/share/locale/az/LC_MESSAGES/foo.mo'
Cannot load translation for 'an': [Errno 2] No such file or directory: '/usr/share/locale/an/LC_MESSAGES/foo.mo'
Cannot load translation for 'fa': [Errno 2] No such file or directory: '/usr/share/locale/fa/LC_MESSAGES/foo.mo'
Cannot load translation for 'ta': [Errno 2] No such file or directory: '/usr/share/locale/ta/LC_MESSAGES/foo.mo'
Cannot load translation for 'en_GB': [Errno 2] No such file or directory: '/usr/share/locale/en_GB/LC_MESSAGES/foo.mo'
```

There is no way to suppress them or specify a list of languages to load.
Issue #2954: prevent logging error messages for not existing translation files
Every not existing translation file for the existing locales logged an error message:
Cannot load translation for 'ps': [Errno 2] No such file or directory: '/usr/share/locale/ps/LC_MESSAGES/foo.mo'


Discussion:
Maybe consider this patch, which only finds existing files?:

```diff
diff --git tornado/locale.py tornado/locale.py
index adb1f774..30f92f90 100644
--- tornado/locale.py
+++ tornado/locale.py
@@ -198,13 +198,11 @@ def load_gettext_translations(directory: str, domain: str) -> None:
     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
+
+    import glob  # move to top
+    for filename in glob.glob(os.path.join(directory, '*', 'LC_MESSAGES', domain + '.mo')):
+        lang = filename.split('/LC_MESSAGES/', 1)[0].split(directory, 1)[1].strip('/')
         try:
-            os.stat(os.path.join(directory, lang, "LC_MESSAGES", domain + ".mo"))
             _translations[lang] = gettext.translation(
                 domain, directory, languages=[lang]
             )
```
Yeah, that makes sense. The gettext support was implemented with the assumption that you'd use an application-specific directory with only your languages, but it should be able to work in shared directories by skipping ones where the expected file is missing. 
OK. I can create a PR with that patch then.


Resolving patch:
diff --git a/tornado/locale.py b/tornado/locale.py
--- a/tornado/locale.py
+++ b/tornado/locale.py
@@ -41,6 +41,7 @@
 import csv
 import datetime
 import gettext
+import glob
 import os
 import re
 
@@ -198,13 +199,12 @@ def load_gettext_translations(directory: str, domain: str) -> None:
     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
+
+    for filename in glob.glob(
+        os.path.join(directory, "*", "LC_MESSAGES", domain + ".mo")
+    ):
+        lang = os.path.basename(os.path.dirname(os.path.dirname(filename)))
         try:
-            os.stat(os.path.join(directory, lang, "LC_MESSAGES", domain + ".mo"))
             _translations[lang] = gettext.translation(
                 domain, directory, languages=[lang]
             )


Test patch: