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

16.0 - How to translate code terms without affecting the original source file? #165036

Closed
moylop260 opened this issue May 9, 2024 · 3 comments
Closed

Comments

@moylop260
Copy link
Contributor

moylop260 commented May 9, 2024

Impacted versions:

16.0

Steps to reproduce:

Old odoo versions you were able to translate core modules and add translations from custom modules without affecting the core module

I mean, if the original code term is Wrong login/password and you change to "Error usuario/contraseña" but both customer request to translate a little differently you could use a file customer/i18n_extra/es.po and here translate a core module term

Now, it is not possible since the translation is extracted only from the original module

So, you need to change the source but what about if 2 customers do not agree with the value translated

Customer 1 want translate: "Error en tu email/contraseña"
Customer 2 want translate: "Error en tu usuario y/o clave"

Current behavior:

What is the best solution to afford this?

Considering, sometimes we need custom translations for the context of different customers

Even if it is only a basic example because there are more cases in-depth where we had a module with custom translations for this customer that after migrating is not possible to install and see the terms in their context

Should we change our policy to "don't touch the original core source" and translate directly into the core module?

If yes, what about fixing conflicts each time you get updated code from the repositories with new terms translated differently each time?

If not, How are you fixing this case?

Also, defining 2 different processes to translate terms one for code terms and another one for everything else looks good for you?

@ossimantylahti
Copy link
Contributor

@moylop260 Odoo has a built-in feature that will automatically update all Odoo core modules -- translations included. Therefore, you cannot really create your own customised translations and overwrite Odoo's own translation files with those. You should also be aware that Odoo regularly adds new strings to the modules, so your own translation files would start eventually to be really lagging from them.

Your best bet would be to create your own 3rd party module that inherits Odoo's models and overwrites them with your own functionality -- or in this case field names and their translations.

@vava-odoo vava-odoo closed this as not planned Won't fix, can't repro, duplicate, stale May 17, 2024
@moylop260
Copy link
Contributor Author

moylop260 commented May 21, 2024

FYI I followed your advice

e.g. to translate the password message I have created a new module called dummy_i18n

With the following code:

from odoo import http

from odoo.addons.web.controllers.home import Home


class WebHome(Home):
    @http.route("/web/login", type="http", auth="none")
    def web_login(self, redirect=None, **kw):
        res = super().web_login(redirect, **kw)
        if res.qcontext.get("error") == "Wrong login/password":
            res.qcontext["error"] = "Incorrect username or password"
        return res

Another one is to translate the part of the attempts to login:

import contextlib

from odoo import _, models
from odoo.exceptions import AccessDenied, UserError


class ResUsers(models.Model):
    _inherit = "res.users"

    @contextlib.contextmanager
    def _assert_can_auth(self, user=None):
        try:
            with super()._assert_can_auth(user) as res:
                yield res
        except AccessDenied as e:
            if e.name == "Too many login failures, please wait a bit before trying again.":
                cfg = self.env["ir.config_parameter"].sudo()
                min_failures = int(cfg.get_param("base.login_cooldown_after", 5))
                raise AccessDenied(
                    _(
                        "Your account is temporarily locked as a security measure due to %s unsuccessful login attempts."
                        " Please allow 1 minute to pass before trying to login again.",
                        min_failures,
                    )
                )
            raise

Another one to translate the password:

   def _check_password_history(self, password):
        for user in self:
            try:
                res = super()._check_password_history(password)
                return res
            except UserError as e:
                if e.name == "Cannot use the most recent %d passwords" % user.company_id.password_history:
                    raise UserError(_("Please enter a new password, your most recent password cannot be reused"))
                raise

Well, Notice the last one has an issue, my translation team generated by mistake (because of uses self for the super but it needs to use the user variable because the message contains a value custom of the user)

Notice the other ones need a decorator and so on

It looks like an innocent change without logical change but even it could break the logic only to translate a term

Is this the right way to deal with this problem or did I misunderstand?

Your answer will be our guideline so I appreciate your answer here since that it for me is not a good choice

@ossimantylahti
Copy link
Contributor

ossimantylahti commented May 21, 2024

@moylop260 This is perhaps not the right place to have this discussion, and I'd need to see the whole code in order to dig deeper. But a couple of notes since this could be of public interest.

  1. In order to make an Odoo or your own moduld string translatable is to preceed it with underscore. So instead of raise AccessDenied ("Foobar"), you should write raise AccessDenied (_("Foobar")). And you have done that.
  2. In your code you are comparing values against whole error message text. I do not think this is a good idea. Example:
    if e.name == "Too many login failures, please wait a bit before trying again.":
    And this probably won't work at all:
    if e.name == "Cannot use the most recent %d passwords" % user.company_id.password_history:
  3. I am not sure if Odoo automatically translates http traffic to https traffic. If not, this code block has a problem.
    @http.route("/web/login", type="http", auth="none")
  4. And on the same code block, please note that the user is not authenticated. Thus Odoo does not know his language preferences and would default to system or site default language. Maybe that is the reason your translations do not seem to be working?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants