Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notifications: remove extra indentation and trailing newlines #10987

Closed
humitos opened this issue Jan 3, 2024 · 8 comments
Closed

Notifications: remove extra indentation and trailing newlines #10987

humitos opened this issue Jan 3, 2024 · 8 comments
Assignees
Labels
Accepted Accepted issue on our roadmap Improvement Minor improvement to code

Comments

@humitos
Copy link
Member

humitos commented Jan 3, 2024

I've found myself wanting to write the copy for all the messages in a simple way that avoid indentation and punctuation mistakes and I'm happy with the result so far. However, the downsides they have is they return they messages as \n \n Please try... (note the \n and the extra spaces).

I'd like to remove those automatically somehow without changing the way we write down the copy for these messages if possible.

We discussed this a little at #10922 (comment) where I exposed what I ideally want.

Example in the code:

body=_(
"""
There was a problem with Read the Docs while building your documentation.
Please try again later.
If this problem persists,
report this error to us with your build id ({instance.pk}).
"""
),

@stsewd
Copy link
Member

stsewd commented Jan 3, 2024

You can use textwrap.dedent + string.strip.

import textwrap

s = textwrap.dedent(
    """
    Foo

    bar
    """
).strip()

@humitos
Copy link
Member Author

humitos commented Jan 3, 2024

That works great!

However, it seems that textwrap.dedent does not support a translated string? Weird.

build_1        |   File "/usr/src/app/checkouts/readthedocs.org/readthedocs/core/admin.py", line 17, in <module>
build_1        |     from readthedocs.oauth.tasks import sync_remote_repositories
build_1        |   File "/usr/src/app/checkouts/readthedocs.org/readthedocs/oauth/tasks.py", line 15, in <module>
build_1        |     from readthedocs.oauth.notifications import (
build_1        |   File "/usr/src/app/checkouts/readthedocs.org/readthedocs/oauth/notifications.py", line 16, in <module>
build_1        |     Message(
build_1        |   File "/usr/src/app/checkouts/readthedocs.org/readthedocs/notifications/messages.py", line 20, in __init__
build_1        |     self.header = textwrap.dedent(header).strip()
build_1        |   File "/usr/lib/python3.10/textwrap.py", line 438, in dedent
build_1        |     text = _whitespace_only_re.sub('', text)
build_1        | TypeError: expected string or bytes-like object

@agjohnson
Copy link
Contributor

+1 on dedent here

It looks like you are effectively doing textwrap.dedent(_("...")) though

To both make the source easy to work with and also solve the issue of the translations including extraneous whitespace, you probably need _(textwrap.dedent("...")).

@agjohnson agjohnson added Improvement Minor improvement to code Accepted Accepted issue on our roadmap labels Jan 3, 2024
@agjohnson
Copy link
Contributor

Noted at #10922 (comment)

However, it might be best to avoid altering our translation files until these strings are resolved. I don't quite know how gettext handles moved strings vs moved and altered strings, but I suspect the additional whitespace could throw off all the existing translations.

I'll add this to this sprint, as I'd like to help translators as much we can here. I don't really know if it matters though. Moving the string is probably already a somewhat breaking change.

@humitos
Copy link
Member Author

humitos commented Jan 4, 2024

It looks like you are effectively doing textwrap.dedent(_("...")) though
To both make the source easy to work with and also solve the issue of the translations including extraneous whitespace, you probably need _(textwrap.dedent("...")).

Yes, I tried doing the first approach because doing _(textwrap.dedent()) means doing it in all the strings instead of just once. However, it seems the shortcut I want to follow is not possible here and I will need to re-write all the strings 😞

humitos added a commit that referenced this issue Jan 4, 2024
@humitos humitos closed this as completed in e778db5 Jan 4, 2024
@agjohnson
Copy link
Contributor

Yeah, I figured we'd have to do something like this, unfortunately. Multiline strings are always a pain.

I do believe there is magic you can do with gettext and creating your own gettext wrappers, but this is almost certainly way too deep.

@humitos
Copy link
Member Author

humitos commented Jan 4, 2024

I don't know exactly how gettext works internally, but I assumed that if I do _(textwrap.dedent(header).strip()) inside the initializer at

the translation string won't get identified by gettext and exposed to be translated. If that works, we can write this only once, but I'm not sure how to test it.

@humitos
Copy link
Member Author

humitos commented Jan 4, 2024

I understand that we can't translate variables in a simple way:

(The caveat with using variables or computed values, as in the previous two examples, is that Django’s translation-string-detecting utility, django-admin makemessages, won’t be able to find these strings. More on makemessages later.)

(from https://docs.djangoproject.com/en/5.0/topics/i18n/translation/#standard-translation)

I think what I've done here is the way to go, unfortunately 😞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Accepted Accepted issue on our roadmap Improvement Minor improvement to code
Projects
Archived in project
Development

No branches or pull requests

3 participants