diff --git a/i18n/en_US.yml b/i18n/en_US.yml new file mode 100644 index 0000000..061af78 --- /dev/null +++ b/i18n/en_US.yml @@ -0,0 +1,82 @@ +--- +en_US: + error: + add: + name_empty: "You must define a name!" + config: + write: "Can't write the config file!" + check: "Checkconfig failed!" + key_bad_format: "The key string isn't in good format!" + delete: + id_no_exist: "Can't delete the item, the item %{id} doesn't exist!" + export: + write: "Can't export, impossible to write in %{file}!" + gpg_file: + decrypt: "Can't decrypt file!" + encrypt: "Can't encrypt the GPG file!" + import: + bad_format: "Can't import, the file is bad format!" + read: "Can't import, impossible to read %{file}!" + update: + id_no_exist: "Can't update the item, the item %{id} doesn't exist!" + cli: + form: + add: + title: "Add a new item" + name: "Enter the name: " + group: "Enter the group [default=NoGroup]: " + server: "Enter the hostname or ip: " + protocol: "Enter the protocol of the connection (ssh, http, other): " + login: "Enter the login connection: " + password: "Enter the the password: " + port: "Enter the connection port (optinal): " + comment: "Enter a comment (optinal): " + valid: "Item has been added!" + delete: + ask: "Are you sure to remove the item: %{id} ?" + valid: "The item %{id} has been removed!" + not_valid: "The item %{id} hasn't been removed, because it doesn't exist!" + import: + ask: "Are you sure to import this file: %{file} ?" + valid: "The import is succesfull!" + not_valid: "No data to import!" + setup: + title: "Setup a new config file" + lang: "Choose your language (en, fr, ...): " + gpg_key: "Enter the GPG key: " + gpg_file: "Enter the path to encrypt file [default=%{home}/.mpw.gpg]: " + timeout: "Enter the timeout (in seconde) to GPG password [default=60]: " + valid: "The config file has been created!" + update: + title: "Update an item" + name: "Enter the name [%{name}]: " + group: "Enter the group [%{group}]: " + server: "Enter the hostname or ip [%{server}]: " + protocol: "Enter the protocol of the connection [%{protocol}]: " + login: "Enter the login connection [%{login}]: " + password: "Enter the the password: " + port: "Enter the connection port [%{port}]: " + comment: "Enter a comment [%{comment}]: " + valid: "Item has been updated!" + interactive: + ask_password: "Password GPG: " + bad_password: "Bad password!" + goodbye: "Goodbye!" + unknown_command: "Unknown command!" + display: + comment: "Comment" + error: "ERROR" + gpg_password: "Password GPG: " + group: "Group" + login: "Login" + name: "Name" + nothing: "Nothing result!" + password: "Password" + port: "Port" + protocol: "Protocol" + server: "Server" + formats: + default: ! '%Y-%m-%d' + long: ! '%B %d, %Y' + short: ! '%b %d' + custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/i18n/fr_FR.yml b/i18n/fr_FR.yml new file mode 100644 index 0000000..b35fb9b --- /dev/null +++ b/i18n/fr_FR.yml @@ -0,0 +1,82 @@ +--- +fr_FR: + error: + add: + name_empty: "Vous devez définir un nom!" + config: + write: "Impossible d'écrire le fichier de configuration!" + check: "Le fichier de configuration est invalide!" + key_bad_format: "La clé GPG est invalide!" + delete: + id_no_exist: "Impossible de supprimer l'élément %{id}, car il n'existe pas!" + export: + write: "Impossible d'exporter les données dans le fichier %{file}!" + gpg_file: + decrypt: "Impossible de déchiffrer le fichier GPG!" + encrypt: "Impossible de chiffrer le fichier GPG!" + import: + bad_format: "Impossible d'importer le fichier car son format est incorrect!" + read: "Impossible d'importer le fichier %{file}, car il n'est pas lisible!" + update: + id_no_exist: "Impossible de mettre à jour l'élément %{id}, car il n'existe pas!" + cli: + form: + add: + title: "Ajout d'un nouvel élément" + name: "Entrez le nom: " + group: "Entrez le groupe [défaut=NoGroup]: " + server: "Entrez the hostname or ip: " + protocol: "Entrez le protocole de connexion (ssh, http, other): " + login: "Entrez l'identifiant de connexion: " + password: "Entrez le mot de passe: " + port: "Entrez le port de connexion (optionnel): " + comment: "Entrez un commentaire (optionnel): " + valid: "L'élément a bien été ajouté!" + delete: + ask: "Êtes vous sûre de vouloir supprimer l'élément %{id} ?" + valid: "L'élément %{id} a bien été supprimé!" + not_valid: "L'élément %{id} n'a pu être supprimé, car il n'existe pas!" + import: + ask: "Êtes vous sûre de vouloir importer le fichier %{file} ?" + valid: "L'import est un succès!" + not_valid: "Aucune donnée à importer!" + setup: + title: "Création d'un nouveau fichier de configuration" + lang: "Choisissez votre langue (en_US, fr_FR, ...) [défaut=%{lang}]: " + gpg_key: "Entrez la clé GPG: " + gpg_file: "Entrez le chemin du fichier qui sera chiffré [défaut=%{home}/.mpw.gpg]: " + timeout: "Entrez le temps (en seconde) du mot de passe GPG [défaut=60]: " + valid: "Le fichier de configuration a bien été créé!" + update: + title: "Mis à jour d'un élément" + name: "Entrez le nom [%{name}]: " + group: "Entrez le groupe [%{group}]: " + server: "Entrez le nom de domaine ou l'ip du serveur [%{server}]: " + protocol: "Entrez le protocole de connexion [%{protocol}]: " + login: "Entrez votre identifiant de connexion [%{login}]: " + password: "Entrez le mot de passe: " + port: "Entrez un port de connexion [%{port}]: " + comment: "Entrez un commentaire [%{comment}]: " + valid: "L'élément a bien été mis à jour!" + interactive: + ask_password: "Mot de passe GPG: " + bad_password: "Mauvais mot de passe!" + goodbye: "Au revoir!" + unknown_command: "Commande inconnue!" + display: + comment: "Commentaire" + error: "ERREUR" + gpg_password: "Mot de passe GPG: " + group: "Groupe" + login: "Identifiant" + name: "Nom" + nothing: "Aucun résultat!" + password: "Mot de passe" + port: "Port" + protocol: "Protocol" + server: "Serveur" + formats: + default: ! '%Y-%m-%d' + long: ! '%B %d, %Y' + short: ! '%b %d' + custom: ! '%A, %M %B, %Y @ %l:%M%P' diff --git a/lib/Cli.rb b/lib/Cli.rb index 81ae5de..9e379a2 100644 --- a/lib/Cli.rb +++ b/lib/Cli.rb @@ -7,43 +7,52 @@ require 'rubygems' require 'highline/import' require 'pathname' require 'readline' +require 'i18n' require "#{APP_ROOT}/lib/MPW.rb" class Cli # Constructor - def initialize() + def initialize(lang) @m = MPW.new() if not @m.checkconfig() - self.setup() + self.setup(lang) end if not self.decrypt() - puts "ERROR: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" exit 2 end end # Create a new config file - def setup() - puts "# Setup a new config file" + # @args: lang -> the software language + def setup(lang) + puts "# #{I18n.t('cli.form.setup.title')}" puts "# --------------------" - key = ask("Enter the GPG key: ") - file_gpg = ask("Enter the path to encrypt file [default=#{Dir.home()}/.mpw.gpg]: ") - timeout_pwd = ask("Enter the timeout (in seconde) to GPG password [default=60]: ") + language = ask(I18n.t('cli.form.setup.lang', :lang => lang)) + key = ask(I18n.t('cli.form.setup.gpg_key')) + file_gpg = ask(I18n.t('cli.form.setup.gpg_file', :home => Dir.home())) + timeout_pwd = ask(I18n.t('cli.form.setup.timeout')) - if @m.setup(key, file_gpg, timeout_pwd) - puts "The config file has been created!" + if !File.exist?("#{APP_ROOT}/i18n/#{language}.yml") + language= 'en_US' + end + I18n.load_path = Dir["#{APP_ROOT}/i18n/#{language}.yml"] + I18n.locale = language.to_sym + + if @m.setup(key, language, file_gpg, timeout_pwd) + puts I18n.t('cli.form.setup.valid') else - puts "ERROR: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" end end # Request the GPG password and decrypt the file def decrypt() - @passwd = ask("Password GPG: ") {|q| q.echo = false} + @passwd = ask(I18n.t('cli.display.gpg_password')) {|q| q.echo = false} return @m.decrypt(@passwd) end @@ -62,7 +71,7 @@ class Cli end end else - puts "Nothing result!" + puts I18n.t('cli.display.nothing') end end @@ -71,14 +80,14 @@ class Cli def displayFormat(item) puts "# --------------------" puts "# Id: #{item[MPW::ID]}" - puts "# Name: #{item[MPW::NAME]}" - puts "# Group: #{item[MPW::GROUP]}" - puts "# Server: #{item[MPW::SERVER]}" - puts "# Protocol: #{item[MPW::PROTOCOL]}" - puts "# Login: #{item[MPW::LOGIN]}" - puts "# Password: #{item[MPW::PASSWORD]}" - puts "# Port: #{item[MPW::PORT]}" - puts "# Comment: #{item[MPW::COMMENT]}" + puts "# #{I18n.t('cli.display.name')}: #{item[MPW::NAME]}" + puts "# #{I18n.t('cli.display.group')}: #{item[MPW::GROUP]}" + puts "# #{I18n.t('cli.display.server')}: #{item[MPW::SERVER]}" + puts "# #{I18n.t('cli.display.protocol')}: #{item[MPW::PROTOCOL]}" + puts "# #{I18n.t('cli.display.login')}: #{item[MPW::LOGIN]}" + puts "# #{I18n.t('cli.display.password')}: #{item[MPW::PASSWORD]}" + puts "# #{I18n.t('cli.display.port')}: #{item[MPW::PORT]}" + puts "# #{I18n.t('cli.display.comment')}: #{item[MPW::COMMENT]}" end # Display an item in the alternative format @@ -100,25 +109,25 @@ class Cli # Form to add a new item def add() row = Array.new() - puts "# Add a new item" + puts "# #{I18n.t('cli.form.add.title')}" puts "# --------------------" - name = ask("Enter the name: ") - group = ask("Enter the group [default=NoGroup]: ") - server = ask("Enter the hostname or ip: ") - protocol = ask("Enter the protocol of the connection (ssh, http, other): ") - login = ask("Enter the login connection: ") - passwd = ask("Enter the the password: ") - port = ask("Enter the connection port (optinal): ") - comment = ask("Enter a comment (optinal): ") + name = ask(I18n.t('cli.form.add.name')) + group = ask(I18n.t('cli.form.add.group')) + server = ask(I18n.t('cli.form.add.server')) + protocol = ask(I18n.t('cli.form.add.protocol')) + login = ask(I18n.t('cli.form.add.login')) + passwd = ask(I18n.t('cli.form.add.password')) + port = ask(I18n.t('cli.form.add.port')) + comment = ask(I18n.t('cli.form.add.comment')) if @m.add(name, group, server, protocol, login, passwd, port, comment) if @m.encrypt() - puts "Item has been added!" + puts I18n.t('cli.form.add.valid') else - puts "ERROR: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" end else - puts "ERROR: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" end end @@ -128,28 +137,28 @@ class Cli row = @m.searchById(id) if not row.empty? - puts "# Update an item" + puts "# #{I18n.t('cli.form.update.title')}" puts "# --------------------" - name = ask("Enter the name [#{row[MPW::NAME]}]: ") - group = ask("Enter the group [#{row[MPW::GROUP]}]: ") - server = ask("Enter the hostname or ip [#{row[MPW::SERVER]}]: ") - protocol = ask("Enter the protocol of the connection [#{row[MPW::PROTOCOL]}]: ") - login = ask("Enter the login connection [#{row[MPW::LOGIN]}]: ") - passwd = ask("Enter the the password: ") - port = ask("Enter the connection port [#{row[MPW::PORT]}]: ") - comment = ask("Enter a comment [#{row[MPW::COMMENT]}]: ") + name = ask(I18n.t('cli.form.update.name' , :name => row[MPW::NAME])) + group = ask(I18n.t('cli.form.update.group' , :group => row[MPW::GROUP])) + server = ask(I18n.t('cli.form.update.server' , :server => row[MPW::SERVER])) + protocol = ask(I18n.t('cli.form.update.protocol', :protocol => row[MPW::PROTOCOL])) + login = ask(I18n.t('cli.form.update.login' , :login => row[MPW::LOGIN])) + passwd = ask(I18n.t('cli.form.update.password')) + port = ask(I18n.t('cli.form.update.port' , :port => row[MPW::PORT])) + comment = ask(I18n.t('cli.form.update.comment' , :comment => row[MPW::COMMENT])) if @m.update(id, name, group, server, protocol, login, passwd, port, comment) if @m.encrypt() - puts "Item has been updated!" + puts I18n.t('cli.form.update.valid') else - puts "ERROR: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" end else - puts "ERROR: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" end else - puts "Nothing result!" + puts I18n.t('cli.display.nothing') end end @@ -163,24 +172,24 @@ class Cli if result.length > 0 self.displayFormat(result) - confirm = ask("Are you sure to remove the item: #{id} ? (y/N) ") + confirm = ask("#{I18n.t('cli.form.delete.ask', :id => id)} (y/N) ") if confirm =~ /^(y|yes|YES|Yes|Y)$/ force = true end else - puts "Nothing result!" + puts I18n.t('cli.display.nothing') end end if force if @m.remove(id) if @m.encrypt() - puts "The item #{id} has been removed!" + puts I18n.t('cli.form.delete.valid', :id => id) else - puts "ERROR: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" end else - puts "Nothing item has been removed!" + puts I18n.t('cli.form.delete.not_valid') end end end @@ -191,7 +200,7 @@ class Cli if @m.export(file) puts "The export in #{file} is succesfull!" else - puts "ERROR: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" end end @@ -208,20 +217,20 @@ class Cli self.displayFormat(r) end - confirm = ask("Are you sure to import this file: #{file} ? (y/N) ") + confirm = ask("#{I18n.t('cli.form.import.ask', :file => file)} (y/N) ") if confirm =~ /^(y|yes|YES|Yes|Y)$/ force = true end else - puts "No data to import!" + puts I18n.t('cli.form.import.not_valid') end end if force if @m.import(file) && @m.encrypt() - puts "The import is succesfull!" + puts I18n.t('cli.form.import.valid') else - puts "ERROR: #{@m.error_msg}" + puts "#{I18n.t('cli.display.error')}: #{@m.error_msg}" end end end @@ -231,15 +240,15 @@ class Cli group = nil last_access = Time.now.to_i - while buf = Readline.readline(" ", true) + while buf = Readline.readline(' ', true) if @m.timeout_pwd < Time.now.to_i - last_access - passwd_confirm = ask("Password GPG: ") {|q| q.echo = false} + passwd_confirm = ask(I18n.t('cli.interactive.ask_password')) {|q| q.echo = false} if @passwd.eql?(passwd_confirm) last_access = Time.now.to_i else - puts 'Bad password!' + puts I18n.t('cli.interactive.bad_password') next end else @@ -293,11 +302,11 @@ class Cli puts '# exit' puts '# q' when 'quit', 'exit', 'q' - puts 'Goodbye!' + puts I18n.t('cli.interactive.goodbye') break else if !command[0].nil? && !command[0].empty? - puts 'Unknow command!' + puts I18n.t('cli.interactive.unknown_command') end end diff --git a/lib/MPW.rb b/lib/MPW.rb index a301250..43b3ac9 100644 --- a/lib/MPW.rb +++ b/lib/MPW.rb @@ -7,6 +7,7 @@ require 'rubygems' require 'gpgme' require 'csv' require 'yaml' +require 'i18n' class MPW @@ -31,14 +32,15 @@ class MPW # Create a new config file # @args: key -> the gpg key to encrypt + # lang -> the software language # file_gpg -> the file who is encrypted # file_pwd -> the file who stock the password # timeout_pwd -> time to save the password # @rtrn: true if le config file is create - def setup(key, file_gpg, timeout_pwd) + def setup(key, lang, file_gpg, timeout_pwd) if not key =~ /[a-zA-Z0-9.-_]+\@[a-zA-Z0-9]+\.[a-zA-Z]+/ - @error_msg = "The key string isn't in good format!" + @error_msg = I18n.t('error.config.key_bad_format') return false end @@ -49,6 +51,7 @@ class MPW timeout_pwd.empty? ? (timeout_pwd = 60) : (timeout_pwd = timeout_pwd.to_i) config = {'config' => {'key' => key, + 'lang' => lang, 'file_gpg' => file_gpg, 'timeout_pwd' => timeout_pwd}} @@ -57,7 +60,7 @@ class MPW file << config.to_yaml end rescue Exception => e - @error_msg = "Can't write the config file!\n#{e}" + @error_msg = "#{I18n.t('error.config.write')}\n#{e}" return false end @@ -70,16 +73,25 @@ class MPW begin config = YAML::load_file(@file_config) @key = config['config']['key'] + @lang = config['config']['lang'] @file_gpg = config['config']['file_gpg'] @timeout_pwd = config['config']['timeout_pwd'].to_i if @key.empty? || @file_gpg.empty? - @error_msg = "Checkconfig failed!" + @error_msg = I18n.t('error.config.check') return false end + + if !@lang.nil? && !@lang.empty? + if !File.exist?("#{APP_ROOT}/i18n/#{@lang}.yml") + language= 'en_US' + end + I18n.load_path = Dir["#{APP_ROOT}/i18n/#{@lang}.yml"] + I18n.locale = @lang.to_sym + end rescue Exception => e - @error_msg = "Checkconfig failed!\n#{e}" + @error_msg = "#{I18n.t('error.config.check')}\n#{e}" return false end @@ -110,7 +122,7 @@ class MPW File.delete(@file_pwd) end - @error_msg = "Can't decrypt file!\n#{e}" + @error_msg = "#{I18n.t('error.gpg_file.decrypt')}\n#{e}" return false end end @@ -133,7 +145,7 @@ class MPW return true rescue Exception => e - @error_msg = "Can't encrypt the GPG file!\n#{e}" + @error_msg = "#{I18n.t('error.gpg_file.encrypt')}\n#{e}" return false end end @@ -191,7 +203,7 @@ class MPW row = Array.new() if name.nil? || name.empty? - @error_msg = "You must define a name!" + @error_msg = I18n.t('error.add.name_empty') return false end @@ -257,7 +269,7 @@ class MPW return true else - @error_msg = "Can't update the item, the item #{id} doesn't exist!" + @error_msg = I18n.t('error.update.id_no_exist', :id => id) return false end end @@ -269,7 +281,7 @@ class MPW if not @data.delete_at(id.to_i).nil? return true else - @error_msg = "Can't delete the item, the item #{id} doesn't exist!" + @error_msg = I18n.t('error.delete.id_no_exist', :id => id) return false end end @@ -288,7 +300,7 @@ class MPW return true rescue Exception => e - @error_msg = "Can't export, impossible to write in #{file}!\n#{e}" + @error_msg = "#{I18n.t('error.export.write', :file => file)}\n#{e}" return false end end @@ -301,7 +313,7 @@ class MPW data_new = IO.read(file) data_new.lines do |line| if not line =~ /(.*,){6}/ - @error_msg = "Can't import, the file is bad format!" + @error_msg = I18n.t('error.import.bad_format') return false else row = line.parse_csv.unshift(0) @@ -313,7 +325,7 @@ class MPW return true rescue Exception => e - @error_msg = "Can't import, impossible to read #{file}!\n#{e}" + @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" return false end end @@ -329,7 +341,7 @@ class MPW data = IO.read(file) data.lines do |line| if not line =~ /(.*,){6}/ - @error_msg = "Can't import, the file is bad format!" + @error_msg = I18n.t('error.import.bad_format') return false else result.push(line.parse_csv.unshift(id)) @@ -340,7 +352,7 @@ class MPW return result rescue Exception => e - @error_msg = "Can't import, impossible to read #{file}!\n#{e}" + @error_msg = "#{I18n.t('error.import.read', :file => file)}\n#{e}" return false end end diff --git a/mpw b/mpw index 597b3b7..dff953c 100755 --- a/mpw +++ b/mpw @@ -6,10 +6,21 @@ require 'rubygems' require 'optparse' require 'pathname' +require 'locale' +require 'i18n' APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) require "#{APP_ROOT}/lib/Cli.rb" + +lang = Locale::Tag.parse(ENV['LANG']).to_simple.to_s + +if !File.exist?("#{APP_ROOT}/i18n/#{lang}.yml") + lang = 'en_US' +end +I18n.load_path = Dir["#{APP_ROOT}/i18n/#{lang}.yml"] +I18n.locale = lang.to_sym + options = {} options[:force] = false options[:format] = false @@ -74,7 +85,7 @@ OptionParser.new do |opts| end.parse! -cli = Cli.new() +cli = Cli.new(lang) # Display the item's informations if not options[:setup].nil?