We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Set direction on placeables
*This issue was created automatically by a [script](https://github.com/mathjazz/bugzilla2github/).*
## [Bug 1692620](https://bugzilla.mozilla.org/show_bug.cgi?id=1692620)
Bug Reporter: @mathjazz

Created attachment 9202997
Screenshot

Everywhere we mark up placeables (i.e. everywhere we show strings in the translate view except in the textarea), we need to set the `dir` attribute to `ltr` in order to prevent bad display of placeables in RTL strings (as seen on the screenshot).
Pontoon picks the wrong folder format for locales (underscore instead of hyphens)
*This issue was created automatically by a [script](https://github.com/mathjazz/bugzilla2github/).*
## [Bug 1698636](https://bugzilla.mozilla.org/show_bug.cgi?id=1698636)
Bug Reporter: @flodolo
CC:   @mathjazz

I created the repository with the source in `en-US` folder.
https://github.com/mozilla-l10n/mozilla-vpn-website-l10n/

Pontoon then synced `pt-BR` as `pt_BR`. One possible explanation is the presence of a file with underscores (`CODE_OF_CONDUCT.md`) in the repository. If that's the case, it's a bug, because we really care about folders, not files.

I then renamed `pt_BR` to use hyphens, synced translations for `en-CA` and it still used the wrong format (`en_CA`). Fixed this one too, synced a string for `en-GB`,  and again wrong format.

At this point, I don't know if it will keep using _ for the next locales.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pontoon/sync/utils.py`
Content:
```
1 import errno
2 import os
3 
4 from pontoon.base.models import Resource
5 from pontoon.base.utils import extension_in, first
6 
7 
8 def is_hidden(path):
9     """
10     Return true if path contains hidden directory.
11     """
12     for p in path.split(os.sep):
13         if p.startswith("."):
14             return True
15     return False
16 
17 
18 def is_resource(filename):
19     """
20     Return True if the filename's extension is a supported Resource
21     format.
22     """
23     return extension_in(filename, Resource.ALLOWED_EXTENSIONS)
24 
25 
26 def is_source_resource(filename):
27     """
28     Return True if the filename's extension is a source-only Resource
29     format.
30     """
31     return extension_in(filename, Resource.SOURCE_EXTENSIONS)
32 
33 
34 def is_asymmetric_resource(filename):
35     """
36     Return True if the filename's extension is an asymmetric Resource
37     format.
38     """
39     return extension_in(filename, Resource.ASYMMETRIC_FORMATS)
40 
41 
42 def get_parent_directory(path):
43     """
44     Get parent directory of the path
45     """
46     return os.path.abspath(os.path.join(path, os.pardir))
47 
48 
49 def uses_undercore_as_separator(directory):
50     """
51     Return True if any subdirectory contains underscore.
52     """
53     subdirs = os.listdir(directory)
54     return "".join(subdirs).count("_") > "".join(subdirs).count("-")
55 
56 
57 def directory_contains_resources(directory_path, source_only=False):
58     """
59     Return True if the given directory contains at least one
60     supported resource file (checked via file extension), or False
61     otherwise.
62 
63     :param source_only:
64         If True, only check for source-only formats.
65     """
66     resource_check = is_source_resource if source_only else is_resource
67     for root, dirnames, filenames in os.walk(directory_path):
68         # first() avoids checking past the first matching resource.
69         if first(filenames, resource_check) is not None:
70             return True
71     return False
72 
73 
74 def locale_directory_path(checkout_path, locale_code, parent_directories=None):
75     """
76     Path to the directory where strings for the given locale are
77     stored.
78     """
79     possible_paths = []
80 
81     # Check paths that use underscore as locale/country code separator
82     locale_code_variants = [locale_code, locale_code.replace("-", "_")]
83 
84     # Optimization for directories with a lot of paths: if parent_directories
85     # is provided, we simply join it with locale_code and check if path exists
86     for parent_directory in parent_directories:
87         for locale in locale_code_variants:
88             candidate = os.path.join(parent_directory, locale)
89             if os.path.exists(candidate):
90                 possible_paths.append(candidate)
91 
92     if not possible_paths:
93         for root, dirnames, filenames in os.walk(checkout_path):
94             for locale in locale_code_variants:
95                 if locale in dirnames:
96                     possible_paths.append(os.path.join(root, locale))
97 
98     for possible_path in possible_paths:
99         if directory_contains_resources(possible_path):
100             return possible_path
101 
102     # If locale directory empty (asymmetric formats)
103     if possible_paths:
104         return possible_paths[0]
105 
106     raise OSError("Directory for locale `{}` not found".format(locale_code or "source"))
107 
108 
109 def locale_to_source_path(path):
110     """
111     Return source resource path for the given locale resource path.
112     Source files for .po files are actually .pot.
113     """
114     if path.endswith("po"):
115         path += "t"
116     return path
117 
118 
119 def source_to_locale_path(path):
120     """
121     Return locale resource path for the given source resource path.
122     Locale files for .pot files are actually .po.
123     """
124     if path.endswith("pot"):
125         path = path[:-1]
126     return path
127 
128 
129 def escape_quotes(value):
130     """
131     DTD files can use single or double quotes for identifying strings,
132     so &quot; and &apos; are the safe bet that will work in both cases.
133     """
134     value = value.replace('"', "\\&quot;")
135     value = value.replace("'", "\\&apos;")
136 
137     return value
138 
139 
140 def unescape_quotes(value):
141     value = value.replace("\\&quot;", '"')
142     value = value.replace("\\u0022", '"')  # Bug 1390111
143     value = value.replace('\\"', '"')
144 
145     value = value.replace("\\&apos;", "'")
146     value = value.replace("\\u0027", "'")  # Bug 1390111
147     value = value.replace("\\'", "'")
148 
149     return value
150 
151 
152 def create_parent_directory(path):
153     """
154     Create parent directory of the given path if it doesn't exist yet.
155     """
156     try:
157         os.makedirs(os.path.dirname(path))
158     except OSError as e:
159         # Directory already exists
160         if e.errno == errno.EEXIST:
161             pass
162         else:
163             raise
164
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pontoon/sync/utils.py b/pontoon/sync/utils.py
--- a/pontoon/sync/utils.py
+++ b/pontoon/sync/utils.py
@@ -48,10 +48,16 @@
 
 def uses_undercore_as_separator(directory):
     """
-    Return True if any subdirectory contains underscore.
+    Return True if the names of folders in a directory contain more '_' than '-'.
     """
+    only_folders = []
     subdirs = os.listdir(directory)
-    return "".join(subdirs).count("_") > "".join(subdirs).count("-")
+
+    for i in subdirs:
+        if os.path.isdir(os.path.join(directory, i)):
+            only_folders.append(i)
+
+    return "".join(only_folders).count("_") > "".join(only_folders).count("-")
 
 
 def directory_contains_resources(directory_path, source_only=False):

{"golden_diff": "diff --git a/pontoon/sync/utils.py b/pontoon/sync/utils.py\n--- a/pontoon/sync/utils.py\n+++ b/pontoon/sync/utils.py\n@@ -48,10 +48,16 @@\n \n def uses_undercore_as_separator(directory):\n     \"\"\"\n-    Return True if any subdirectory contains underscore.\n+    Return True if the names of folders in a directory contain more '_' than '-'.\n     \"\"\"\n+    only_folders = []\n     subdirs = os.listdir(directory)\n-    return \"\".join(subdirs).count(\"_\") > \"\".join(subdirs).count(\"-\")\n+\n+    for i in subdirs:\n+        if os.path.isdir(os.path.join(directory, i)):\n+            only_folders.append(i)\n+\n+    return \"\".join(only_folders).count(\"_\") > \"\".join(only_folders).count(\"-\")\n \n \n def directory_contains_resources(directory_path, source_only=False):\n", "issue": "Set direction on placeables\n*This issue was created automatically by a [script](https://github.com/mathjazz/bugzilla2github/).*\r\n## [Bug 1692620](https://bugzilla.mozilla.org/show_bug.cgi?id=1692620)\r\nBug Reporter: @mathjazz\r\n\r\nCreated attachment 9202997\r\nScreenshot\r\n\r\nEverywhere we mark up placeables (i.e. everywhere we show strings in the translate view except in the textarea), we need to set the `dir` attribute to `ltr` in order to prevent bad display of placeables in RTL strings (as seen on the screenshot).\nPontoon picks the wrong folder format for locales (underscore instead of hyphens)\n*This issue was created automatically by a [script](https://github.com/mathjazz/bugzilla2github/).*\n## [Bug 1698636](https://bugzilla.mozilla.org/show_bug.cgi?id=1698636)\nBug Reporter: @flodolo\nCC:   @mathjazz\n\nI created the repository with the source in `en-US` folder.\nhttps://github.com/mozilla-l10n/mozilla-vpn-website-l10n/\n\nPontoon then synced `pt-BR` as `pt_BR`. One possible explanation is the presence of a file with underscores (`CODE_OF_CONDUCT.md`) in the repository. If that's the case, it's a bug, because we really care about folders, not files.\n\nI then renamed `pt_BR` to use hyphens, synced translations for `en-CA` and it still used the wrong format (`en_CA`). Fixed this one too, synced a string for `en-GB`,  and again wrong format.\n\nAt this point, I don't know if it will keep using _ for the next locales.\n", "before_files": [{"content": "import errno\nimport os\n\nfrom pontoon.base.models import Resource\nfrom pontoon.base.utils import extension_in, first\n\n\ndef is_hidden(path):\n    \"\"\"\n    Return true if path contains hidden directory.\n    \"\"\"\n    for p in path.split(os.sep):\n        if p.startswith(\".\"):\n            return True\n    return False\n\n\ndef is_resource(filename):\n    \"\"\"\n    Return True if the filename's extension is a supported Resource\n    format.\n    \"\"\"\n    return extension_in(filename, Resource.ALLOWED_EXTENSIONS)\n\n\ndef is_source_resource(filename):\n    \"\"\"\n    Return True if the filename's extension is a source-only Resource\n    format.\n    \"\"\"\n    return extension_in(filename, Resource.SOURCE_EXTENSIONS)\n\n\ndef is_asymmetric_resource(filename):\n    \"\"\"\n    Return True if the filename's extension is an asymmetric Resource\n    format.\n    \"\"\"\n    return extension_in(filename, Resource.ASYMMETRIC_FORMATS)\n\n\ndef get_parent_directory(path):\n    \"\"\"\n    Get parent directory of the path\n    \"\"\"\n    return os.path.abspath(os.path.join(path, os.pardir))\n\n\ndef uses_undercore_as_separator(directory):\n    \"\"\"\n    Return True if any subdirectory contains underscore.\n    \"\"\"\n    subdirs = os.listdir(directory)\n    return \"\".join(subdirs).count(\"_\") > \"\".join(subdirs).count(\"-\")\n\n\ndef directory_contains_resources(directory_path, source_only=False):\n    \"\"\"\n    Return True if the given directory contains at least one\n    supported resource file (checked via file extension), or False\n    otherwise.\n\n    :param source_only:\n        If True, only check for source-only formats.\n    \"\"\"\n    resource_check = is_source_resource if source_only else is_resource\n    for root, dirnames, filenames in os.walk(directory_path):\n        # first() avoids checking past the first matching resource.\n        if first(filenames, resource_check) is not None:\n            return True\n    return False\n\n\ndef locale_directory_path(checkout_path, locale_code, parent_directories=None):\n    \"\"\"\n    Path to the directory where strings for the given locale are\n    stored.\n    \"\"\"\n    possible_paths = []\n\n    # Check paths that use underscore as locale/country code separator\n    locale_code_variants = [locale_code, locale_code.replace(\"-\", \"_\")]\n\n    # Optimization for directories with a lot of paths: if parent_directories\n    # is provided, we simply join it with locale_code and check if path exists\n    for parent_directory in parent_directories:\n        for locale in locale_code_variants:\n            candidate = os.path.join(parent_directory, locale)\n            if os.path.exists(candidate):\n                possible_paths.append(candidate)\n\n    if not possible_paths:\n        for root, dirnames, filenames in os.walk(checkout_path):\n            for locale in locale_code_variants:\n                if locale in dirnames:\n                    possible_paths.append(os.path.join(root, locale))\n\n    for possible_path in possible_paths:\n        if directory_contains_resources(possible_path):\n            return possible_path\n\n    # If locale directory empty (asymmetric formats)\n    if possible_paths:\n        return possible_paths[0]\n\n    raise OSError(\"Directory for locale `{}` not found\".format(locale_code or \"source\"))\n\n\ndef locale_to_source_path(path):\n    \"\"\"\n    Return source resource path for the given locale resource path.\n    Source files for .po files are actually .pot.\n    \"\"\"\n    if path.endswith(\"po\"):\n        path += \"t\"\n    return path\n\n\ndef source_to_locale_path(path):\n    \"\"\"\n    Return locale resource path for the given source resource path.\n    Locale files for .pot files are actually .po.\n    \"\"\"\n    if path.endswith(\"pot\"):\n        path = path[:-1]\n    return path\n\n\ndef escape_quotes(value):\n    \"\"\"\n    DTD files can use single or double quotes for identifying strings,\n    so &quot; and &apos; are the safe bet that will work in both cases.\n    \"\"\"\n    value = value.replace('\"', \"\\\\&quot;\")\n    value = value.replace(\"'\", \"\\\\&apos;\")\n\n    return value\n\n\ndef unescape_quotes(value):\n    value = value.replace(\"\\\\&quot;\", '\"')\n    value = value.replace(\"\\\\u0022\", '\"')  # Bug 1390111\n    value = value.replace('\\\\\"', '\"')\n\n    value = value.replace(\"\\\\&apos;\", \"'\")\n    value = value.replace(\"\\\\u0027\", \"'\")  # Bug 1390111\n    value = value.replace(\"\\\\'\", \"'\")\n\n    return value\n\n\ndef create_parent_directory(path):\n    \"\"\"\n    Create parent directory of the given path if it doesn't exist yet.\n    \"\"\"\n    try:\n        os.makedirs(os.path.dirname(path))\n    except OSError as e:\n        # Directory already exists\n        if e.errno == errno.EEXIST:\n            pass\n        else:\n            raise\n", "path": "pontoon/sync/utils.py"}], "after_files": [{"content": "import errno\nimport os\n\nfrom pontoon.base.models import Resource\nfrom pontoon.base.utils import extension_in, first\n\n\ndef is_hidden(path):\n    \"\"\"\n    Return true if path contains hidden directory.\n    \"\"\"\n    for p in path.split(os.sep):\n        if p.startswith(\".\"):\n            return True\n    return False\n\n\ndef is_resource(filename):\n    \"\"\"\n    Return True if the filename's extension is a supported Resource\n    format.\n    \"\"\"\n    return extension_in(filename, Resource.ALLOWED_EXTENSIONS)\n\n\ndef is_source_resource(filename):\n    \"\"\"\n    Return True if the filename's extension is a source-only Resource\n    format.\n    \"\"\"\n    return extension_in(filename, Resource.SOURCE_EXTENSIONS)\n\n\ndef is_asymmetric_resource(filename):\n    \"\"\"\n    Return True if the filename's extension is an asymmetric Resource\n    format.\n    \"\"\"\n    return extension_in(filename, Resource.ASYMMETRIC_FORMATS)\n\n\ndef get_parent_directory(path):\n    \"\"\"\n    Get parent directory of the path\n    \"\"\"\n    return os.path.abspath(os.path.join(path, os.pardir))\n\n\ndef uses_undercore_as_separator(directory):\n    \"\"\"\n    Return True if the names of folders in a directory contain more '_' than '-'.\n    \"\"\"\n    only_folders = []\n    subdirs = os.listdir(directory)\n\n    for i in subdirs:\n        if os.path.isdir(os.path.join(directory, i)):\n            only_folders.append(i)\n\n    return \"\".join(only_folders).count(\"_\") > \"\".join(only_folders).count(\"-\")\n\n\ndef directory_contains_resources(directory_path, source_only=False):\n    \"\"\"\n    Return True if the given directory contains at least one\n    supported resource file (checked via file extension), or False\n    otherwise.\n\n    :param source_only:\n        If True, only check for source-only formats.\n    \"\"\"\n    resource_check = is_source_resource if source_only else is_resource\n    for root, dirnames, filenames in os.walk(directory_path):\n        # first() avoids checking past the first matching resource.\n        if first(filenames, resource_check) is not None:\n            return True\n    return False\n\n\ndef locale_directory_path(checkout_path, locale_code, parent_directories=None):\n    \"\"\"\n    Path to the directory where strings for the given locale are\n    stored.\n    \"\"\"\n    possible_paths = []\n\n    # Check paths that use underscore as locale/country code separator\n    locale_code_variants = [locale_code, locale_code.replace(\"-\", \"_\")]\n\n    # Optimization for directories with a lot of paths: if parent_directories\n    # is provided, we simply join it with locale_code and check if path exists\n    for parent_directory in parent_directories:\n        for locale in locale_code_variants:\n            candidate = os.path.join(parent_directory, locale)\n            if os.path.exists(candidate):\n                possible_paths.append(candidate)\n\n    if not possible_paths:\n        for root, dirnames, filenames in os.walk(checkout_path):\n            for locale in locale_code_variants:\n                if locale in dirnames:\n                    possible_paths.append(os.path.join(root, locale))\n\n    for possible_path in possible_paths:\n        if directory_contains_resources(possible_path):\n            return possible_path\n\n    # If locale directory empty (asymmetric formats)\n    if possible_paths:\n        return possible_paths[0]\n\n    raise OSError(\"Directory for locale `{}` not found\".format(locale_code or \"source\"))\n\n\ndef locale_to_source_path(path):\n    \"\"\"\n    Return source resource path for the given locale resource path.\n    Source files for .po files are actually .pot.\n    \"\"\"\n    if path.endswith(\"po\"):\n        path += \"t\"\n    return path\n\n\ndef source_to_locale_path(path):\n    \"\"\"\n    Return locale resource path for the given source resource path.\n    Locale files for .pot files are actually .po.\n    \"\"\"\n    if path.endswith(\"pot\"):\n        path = path[:-1]\n    return path\n\n\ndef escape_quotes(value):\n    \"\"\"\n    DTD files can use single or double quotes for identifying strings,\n    so &quot; and &apos; are the safe bet that will work in both cases.\n    \"\"\"\n    value = value.replace('\"', \"\\\\&quot;\")\n    value = value.replace(\"'\", \"\\\\&apos;\")\n\n    return value\n\n\ndef unescape_quotes(value):\n    value = value.replace(\"\\\\&quot;\", '\"')\n    value = value.replace(\"\\\\u0022\", '\"')  # Bug 1390111\n    value = value.replace('\\\\\"', '\"')\n\n    value = value.replace(\"\\\\&apos;\", \"'\")\n    value = value.replace(\"\\\\u0027\", \"'\")  # Bug 1390111\n    value = value.replace(\"\\\\'\", \"'\")\n\n    return value\n\n\ndef create_parent_directory(path):\n    \"\"\"\n    Create parent directory of the given path if it doesn't exist yet.\n    \"\"\"\n    try:\n        os.makedirs(os.path.dirname(path))\n    except OSError as e:\n        # Directory already exists\n        if e.errno == errno.EEXIST:\n            pass\n        else:\n            raise\n", "path": "pontoon/sync/utils.py"}]}