Improve internationalization
While experimenting with internationalization of a personal project, I encountered two issues:
- I had to translate a bulk of messages coming from click.
- I had to configure gettext globally (or monkey-patch it) before loading click, which introduces many complications. This is discussed by another user, carmenbianca, in #2706.
I was initially thinking of creating a discussion about this, but I wanted to also share an implementation. I am myself inexperienced in translating software, so any criticism is welcome. I will list what I have done and what I am unsure about. Perhaps carmenbianca can chime in?
-
I have added some .po files with translations into Russian and Bulgarian. These are straightforward, but there are subtleties:
- They must be compiled to .mo files. This is an issue because the setup becomes more difficult, especially on Windows where gettext tools must be installed manually. I found no easy way to compile the .po files to .mo files. I have thus committed the .mo files, as well as a compilation script. gettext really is clunky.
- The locale files are under the
clickdomain. Client applications will have to use other gettext domains. I am unaware of best practices here. - In order for flit to package these files, they must be put in the source code directory.
-
I have replaced the calls to gettext with a wrapper that stores a locale internally. This should not be a problem generally, but I want to hear if you have any precautions.
-
I have added some unit tests that unfortunately depend on gettext. Hence, on gettext itself and the .mo files discussed above. Conditionally skipping tests in pytest is fortunately easy enough, if running them in CI (or on Windows) becomes a problem.
@v-- Thanks for this. Unfortunately this is a little out of scope for Click. If you are interested in contributing to docs translations hop on pallets discord, and I can get you setup with the right person. I am rowlando on there. I see what you are going for and click-extra might be interested.
@Rowlando13 I am not attempting to extend the scope, just improve what is already in the scope since #1829
I understand that you might not want to host translation files inside this repository. These can easily get extracted into another package.
Even if this wasn't the case, however, both my comment above and the more verbose discussion in #2706 highlight that the usage of the global gettext and ngettext by click is inconvenient for software using click. That is why I have introduced wrappers for gettext and ngettext that are configurable via set_click_locale. There are other approaches, of course, but the gist is that there is demand among the few people using internationalized click to have this configurable on the level of click.
This configuration is not something that can be done in another package. It must be a part of click, slightly modifying what already exists in the codebase. In fact, if translation files are not part of the codebase, set_click_locale must either be extended with a parameter specifying the location of the translation files, or simply accept a NullTranslations object (the base class of the gettext module). The latter approach is much more flexible.
Anyhow, I would appreciate more concrete comments on translations being configurable at the level of click.
Thank you for working on this. I will need to very carefully review this at some point, since it affects quite a bit of the code and introduces a new pattern that needs to be maintainable later. Additionally, based on experiments for docs translations, I want to manage translations using Weblate, so I'll have to figure out how to set that up for this project. This is unlikely to happen soon, so I just want to set expectations.
@davidism I appreciate your comment. I also just realized that I haven't thanked the team for developing click - it's one of the libraries I have been using consistently over the years.
Now, more to the point. I have no expectations for this pull request myself. As mentioned, the translations can easily be extracted into another package (or implemented differently in a later pull request). This would leave mostly mundane changes that should not induce maintenance overhead (replacing which implementations of gettext and ngettext get used).
@v-- I appreciate your candor. I don't have a super long history with Click so sometimes it is a bit hard to tell where the line for should be with regard to accepting something. Sounds @davidism is going to help you out.