Repository: zulip/zulip

Issue:
Some messages in JS code don't make it to the list to be translated
I first noticed this with the "You subscribed to stream __stream__" message that appears between messages in a (public) stream/topic at the point where you subscribed. It's not in any `translations.json`, and consequently doesn't make it to Transifex and doesn't get translated.

Looking at the source, the `i18n.t` call continues to the next line, so I suspect that's not a coincidence:
```
$ rg -A1 'You subscribed' static/js/ static/locale/ja/
static/js/message_list.js
360:        return i18n.t("You subscribed to stream __stream__",
361-                      {stream: stream_name});
```

There are a few other messages like that (`git grep 'i18n.t[^)]*$' static/js/`). Some work, like this one (actually this is also busted, in that we end up translating just the first part, but that's a different symptom):
```
$ rg -A1 'Upload would exceed' static/js static/locale/ja/
static/js/compose.js
769:            msg = i18n.t("Upload would exceed your maximum quota."
770-                      + " Consider deleting some previously uploaded files.");

static/locale/ja/LC_MESSAGES/django.po
2437:msgid "Upload would exceed your maximum quota."
2438-msgstr ""
```

But most of them don't. This is a bug somewhere in our makemessages chain -- or if it's hard to make `gettext` find these and we'd rather just not do them, then we should have a linter to prevent them.



Discussion:
Hello @zulip/server-i18n members, this issue was labeled with the **area: i18n** label, so you may want to check it out!

Will check it out. @zulipbot, claim.
Seems like the issue with our `makemessages` regexes.

Resolving patch:
diff --git a/tools/linter_lib/custom_check.py b/tools/linter_lib/custom_check.py
--- a/tools/linter_lib/custom_check.py
+++ b/tools/linter_lib/custom_check.py
@@ -135,6 +135,12 @@ def custom_check_file(fn, identifier, rules, color, skip_rules=None, max_length=
          'description': 'The module blueslip has no function warning, try using blueslip.warn'},
         {'pattern': '[)]{$',
          'description': 'Missing space between ) and {'},
+        {'pattern': 'i18n\.t\([^)]+[^,\{]$',
+         'description': 'i18n string should not be a multiline string'},
+        {'pattern': 'i18n\.t([^)]+?\+.+?)',
+         'description': 'Do not concatenate i18n strings'},
+        {'pattern': 'i18n\.t([^+]+?).+?\+',
+         'description': 'Do not concatenate i18n strings'},
         {'pattern': '["\']json/',
          'description': 'Relative URL for JSON route not supported by i18n'},
         # This rule is constructed with + to avoid triggering on itself
diff --git a/zerver/management/commands/makemessages.py b/zerver/management/commands/makemessages.py
--- a/zerver/management/commands/makemessages.py
+++ b/zerver/management/commands/makemessages.py
@@ -55,9 +55,9 @@
            '{{\s*t "(.*?)"\W*}}',
            "{{\s*t '(.*?)'\W*}}",
            "i18n\.t\('([^\']*?)'\)",
-           "i18n\.t\('(.*?)',.*?[^,]\)",
+           "i18n\.t\('(.*?)',\s*.*?[^,]\)",
            'i18n\.t\("([^\"]*?)"\)',
-           'i18n\.t\("(.*?)",.*?[^,]\)',
+           'i18n\.t\("(.*?)",\s*.*?[^,]\)',
            ]
 
 frontend_compiled_regexes = [re.compile(regex) for regex in regexes]


Test patch: