20 Commits

Author SHA1 Message Date
SomberNight 3afa2fcdf3 locale: gui: show translation completion percentage in language names
In the GUIs, on the language-select screen, show e.g.
  Czech (100%), Danish (13%), Dutch (54%)
instead of
  Czech, Danish, Dutch

- we count the source strings when creating the .pot PO-template file
  and add an "X-Electrum-SourceStringCount" header to it, in the push_locale.py script that uploads the .pot file to crowdin.
  - later, when we run electrum-locale/update.py to download the translations in .po files, these files will also contain the same header.
  - then when the build_locale.sh script compiles those .po files, we can read the header and use it to populate a new "stats.json" file
    that we place in electrum/locale/locale/ and bundle in the all release binaries/distributables.
    - stats.json also includes the number of translated strings for each lang
- at runtime we simply read stats.json and use the values to calculate the percentages
  - a prior implementation did not pre-calc stats.json but did all calculations at runtime (by opening all .mo translations)
    - however that was deemed to slow, hence the build-time pre-calc
      - runtime calc took 40 ms on my laptop, so I guess it could easily take 10x that on an old phone
- just as we have always been very tolerant of any locale files or even the whole locale/ dir missing, we also tolerate stats.json missing
2026-02-21 03:40:09 +00:00
SomberNight 4c597ffb5a follow-up prev: satisfy ban_unicode.py 2026-02-14 10:10:59 +00:00
SomberNight 1fc8804791 locale: don't translate names of languages
note this is just a conceptual change, in practice it is a no-op:
i18n.py global scope is executed much earlier than the language gets set.
see https://github.com/spesmilo/electrum/blob/61a6ab1d95e6faccce45ed008426283430fa99d4/run_electrum#L422
2026-02-14 10:03:03 +00:00
SomberNight 0f1a282316 logging: add "only_once=False" param to logger.info/warning/etc calls
very basic form of opt-in rate-limiting of log spam
2025-07-07 14:26:18 +00:00
SomberNight d16c625019 i18n: syntax-check translations at runtime
We often call str.format() on translated strings.
E.g. `_("time left: {} seconds").format(t1)`
If the translated string has a different format syntax, this can raise at runtime.

This PR adds some runtime checks that try to ensure the source string and the translated string
have a similar format syntax. If the checks fail, `_()` will "reject" the translation by
returning the source string.

fixes https://github.com/spesmilo/electrum/issues/10010
ref https://github.com/spesmilo/electrum/issues/10007#issue-3203378250
2025-07-07 13:54:11 +00:00
SomberNight bbac398d1b i18n: add comment about positional substitution in str.format() 2025-07-06 00:20:11 +00:00
SomberNight df6057bc9f i18n: forbid "English" translations
This adds an additional layer of defense.
Potential attack:
- "English" gets added as a language on the crowdin project
  - (this can only be done by a moderator or the crowdin devs)
- malicious strings get added on crowdin as English translations
- we don't notice and pull the updates into the locale git submodule
- users with the "default" lang option selected who have their OS lang set to English
  - and users with "English" explicitly selected in Electrum
  - would see the malicious strings
2025-05-26 15:31:08 +00:00
SomberNight 7b531a7378 i18n: make "language" field private 2025-05-26 15:30:12 +00:00
SomberNight 3567a4cfb0 mv git submodule electrum-locale from contrib to electrum/locale
- this merges `contrib/deterministic-build/locale` and `electrum/locale`
- it is now once again possible have translations when running from a local git clone
    - which was already possible in the past before crowdin removed their unauthenticated APIs
        - see https://github.com/spesmilo/electrum/issues/9531
    - however, the translations available are the often-old frozen strings from electrum-locale
        - while previously one could just download the latest strings from crowdin
2025-04-14 17:18:30 +00:00
SomberNight 55281295b7 ci: bump flake8 to new version
```
./electrum/commands.py:144:9: F824 `global known_commands` is unused: name is never assigned in scope
        global known_commands
        ^
./electrum/commands.py:1916:9: F824 `global known_commands` is unused: name is never assigned in scope
        global known_commands
        ^
./electrum/gui/qt/main_window.py:2405:13: F824 `nonlocal done` is unused: name is never assigned in scope
            nonlocal done
            ^
./electrum/i18n.py:52:5: F824 `global language` is unused: name is never assigned in scope
    global language
    ^
./electrum/plugin.py:189:9: F824 `global _root_permission_cache` is unused: name is never assigned in scope
        global _root_permission_cache
        ^
5     F824 `global known_commands` is unused: name is never assigned in scope
5

```
2025-04-02 14:56:53 +00:00
SomberNight 0e5a1380ca i18n: simplify language default. only translate string if using GUI. 2024-01-16 17:23:43 +00:00
SomberNight b0b4f39b40 i18n: add "context" param to _(), and use it from qml
fixes https://github.com/spesmilo/electrum/issues/8323

from issue:
> Currently, translatable strings from QML are assigned a `context`
> by `lupdate`, which is then also used by the conversion to `gettext`.
> This `context` must be used when translating such a string. This results in
> strings that are unique to QML to not be translated, due to a missing
> `context` parameter which we do not take into account in electrum.
2023-04-20 14:31:44 +00:00
SomberNight 27ce8ba241 i18n: log initial default language set based on OS locale 2023-04-17 19:56:05 +00:00
SomberNight e3544f260b i18n: log set_language 2023-04-17 18:26:29 +00:00
SomberNight b0e2e89395 i18n: document not to use old-style (%) string formatting 2023-01-10 14:06:29 +00:00
SomberNight 4293d6eca0 kivy: settings: better handling of "default" language 2021-09-15 19:52:40 +02:00
Caio Costa 397e43373f Removes inaccurate "brasilian" language
The option "brasilian" is inaccurate since we brazilians do speak Portuguese.
We don't consider "brasilian" as a language, so I believe this change I've made is a more accurate option for this public.
2021-09-09 22:32:51 -03:00
SomberNight 210ff647fa i18n: don't translate empty string
see #7158

```
$ ./contrib/pull_locale
Found 260 files to translate
Generate template
electrum/gui/qt/installwizard.py:265: warning: Empty msgid.  It is reserved by GNU gettext:
                                               gettext("") returns the header entry with
                                               meta information, not the empty string.
electrum/gui/qt/channels_list.py:49: warning: Empty msgid.  It is reserved by GNU gettext:
                                              gettext("") returns the header entry with
                                              meta information, not the empty string.
```
2021-04-01 03:33:16 +02:00
SomberNight 9a88c13b3d translations: add note that f-strings cannot be translated
and replace current usage
2020-04-11 16:33:45 +02:00
Janus 097ac144d9 file reorganization with top-level module 2018-07-13 14:01:37 +02:00