Use ngettext for strings with count
Proposed Changes
netbox/dcim/views.py has _("Disconnected {count} {type}") where count is as far as I can tell an arbitrary number and type a pre-baked plural. This cannot be properly translated in some languages, because plurals don’t work the same way as they do in English.
You need to:
- use
ngettextfor the count part, so plural forms can be handled properly. - use one full string per type, because that’s the only way nouns can be declined as necessary.
This would result in something along the lines of
…
ngettext("Disconnected 1 device", "Disconnected {count} devices", count)
…
ngettext("Disconnected 1 client", "Disconnected {count} clients", count)
…
with something like a switch-case to match a given type with a given ngettext call.
Sorry for using client and device instead of actual types, I couldn’t easily find the type list.
Justification
You shouldn’t make up your own plural handling. There are tools for that, and good reasons to use them.
See #16659 for a similar but different situation.
I only mentioned one string because it’s the one I could find, but there may be other ones that are affected by this issue.
And of course right after I post that comment, I find more:
netbox/virtualization/models/clusters.pyhas"{count} devices are assigned as hosts for this cluster but are not in site {site}"netbox/utilities/error_handlers.pyhas"Unable to delete <strong>{objects}</strong>. {count} dependent objects were found: "netbox/utilities/forms/utils.pyhas"Row {row}: Expected {count_expected} columns but found {count_found}"netbox/dcim/models/device_component_templates.pyhas"Invalid rear port position ({position}); rear port {name} has only {count} positions"
I may still be missing some more.
@afranke thanks for bringing this to our attention. Would you be willing to contribute a PR to make the proposed changes?
I’m sorry but I won’t be able to. I can review a PR to check if it’s doing the right thing from an i18n perspective though.
Could you please assign it to me?
@afranke In this case In netbox/dcim/views.py if we used the line:
messages.success(request, _(ngettext(
"Disconnected 1 {type}",
"Disconnected {count} {type_plural}",
count,
)).format(
count=count,
type=self.queryset.model._meta.verbose_name,
type_plural=self.queryset.model._meta.verbose_name_plural
))
Would that work for pluralization as you mentioned for Polish? We just have the singular and pluralized model name.
No, it wouldn’t work. See point 2 in the issue description.
Putting this back in the backlog - more research needs to be done on a viable solution as it's probably not viable to create a separate string per type there.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. Do not attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our contributing guide.
This issue has been automatically closed due to lack of activity. In an effort to reduce noise, please do not comment any further. Note that the core maintainers may elect to reopen this issue at a later date if deemed necessary.
Let me try one more time, and add a bit more context. First of all, I am neither a user nor a translator for your software. I am a free software translator, both as a volunteer and professionally, with twenty years of experience, including as an internationalisation coordinator for GNOME. A friend of mine uses your software and told me about it. Out of curiosity, I looked into the quality of your translations, because that’s something I do: sharing my expertise with smaller projects who aren’t lucky enough to have someone with the necessary knowledge, in order to improve the commons. That is not to say that you should blindly trust me, but hopefully it helps you understand where I’m coming from and indeed trust me a bit more.
Putting this back in the backlog - more research needs to be done on a viable solution as it's probably not viable to create a separate string per type there.
But it is the one correct way to do this. You shouldn’t be worried about adding a dozen more strings (which is peanuts compared to the 3k+ strings you already have). You should be worried about doing things correctly so translators can effectively do their work.