Skip to content

Commit

Permalink
(CODEMGMT-725) Externalize r10k log and error strings
Browse files Browse the repository at this point in the history
This commit externalizes all error and log messages in R10k.

Use the rake tasks provided by the gettext-setup-gem to create
translations.

r10k will attempt to set its error and log message locale using the
LANG environment variable and will default to English if it cannot
find a translation.
  • Loading branch information
austb committed Jul 7, 2016
1 parent 536f488 commit 9f19195
Show file tree
Hide file tree
Showing 52 changed files with 170 additions and 117 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ Gemfile.lock
.bundle
bundle
coverage
locales/r10k.pot
16 changes: 16 additions & 0 deletions README.mkd
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ information see the topic specific documentation:

For more general questions, see the [FAQ](doc/faq.mkd).

Development
-----------

### i18n

R10k has now had all user-facing strings in error messages and log messages
externalized. When adding new error or log messages please follow the
instructions for [writing translatable code](https://github.com/puppetlabs/gettext-setup-gem#writing-translatable-code).

### l10n

When localizing the strings found in R10k, follow the prescribed
[translation workflow](https://github.com/puppetlabs/gettext-setup-gem#translation-workflow).
The workflow describes the rake tasks provided to generate the .po files for
each locale.

Getting help
------------

Expand Down
3 changes: 3 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
spec = Gem::Specification.find_by_name 'gettext-setup'
load "#{spec.gem_dir}/lib/tasks/gettext.rake"
GettextSetup.initialize(File.absolute_path('locales', File.dirname(__FILE__)))
9 changes: 8 additions & 1 deletion lib/r10k.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
module R10K; end
require 'gettext-setup'

module R10K
GettextSetup.initialize(File.absolute_path('../locales', File.dirname(__FILE__)))

# Attempt to set the R10k error and log message locale
FastGettext.locale = ENV["LANG"]
end

require 'r10k/version'
require 'r10k/logging'
6 changes: 3 additions & 3 deletions lib/r10k/action/deploy/deploy_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module DeployHelpers
# @raise [SystemExit] If no config file was loaded
def expect_config!
if @config.nil?
logger.fatal("No configuration file given, no config file found in current directory, and no global config present")
logger.fatal(_("No configuration file given, no config file found in current directory, and no global config present"))
exit(8)
end
end
Expand All @@ -23,8 +23,8 @@ def expect_config!
def check_write_lock!(config)
write_lock = config.fetch(:deploy, {})[:write_lock]
if write_lock
logger.fatal("Making changes to deployed environments has been administratively disabled.")
logger.fatal("Reason: #{write_lock}")
logger.fatal(_("Making changes to deployed environments has been administratively disabled."))
logger.fatal(_("Reason: %{write_lock}") % {write_lock: write_lock})
exit(16)
end
end
Expand Down
12 changes: 6 additions & 6 deletions lib/r10k/action/deploy/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def visit_deployment(deployment)
undeployable = undeployable_environment_names(deployment.environments, @argv)
if !undeployable.empty?
@visit_ok = false
logger.error "Environment(s) \'#{undeployable.join(", ")}\' cannot be found in any source and will not be deployed."
logger.error _("Environment(s) \'%{environments}\' cannot be found in any source and will not be deployed.") % {environments: undeployable.join(", ")}
end

yield
Expand All @@ -72,21 +72,21 @@ def visit_source(source)

def visit_environment(environment)
if !(@argv.empty? || @argv.any? { |name| environment.dirname == name })
logger.debug1("Environment #{environment.dirname} does not match environment name filter, skipping")
logger.debug1(_("Environment %{env_dir} does not match environment name filter, skipping") % {env_dir: environment.dirname})
return
end

started_at = Time.new

status = environment.status
logger.info "Deploying environment #{environment.path}"
logger.info _("Deploying environment %{env_path}") % {env_path: environment.path}

environment.sync
logger.info "Environment #{environment.dirname} is now at #{environment.signature}"
logger.info _("Environment %{env_dir} is now at %{env_signature}") % {env_dir: environment.dirname, env_signature: environment.signature}

if status == :absent || @puppetfile
if status == :absent
logger.debug("Environment #{environment.dirname} is new, updating all modules")
logger.debug(_("Environment %{env_dir} is new, updating all modules") % {env_dir: environment.dirname})
end

yield
Expand Down Expand Up @@ -116,7 +116,7 @@ def visit_puppetfile(puppetfile)
end

def visit_module(mod)
logger.info "Deploying module #{mod.path}"
logger.info _("Deploying module %{mod_path}") % {mod_path: mod.path}
mod.sync
end

Expand Down
8 changes: 4 additions & 4 deletions lib/r10k/action/deploy/module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ def visit_source(source)

def visit_environment(environment)
if @opts[:environment] && (@opts[:environment] != environment.dirname)
logger.debug1("Only updating modules in environment #{@opts[:environment]}, skipping environment #{environment.path}")
logger.debug1(_("Only updating modules in environment %{opt_env} skipping environment %{env_path}") % {opt_env: @opts[:environment], env_path: environment.path})
else
logger.debug1("Updating modules #{@argv.inspect} in environment #{environment.path}")
logger.debug1(_("Updating modules %{modules} in environment %{env_path}") % {modules: @argv.inspect, env_path: environment_path})
yield
end
end
Expand All @@ -49,10 +49,10 @@ def visit_puppetfile(puppetfile)

def visit_module(mod)
if @argv.include?(mod.name)
logger.info "Deploying module #{mod.path}"
logger.info _("Deploying module %{mod_path}") % {mod_path: mod.path}
mod.sync
else
logger.debug1("Only updating modules #{@argv.inspect}, skipping module #{mod.name}")
logger.debug1(_("Only updating modules %{modules}, skipping module %{mod_name}") % {modules: @argv.inspect, mod_name: mod.name})
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/r10k/action/puppetfile/check.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def call
pf = R10K::Puppetfile.new(@root, @moduledir, @path)
begin
pf.load!
$stderr.puts "Syntax OK"
$stderr.puts _("Syntax OK")
true
rescue => e
$stderr.puts R10K::Errors::Formatting.format_exception(e, @trace)
Expand Down
2 changes: 1 addition & 1 deletion lib/r10k/action/puppetfile/install.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def visit_puppetfile(pf)
end

def visit_module(mod)
logger.info "Updating module #{mod.path}"
logger.info _("Updating module %{mod_path}") % {mod_path: mod.path}
mod.sync
end

Expand Down
6 changes: 3 additions & 3 deletions lib/r10k/action/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def setup_settings
overrides.delete_if { |_, val| val.nil? }

with_overrides = config_settings.merge(overrides) do |key, oldval, newval|
logger.debug2 "Overriding config file setting '#{key}': '#{oldval}' -> '#{newval}'"
logger.debug2 _("Overriding config file setting '%{key}': '%{old_val}' -> '%{new_val}'") % {key: key, old_val: oldval, new_val: newval}
newval
end

Expand Down Expand Up @@ -79,10 +79,10 @@ def settings_from_config(override_path)

if path
@opts[:config] = path
logger.debug2 "Reading configuration from #{path.inspect}"
logger.debug2 _("Reading configuration from %{config_path}") % {config_path: path.inspect}
results = loader.read(path)
else
logger.debug2 "No config file explicitly given and no default config file could be found, default settings will be used."
logger.debug2 _("No config file explicitly given and no default config file could be found, default settings will be used.")
end

results
Expand Down
12 changes: 8 additions & 4 deletions lib/r10k/deployment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,13 @@ def validate!
source.environments.each do |environment|
if hash.key?(environment.path)
osource, oenvironment = hash[environment.path]
msg = ""
msg << "Environment collision at #{environment.path} between "
msg << "#{source.name}:#{environment.name} and #{osource.name}:#{oenvironment.name}"
msg = _("Environment collision at %{env_path} between %{source}:%{env_name} and %{osource}:%{oenv_name}") %
{env_path: environment.path,
source: source.name,
env_name: environment.name,
osource: osource.name,
oenv_name: oenvironment.name}

raise R10K::Error, msg
else
hash[environment.path] = [source, environment]
Expand All @@ -111,7 +115,7 @@ def accept(visitor)
def load_sources
sources = @config[:sources]
if sources.nil? || sources.empty?
raise R10K::Error, "Unable to load sources; the supplied configuration does not define the 'sources' key"
raise R10K::Error, _("Unable to load sources; the supplied configuration does not define the 'sources' key")
end
@_sources = sources.map do |(name, hash)|
R10K::Source.from_hash(name, hash)
Expand Down
2 changes: 1 addition & 1 deletion lib/r10k/deployment/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def load_config
hash = loader.read(@configfile)

with_overrides = hash.merge(@overrides) do |key, oldval, newval|
logger.debug2 "Overriding config file setting '#{key}': '#{oldval}' -> '#{newval}'"
logger.debug2 _("Overriding config file setting '%{key}': '%{old_val}' -> '%{new_val}'") % {key: key, old_val: oldval, new_val: newval}
newval
end

Expand Down
6 changes: 3 additions & 3 deletions lib/r10k/environment/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def initialize(name, basedir, dirname, options = {})
# @abstract
# @return [void]
def sync
raise NotImplementedError, "#{self.class} has not implemented method #{__method__}"
raise NotImplementedError, _("%{class} has not implemented method %{method}") % {class: self.class, method: __method__}
end

# Determine the current status of the environment.
Expand All @@ -66,7 +66,7 @@ def sync
# @abstract
# @return [Symbol]
def status
raise NotImplementedError, "#{self.class} has not implemented method #{__method__}"
raise NotImplementedError, _("%{class} has not implemented method %{method}") % {class: self.class, method: __method__}
end

# Returns a unique identifier for the environment's current state.
Expand All @@ -75,7 +75,7 @@ def status
# @abstract
# @return [String]
def signature
raise NotImplementedError, "#{self.class} has not implemented method #{__method__}"
raise NotImplementedError, _("%{class} has not implemented method %{method}") %{class: self.class, method: __method__}
end

# Returns a hash describing the current state of the environment.
Expand Down
12 changes: 6 additions & 6 deletions lib/r10k/feature.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,29 @@ def initialize(name, opts = {}, &block)

# @return [true, false] Is this feature available?
def available?
logger.debug1 { "Testing to see if feature #{@name} is available." }
logger.debug1 { _("Testing to see if feature %{name} is available.") % {name: @name} }
rv = @libraries.all? { |lib| library_available?(lib) } && proc_available?
msg = rv ? "is" : "is not"
logger.debug1 { "Feature #{@name} #{msg} available." }
logger.debug1 { _("Feature %{name} %{message} available.") % {name: @name, message: msg} }
rv
end

private

def library_available?(lib)
logger.debug2 { "Attempting to load library '#{lib}' for feature #{@name}" }
logger.debug2 { _("Attempting to load library '%{lib}' for feature %{name}") % {lib: lib, name: @name} }
require lib
true
rescue ScriptError => e
logger.debug2 { "Error while loading library #{lib} for feature #{@name}: #{e.message}" }
logger.debug2 { _("Error while loading library %{lib} for feature %{name}: %{error_msg}") % {lib: lib, name: @name, error_msg: e.message} }
false
end

def proc_available?
if @block
logger.debug2 { "Evaluating proc #{@block.inspect} to test for feature #{@name}" }
logger.debug2 { _("Evaluating proc %{block} to test for feature %{name}") % {block: @block.inspect, name: @name} }
output = @block.call
logger.debug2 { "Proc #{@block.inspect} for feature #{@name} returned #{output.inspect}" }
logger.debug2 { _("Proc %{block} for feature %{name} returned %{output}") % {block: @block.inspect, name: @name, output: output.inspect } }
!!output
else
true
Expand Down
10 changes: 4 additions & 6 deletions lib/r10k/forge/module_release.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,14 @@ def verify
# should be unpacked/installed into.
# @return [void]
def unpack(target_dir)
logger.debug1 "Unpacking #{download_path} to #{target_dir} (with tmpdir #{unpack_path})"
logger.debug1 _("Unpacking %{download_path} to %{target_dir} (with tmpdir %{tmp_path})") % {download_path: download_path, target_dir: target_dir, tmp_path: unpack_path}
file_lists = PuppetForge::Unpacker.unpack(download_path.to_s, target_dir.to_s, unpack_path.to_s)
logger.debug2 "Valid files unpacked: #{file_lists[:valid]}"
logger.debug2 _("Valid files unpacked: %{valid_files}") % {valid_files: file_lists[:valid]}
if !file_lists[:invalid].empty?
logger.debug1 "These files existed in the module's tar file, but are invalid filetypes and were not " +
"unpacked: #{file_lists[:invalid]}"
logger.debug1 _("These files existed in the module's tar file, but are invalid filetypes and were not unpacked: %{invalid_files}") % {invalid_files: file_lists[:invalid]}
end
if !file_lists[:symlinks].empty?
raise R10K::Error, "Symlinks are unsupported and were not unpacked from the module tarball. " +
"#{@forge_release.slug} contained these ignored symlinks: #{file_lists[:symlinks]}"
raise R10K::Error, _("Symlinks are unsupported and were not unpacked from the module tarball. %{release_slug} contained these ignored symlinks: %{symlinks}") % {release_slug: @forge_release.slug, symlinks: file_lists[:symlinks]}
end
end

Expand Down
14 changes: 7 additions & 7 deletions lib/r10k/git.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module Git
:on_set => proc do
[:ssh, :https].each do |transport|
if !::Rugged.features.include?(transport)
logger.warn "Rugged has been compiled without support for #{transport}; Git repositories will not be reachable via #{transport}."
logger.warn _("Rugged has been compiled without support for %{transport}; Git repositories will not be reachable via %{transport}.") % {transport: transport}
end
end
end
Expand Down Expand Up @@ -65,7 +65,7 @@ module Git
def self.default_name
name, _ = @providers.find { |(_, hash)| R10K::Features.available?(hash[:feature]) }
if name.nil?
raise R10K::Error, "No Git providers are functional."
raise R10K::Error, _("No Git providers are functional.")
end
name
end
Expand All @@ -82,29 +82,29 @@ def self.provider=(name)
_, attrs = @providers.find { |(providername, _)| name == providername }
if attrs.nil?
@provider = NULL_PROVIDER
raise R10K::Error, "No Git provider named '#{name}'."
raise R10K::Error, _("No Git provider named '%{name}'.") % {name: name}
end
if !R10K::Features.available?(attrs[:feature])
@provider = NULL_PROVIDER
raise R10K::Error, "Git provider '#{name}' is not functional."
raise R10K::Error, _("Git provider '%{name}' is not functional.") % {name: name}
end
if attrs[:on_set]
attrs[:on_set].call
end

@provider = attrs[:module]
logger.debug1 { "Setting Git provider to #{@provider.name}" }
logger.debug1 { _("Setting Git provider to %{provider}") % {provider: @provider.name} }
end

# @return [Module] The namespace of the first available Git implementation.
# Implementation classes should be looked up against this returned Module.
def self.provider
case @provider
when NULL_PROVIDER
raise R10K::Error, "No Git provider set."
raise R10K::Error, _("No Git provider set.")
when UNSET_PROVIDER
self.provider = default_name
logger.debug1 { "Setting Git provider to default provider #{default_name}" }
logger.debug1 { _("Setting Git provider to default provider %{name}") % {name: default_name} }
end

@provider
Expand Down
2 changes: 1 addition & 1 deletion lib/r10k/git/alternates.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def include?(path)

def write(entries)
if ! @file.parent.directory?
raise R10K::Git::GitError, "Cannot write #{@file}; parent directory does not exist"
raise R10K::Git::GitError, _("Cannot write %{file}; parent directory does not exist") % {file: @file}
end
@file.open("w") do |fh|
entries.each do |entry|
Expand Down
4 changes: 2 additions & 2 deletions lib/r10k/git/cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def self.bare_repository
# @deprecated
# @return [String] The path to the git cache repository
def path
logger.warn "#{self.class}#path is deprecated; use #git_dir"
logger.warn _("%{class}#path is deprecated; use #git_dir") % {class: self.class}
git_dir
end

Expand Down Expand Up @@ -81,7 +81,7 @@ def sync!
if cached?
@repo.fetch
else
logger.debug1 "Creating new git cache for #{@remote.inspect}"
logger.debug1 _("Creating new git cache for %{remote}") % {remote: @remote.inspect}

# TODO extract this to an initialization step
if !File.exist?(settings[:cache_root])
Expand Down
4 changes: 2 additions & 2 deletions lib/r10k/git/rugged/bare_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def objects_dir
# @param remote [String] The URL of the Git remote to clone.
# @return [void]
def clone(remote)
logger.debug1 { "Cloning '#{remote}' into #{@path}" }
logger.debug1 { _("Cloning '%{remote}' into %{path}") % {remote: remote, path: @path} }

@_rugged_repo = ::Rugged::Repository.init_at(@path.to_s, true).tap do |repo|
config = repo.config
Expand All @@ -50,7 +50,7 @@ def clone(remote)
# @return [void]
def fetch(remote_name='origin')
backup_branches = wipe_branches
logger.debug1 { "Fetching remote '#{remote_name}' at #{@path}" }
logger.debug1 { _("Fetching remote '%{remote_name}' at %{path}") % {remote_name: remote_name, path: @path } }
options = {:credentials => credentials}
refspecs = ['+refs/*:refs/*']

Expand Down
Loading

0 comments on commit 9f19195

Please sign in to comment.