-
Notifications
You must be signed in to change notification settings - Fork 993
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
Fixes #36575 - Avoid translating labels during startup #9771
base: develop
Are you sure you want to change the base?
Fixes #36575 - Avoid translating labels during startup #9771
Conversation
Issues: #36575 |
814d2b1
to
e902a84
Compare
@ofedoren I've added some TODOs with procs, but I doubt it's valid. Mind having a look? |
app/models/domain.rb
Outdated
@@ -51,7 +51,7 @@ class Domain < ApplicationRecord | |||
|
|||
set_crud_hooks :domain | |||
|
|||
apipie :class, desc: "A class representing #{model_name.human} object" do | |||
apipie :class, desc: "A class representing #{humanize_class_name} object" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized this actually doesn't exist and we need something else to describe the object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, since the class names mostly taken as is for DSL, unless they explicitly renamed, it's okay to leave this untranslated and closer to something that is used within methods/return values. Although, there is a need to review all DSL documentation and make sure it's actually consistent.
Also, this whole string is not being translated...
@@ -33,7 +33,8 @@ module Api::V2::TaxonomiesController | |||
param :ignore_types, Array, N_("List of resources types that will be automatically associated"), :required => false | |||
resource_name = (param_name == :location) ? 'organization' : 'location' | |||
resource_ids = "#{resource_name}_ids".to_sym | |||
param resource_ids, Array, N_("Associated %{resource} IDs") % { resource: _(resource_name) }, :required => false | |||
# TODO: translate resource_name? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm dumb for writing _(resource_name)
instead of simply translating taxonomy names. Although, due to some language specialties, this would seems odd in the end anyway.
In this case, I'd better be more explicit or WET:
# ...
mapping = { location: ['organization', N_("Associated organization IDs")], organization: ['location', N_("Associated location IDs")] }
resource_ids = "#{mapping[param_name]&.at(0)}_ids".to_sym # & is just to be sure it doesn't crash, but can be omitted I guess
# ...
param resource_ids, Array, mapping[param_name]&.at(1), :required => false # & is for the same reason, can be changed to [1]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll expand it then.
app/models/domain.rb
Outdated
@@ -51,7 +51,7 @@ class Domain < ApplicationRecord | |||
|
|||
set_crud_hooks :domain | |||
|
|||
apipie :class, desc: "A class representing #{model_name.human} object" do | |||
apipie :class, desc: "A class representing #{humanize_class_name} object" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, since the class names mostly taken as is for DSL, unless they explicitly renamed, it's okay to leave this untranslated and closer to something that is used within methods/return values. Although, there is a need to review all DSL documentation and make sure it's actually consistent.
Also, this whole string is not being translated...
1eb6c35
to
7c974b4
Compare
@ofedoren any idea if apipie descriptions can be callable? That way we can have translatable descriptions without having to rewrite so much. |
@ekohl, so sorry for the late reply. It's not that they can be callable, but AFAIU we can defer the actual translation: https://github.com/theforeman/foreman/blob/develop/config/initializers/apipie.rb#L68. |
I split off some of the changes in #9854 for easier review. |
7c974b4
to
9e7596c
Compare
Rebased on develop now #9854 is merged. This reduces the scope to apipie docs. |
app/models/domain.rb
Outdated
@@ -51,7 +51,7 @@ class Domain < ApplicationRecord | |||
|
|||
set_crud_hooks :domain | |||
|
|||
apipie :class, desc: "A class representing #{model_name.human} object" do | |||
apipie :class, desc: "A class representing #{model_name.singular.humanize(capitalize: false)} object" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ofedoren I wonder if it makes sense to enhance apipie to provide a desc_from_class
or some other way to automatically derive this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like all the descriptions are quite the same, so yeah, it makes sense to add something like default_desc
. Since I've noticed that apipie-dsl
needs some love, I'm going to add this as well.
Since, ideally we want to support translation for all the strings (and apipie-dsl doesn't have dependency on gettext), we shouldn't hardcode such string in the lib, but somehow provide it to be evaluated in the scope of a certain class. My suggestion is to add a new entry called e.g. default_model_description
to the config
(https://github.com/theforeman/foreman/blob/develop/config/initializers/apipie.rb#L3), which will accept a proc, which will be evaluated in the class (to be able to call model_name
) and save the string in the object. This could be translated later via callback we provide in the same config
. It would look like:
ApipieDSL.configure do |config|
# ...
config.default_model_description = ->(model) { N_("A class representing %s object") % model.model_name.singular.humanize(capitalize: false) }
# ...
end
That will be applied to all documented models unless there is an explicit override, such as :desc
option or short
method is called within a block. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do provide a translate method as ApipieDSL.translate(str, locale)
:
AFAIK it doesn't support interpolating the translated strings with variables, which makes it rather hard to use. I think that would still be needed.
In the context of Foreman: do we configure the translate method:
foreman/config/initializers/apipie.rb
Lines 22 to 28 in d8200ee
config.translate = lambda do |str, loc| | |
old_loc = FastGettext.locale | |
FastGettext.set_locale(loc) | |
trans = _(str) if str | |
FastGettext.set_locale(old_loc) | |
trans | |
end |
And I think we should rewrite that to use FastGettext.with_locale
:
config.translate = lambda do |str, loc|
str ? FastGettext.with_locale(loc) { _(str) } : nil
end
So I think your suggestion makes sense, but I'm not sure how to hook it up properly.
app/models/taxonomy.rb
Outdated
sections only: %w[all additional] | ||
name_exl, title_exl = class_scope.model_name.human == 'Location' ? ['Europe', 'Europe/Prague'] : ['Red Hat', 'Red Hat/Engineering'] | ||
name_exl, title_exl = model_name.to_s == 'Location' ? ['Europe', 'Europe/Prague'] : ['Red Hat', 'Red Hat/Engineering'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ekohl I believe we can consider using class_scope
here to determine the context of the model and this will help us to resolve the apipie
issue.
name_exl, title_exl = class_scope.model_name.to_s == 'Location' ? ['Europe', 'Europe/Prague'] : ['Red Hat', 'Red Hat/Engineering']
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, good catch.
9e7596c
to
46931e4
Compare
@ekohl should I raise a new PR to resolve the rubocop issue that I can see here, on top of this PR? and what does single commit workflow mean here? |
I'll address it.
Generally speaking a PR should have a single commit. Sometimes contributors add small commits to fix review comments, but that makes it hard to cherry pick into stable releases. That check signals reviewers they should pay attention to it. In this case I chose it and I think it makes sense because I'm fixing individual commits. This is then a discussion a reviewer can have with the author. The check is not blocking, but GH isn't great a providing alternatives here. |
@ekohl, I've released apipie-dsl-2.6.0. Along with some dependencies upgrades it supports now I'd also highly recommend to add to the # ...
config.reload_dsl = false
# ... Otherwise it's a pain to load the pages in development. |
@archanaserver is updating to apipie-dsl 2.6.0 something you could look at? It would probably supersede this PR |
Sure. |
Needs to be rebased after #9867 is merged. |
46931e4
to
dd01d0e
Compare
@ofedoren can you take a look at this? I still think these translations are executed on application startup, which can't work. |
It's invalid to do translations during startup, such as in models or in controllers. You should always use
N_()
(see https://projects.theforeman.org/projects/foreman/wiki/Translating#Extracting-strings). This is because when it's running you actually don't have translations at all, so it's effectively a noop anyway.When updating fast_gettext to 2.1+ (#9770) it turns into infinite recursion so it must be addressed if we want to move forward.