Resolve "Email templates are not translated to zh_CN"
related to MR on JiHu
What does this MR do and why?
This MR is to solve the problem that the mail sent is not localized according to user preference_language
when single recipient.
As for "multiple recipients", "emails with cc/bcc and to
is blank" are sent using the default locale :en
.
mail
in gitlab
Usages of In gitlab, the usage of mail is classified into three types according to the format of to
:
-
:to
is a string type, a single email address -
:to
is an array type -
:to
is blank with:bcc
:to is a string type, a single email address |
:to is an array type |
:to is blank with :bcc
|
|
---|---|---|---|
locale | recipient's preferred language | ::I18n.default_locale | ::I18n.default_locale |
use example | |||
test case | https://gitlab.com/gitlab-jh/jh-team/gitlab/-/blob/upstream-1456-email-templates-translation/spec/mailers/notify_spec.rb#L132 | https://gitlab.com/gitlab-jh/jh-team/gitlab/-/blob/upstream-1456-email-templates-translation/spec/mailers/repository_check_mailer_spec.rb#L17 | https://gitlab.com/gitlab-jh/jh-team/gitlab/-/blob/upstream-1456-email-templates-translation/ee/spec/mailers/license_mailer_spec.rb#L12 |
Problem cause and solution
Problem cause: An around_action render_with_default_locale
in ApplicationMailer
used default locale instead of recipient language preference.
def render_with_default_locale(&block)
Gitlab::I18n.with_default_locale(&block)
end
Solution: Define mail_with_locale
in ApplicationMailer
to set the locale according to the recipient's language preference.Also replace mail
with mail_with_locale
def mail_with_locale(headers = {}, &block)
locale = recipient_locale headers
Gitlab::I18n.with_locale(locale) do
mail(headers, &block)
end
end
def recipient_locale(headers = {})
locale = I18n.locale
locale = preferred_language_by_email headers[:to] if headers[:to].is_a?(String)
locale = preferred_language_by_email headers[:to][0] if headers[:to].is_a?(Array) && headers[:to].length == 1
locale
end
def preferred_language_by_email(email)
email_obj = Email.find_by_email email
email_obj ? User.find(email_obj.user_id)&.preferred_language || I18n.locale : I18n.locale
end
Why
There are some reasons do this:
Our original idea was to override mail
in ApplicationMailer
:
- Why override
mail
: There are about 50 direct calls to mail (excluding spec) in gitlab. It would be very complex and difficult to maintain to set the locale on its caller without overridingmail
- Why override under
ApplicationMailer
: The callers of themail
method are all from theApplicationMailer
class and its subclasses. Overriding themail
method underApplicationMailer
can solve all problems at once
But it is inappropriate for mail
to be rewritten as the base api. So we choose to define mail_with_locale
to achieve a similar effect. Even this adds modification: replace mail
with mail_with_locale
.
How to set up and validate locally
- Login to your GDK
- Go to any project
- Click Issues > any issue
- Add an assignee
- Open /rails/letter_opener
- See the mail about adding an assignee.
MR acceptance checklist
This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.
-
I have evaluated the MR acceptance checklist for this MR.
cc @prajnamas