(PUP-7518) i18n module loading#5851
Conversation
|
CLA signed by all contributors. |
|
@eputnam the ticket here should be moved over to PUP, and commit message should be updated to correspond to the PUP ticket. We don't use MODULES tickets inside of Puppet. Thanks! |
|
Pinged @Magisus for a review as she's the resident gettext ninja. |
|
i may also add gettext config creation here in the future to reduce test clutter |
lib/puppet/module.rb
Outdated
|
|
||
| @absolute_path_to_manifests = Puppet::FileSystem::PathPattern.absolute(manifests) | ||
|
|
||
| # # i18n initialization for modules |
lib/puppet/module.rb
Outdated
| require 'locale' | ||
|
|
||
| initialize_i18n | ||
| rescue |
There was a problem hiding this comment.
It's nice to actually output the error message too
lib/puppet/module.rb
Outdated
| config_path = File.absolute_path('config.yaml', locales_path) | ||
| module_name = @forge_name.gsub("/","-") if @forge_name | ||
|
|
||
| nil if initialized_i18n? module_name |
There was a problem hiding this comment.
Should this be return nil?
There was a problem hiding this comment.
explicit returns in Ruby are frowned upon?
There was a problem hiding this comment.
Only at the ends of methods. This one is in the middle, and we want to quit if this is true.
lib/puppet/module.rb
Outdated
|
|
||
| initialize_i18n | ||
| rescue | ||
| Puppet.warning "GettextSetup initialization for #{@name} failed." |
There was a problem hiding this comment.
I assume this cannot be externalised as Gettext isn't setup yet.
There was a problem hiding this comment.
So I think since this is going to use Puppet's GettextSetup and not the module's, it can be. And it should be. We are trying to externalize all warnings and errors.
There was a problem hiding this comment.
good catch, it should have been but i guess we aren't externalizing yet.
spec/unit/module_spec.rb
Outdated
|
|
||
| before do | ||
| modroot = "#{modpath}/#{modname}/" | ||
| @config_path = "#{modroot}/locales/config.yaml" |
There was a problem hiding this comment.
nit: These variables should probably all be let definitions. None of them are used in before(:after) which is usually why @ variables are used.
lib/puppet/module.rb
Outdated
| end | ||
| end | ||
|
|
||
| def initialized_i18n? module_name |
There was a problem hiding this comment.
nit: It's probably more readable as i18n_initialized? e.g. "Is the door closed" vs "have you closed the door?"
lib/puppet/module.rb
Outdated
|
|
||
| begin | ||
| GettextSetup.initialize(locales_path) unless !File.file? config_path | ||
| Puppet.debug _("%{value0,} initialized for i18n: %{value1,}") % { value0: module_name, value1: GettextSetup.translation_repositories[module_name]} |
There was a problem hiding this comment.
We have been asked at least for now to not externalize debug messages.
There was a problem hiding this comment.
Also for future reference, please try to replace the value0 etc. with meaningful names. This will make it easier for the translator. Also as written, the commas will cause a mismatch of keys and this will explode.
lib/puppet/module.rb
Outdated
| end | ||
| end | ||
|
|
||
| def initialized_i18n? module_name |
|
Are modules with externalized strings able to function normally if GettextSetup is not present? See https://github.com/puppetlabs/puppet/blob/master/lib/puppet.rb#L25-L45 for how we are handling this in Puppet. |
|
we haven't started externalizing yet fortunately. this is a great point @Magisus , thank you! |
|
This is blocked on more extensive testing. |
|
Also if this functionality is going to be needed/supported in the LTS, this needs to be retargeted at stable. |
4fd3a5a to
238c010
Compare
|
Closing and reopening to fix CI |
|
Sorry to shuffle this again, but would you mind retargeting this at the 4.10.x branch? We're going to be deleting the stable branch in favor of that one soon. |
|
Would like to get this merged before the next release. @Iristyle have you had a chance to take a look? |
|
Are the translations namespaced so that translations in the module(s) don't affect puppet, and vice-versa? Or do we need to rely/assume that the keys are unique across puppet and all modules? |
|
they are namespaced inside the master_domain by "project_name" from config.yaml so there should not be any interference. |
lib/puppet/module.rb
Outdated
|
|
||
| private | ||
|
|
||
| def i18n_initialized? module_name |
There was a problem hiding this comment.
nit: Please use parens in method declaration
| @absolute_path_to_manifests = Puppet::FileSystem::PathPattern.absolute(manifests) | ||
|
|
||
| # i18n initialization for modules | ||
| if Puppet::GETTEXT_AVAILABLE |
There was a problem hiding this comment.
GETTEXT_AVAILABLE as a top-level constant for a feature test feels a little weird. The ship has probably sailed on this decision, but wondering why this isn't in a Puppet feature?
There was a problem hiding this comment.
Loading gettext happens very early (https://github.com/puppetlabs/puppet/blob/master/lib/puppet.rb#L51) and I seem to remember there being a reason we couldn't use Puppet features because of that. If that's not the case, this CAN probably change; the constant is only used internally.
There was a problem hiding this comment.
Fair enough... that sounds like a plausible explanation.
lib/puppet/module.rb
Outdated
| config_path = File.absolute_path('config.yaml', locales_path) | ||
| module_name = @forge_name.gsub("/","-") if @forge_name | ||
|
|
||
| return nil if i18n_initialized? module_name |
There was a problem hiding this comment.
nit: can just return rather than return nil given the return value of initialize_i18n is not used
Do we want to guard against a nil value for module_name?
Also, no need to allocate a locales_path or config_path if not necessary - so method could be reordered a bit:
def initialize_i18n
module_name = @forge_name.gsub("/","-") if @forge_name
return if module_name.nil? || i18n_initialized?(module_name)
locales_path = File.absolute_path('locales', path)
begin
GettextSetup.initialize(locales_path)
Puppet.debug "#{module_name} initialized for i18n: #{GettextSetup.translation_repositories[module_name]}"
rescue
config_path = File.absolute_path('config.yaml', locales_path)
Puppet.debug "Could not find locales configuration file for #{module_name} at #{config_path}. Skipping i18n initialization."
end
endThere was a problem hiding this comment.
I'm also not sure how the method is designed to fail here? This method rescues ... and so does its caller. Can probably streamline the error-handling a bit.
There was a problem hiding this comment.
it's not designed to fail, it just warns that there won't be any translations. i didn't think it was worth blocking a puppet run because translations aren't running. it's not affecting system configuration or anything, just the language of the log output, which will be obvious.
also, i like your version of the function a lot. thanks for the review!
|
perhaps a little blurb above the
|
bd3565a to
6bb02e2
Compare
|
doing some git shuffling now, don't merge yet. |
3586606 to
9252b22
Compare
|
ok, canoodling over, ready for merge. |
|
I would go ahead and squash those last two commits. They're not really logically separable. |
This adds to Puppet::Module to "initialize" a module for translations. Each module must be added to FastGettext.translation_repositories, so that translations in the modules code will be available to Puppet. Two methods are added here, one to check if a module has been initialized and another to initialize. To initialize, we are just wrapping GettextSetup.initialize basically.
| # i18n initialization for modules | ||
| if Puppet::GETTEXT_AVAILABLE | ||
| begin | ||
| initialize_i18n |
There was a problem hiding this comment.
What I meant here @eputnam is that if initialize_i18n never raises an exception based on its code already catching inside a begin / rescue ... that means there's no need for a rescue here.
Merged for now, but this could probably be tightened up a little.
This adds to Puppet::Module to "initialize" a module for translations. Each module must be added to FastGettext.translation_repositories, so that translations in the modules code will be available to Puppet. Two methods are added here, one to check if a module has been initialized and another to initialize. To initialize, we are just wrapping GettextSetup.initialize basically.