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``. Th
(directory: str, encoding: Optional[str] = None)
| 88 | |
| 89 | |
| 90 | def load_translations(directory: str, encoding: Optional[str] = None) -> None: |
| 91 | """Loads translations from CSV files in a directory. |
| 92 | |
| 93 | Translations are strings with optional Python-style named placeholders |
| 94 | (e.g., ``My name is %(name)s``) and their associated translations. |
| 95 | |
| 96 | The directory should have translation files of the form ``LOCALE.csv``, |
| 97 | e.g. ``es_GT.csv``. The CSV files should have two or three columns: string, |
| 98 | translation, and an optional plural indicator. Plural indicators should |
| 99 | be one of "plural" or "singular". A given string can have both singular |
| 100 | and plural forms. For example ``%(name)s liked this`` may have a |
| 101 | different verb conjugation depending on whether %(name)s is one |
| 102 | name or a list of names. There should be two rows in the CSV file for |
| 103 | that string, one with plural indicator "singular", and one "plural". |
| 104 | For strings with no verbs that would change on translation, simply |
| 105 | use "unknown" or the empty string (or don't include the column at all). |
| 106 | |
| 107 | The file is read using the `csv` module in the default "excel" dialect. |
| 108 | In this format there should not be spaces after the commas. |
| 109 | |
| 110 | If no ``encoding`` parameter is given, the encoding will be |
| 111 | detected automatically (among UTF-8 and UTF-16) if the file |
| 112 | contains a byte-order marker (BOM), defaulting to UTF-8 if no BOM |
| 113 | is present. |
| 114 | |
| 115 | Example translation ``es_LA.csv``:: |
| 116 | |
| 117 | "I love you","Te amo" |
| 118 | "%(name)s liked this","A %(name)s les gustó esto","plural" |
| 119 | "%(name)s liked this","A %(name)s le gustó esto","singular" |
| 120 | |
| 121 | .. versionchanged:: 4.3 |
| 122 | Added ``encoding`` parameter. Added support for BOM-based encoding |
| 123 | detection, UTF-16, and UTF-8-with-BOM. |
| 124 | """ |
| 125 | global _translations |
| 126 | global _supported_locales |
| 127 | _translations = {} |
| 128 | for path in os.listdir(directory): |
| 129 | if not path.endswith(".csv"): |
| 130 | continue |
| 131 | locale, extension = path.split(".") |
| 132 | if not re.match("[a-z]+(_[A-Z]+)?$", locale): |
| 133 | gen_log.error( |
| 134 | "Unrecognized locale %r (path: %s)", |
| 135 | locale, |
| 136 | os.path.join(directory, path), |
| 137 | ) |
| 138 | continue |
| 139 | full_path = os.path.join(directory, path) |
| 140 | if encoding is None: |
| 141 | # Try to autodetect encoding based on the BOM. |
| 142 | with open(full_path, "rb") as bf: |
| 143 | data = bf.read(len(codecs.BOM_UTF16_LE)) |
| 144 | if data in (codecs.BOM_UTF16_LE, codecs.BOM_UTF16_BE): |
| 145 | encoding = "utf-16" |
| 146 | else: |
| 147 | # utf-8-sig is "utf-8 with optional BOM". It's discouraged |