From 4fc15c306b3a7e4b5fb6c2779484dbce2748eb01 Mon Sep 17 00:00:00 2001 From: Mathieu Benoit Date: Thu, 12 Mar 2026 05:31:45 -0400 Subject: [PATCH] [REF] todo: use English text as i18n keys Replace snake_case i18n keys with their English translation so developers can read the code without cross-referencing the translations dictionary. Remove 5 obsolete duplicate entries. Generated by Claude Code 2.1.74 model claude-opus-4-6 Co-Authored-By: Mathieu Benoit --- script/todo/todo.json | 18 +- script/todo/todo.py | 398 +++++++++++++++++++-------------------- script/todo/todo_i18n.py | 358 +++++++++++++++++------------------ 3 files changed, 379 insertions(+), 395 deletions(-) diff --git a/script/todo/todo.json b/script/todo/todo.json index 256c02b..27255b0 100644 --- a/script/todo/todo.json +++ b/script/todo/todo.json @@ -10,51 +10,51 @@ }, "instance": [ { - "prompt_description_key": "json_instance_test", + "prompt_description_key": "Test - Minimal base instance", "makefile_cmd": "db_restore_erplibre_base_db_test", "database": "test" }, { - "prompt_description_key": "json_robot_minimal", + "prompt_description_key": "Open RobotLibre 🤖 minimal", "makefile_cmd": "robot_libre", "database": "robotlibre" }, { - "prompt_description_key": "json_robot_search", + "prompt_description_key": "Open RobotLibre 🤖 with search enabled", "makefile_cmd": "robot_libre_all", "database": "robotlibre" } ], "function": [ { - "prompt_description_key": "json_open_erplibre_todo", + "prompt_description_key": "Open ERPLibre with TODO 🤖", "command": "./.venv.erplibre/bin/python ./script/selenium/web_login.py" } ], "update_from_makefile": [ { - "prompt_description_key": "json_update_erplibre_base_test", + "prompt_description_key": "Update all erplibre_base on database test", "makefile_cmd": "db_erplibre_base_db_test_update_all", "database": "test" } ], "code_from_makefile": [ { - "prompt_description_key": "json_show_code_status", + "prompt_description_key": "Show code status", "makefile_cmd": "repo_show_status" }, { - "prompt_description_key": "json_stash_all_code", + "prompt_description_key": "Stash all code", "makefile_cmd": "repo_do_stash" }, { - "prompt_description_key": "json_format_modified_code", + "prompt_description_key": "Format modified code", "makefile_cmd": "format" } ], "git_from_makefile": [ { - "prompt_description_key": "git_config_vim", + "prompt_description_key": "Configure git local editor to vim", "bash_command": "git config --global core.editor \"vim\"" } ] diff --git a/script/todo/todo.py b/script/todo/todo.py index 2be6d41..d9a9790 100755 --- a/script/todo/todo.py +++ b/script/todo/todo.py @@ -100,33 +100,33 @@ class TODO: def _change_language(self): print() - print(t("lang_prompt") + ":") - print(f"[1] {t('lang_french')}") - print(f"[2] {t('lang_english')}") - print(f"[0] {t('back')}") + print(t("Choose language / Choisir la langue") + ":") + print(f"[1] {t('French')}") + print(f"[2] {t('English')}") + print(f"[0] {t('Back')}") choice = "" while choice not in ("0", "1", "2"): - choice = input(t("selection")).strip() + choice = input(t("Select: ")).strip() if choice == "0": return False elif choice == "1": set_lang("fr") else: set_lang("en") - print(t("lang_changed")) + print(t("Language changed to: English")) def run(self): with open(self.config_file.get_logo_ascii_file_path()) as my_file: print(my_file.read()) self._ask_language() - print(t("opening")) - print(f"🤖 {t('enter_directives')}") - help_info = f"""{t("command")} -[1] {t("menu_execute")} -[2] {t("menu_install")} -[3] {t("menu_question")} -[4] {t("menu_fork")} -[0] {t("menu_quit")} + print(t("Opening TODO ...")) + print(f"🤖 {t('=> Enter your choice by number and press Enter!')}") + help_info = f"""{t("Command:")} +[1] {t("Execute")} +[2] {t("Install")} +[3] {t("Question")} +[4] {t("Fork - Open TODO in a new tab")} +[0] {t("Quit")} """ while True: try: @@ -160,16 +160,16 @@ class TODO: # elif status == "3" or status == "install": # print("install") else: - print(t("cmd_not_found")) + print(t("Command not found !")) print(status) # manipuler() def execute_prompt_ia(self): while True: - help_info = f"""{t("command")} -[0] {t("back")} -{t("ia_prompt")}""" + help_info = f"""{t("Command:")} +[0] {t("Back")} +{t("Write your question ")}""" status = click.prompt(help_info) print() if status == "0": @@ -193,22 +193,22 @@ class TODO: print() def prompt_execute(self): - help_info = f"""{t("command")} -[1] {t("menu_automation")} -[2] {t("menu_code")} -[3] {t("menu_config")} -[4] {t("menu_database")} -[5] {t("menu_doc")} -[6] {t("menu_git")} -[7] {t("menu_gpt_code")} -[8] {t("menu_lang")} -[9] {t("menu_network")} -[10] {t("menu_process")} -[11] {t("menu_run")} -[12] {t("menu_security")} -[13] {t("menu_test")} -[14] {t("menu_update")} -[0] {t("back")} + help_info = f"""{t("Command:")} +[1] {t("Automation - Demonstration of developed features")} +[2] {t("Code - Developer tools")} +[3] {t("Config - Configuration file management")} +[4] {t("Database - Database tools")} +[5] {t("Doc - Documentation search")} +[6] {t("Git - Git tools")} +[7] {t("GPT code - AI assistant tools")} +[8] {t("Language - Change language / Changer la langue")} +[9] {t("Network - Network tools")} +[10] {t("Process - Execution tools")} +[11] {t("Run - Execute and install an instance")} +[12] {t("Security - Dependency security audit")} +[13] {t("Test - Test an Odoo module")} +[14] {t("Update - Update all developed staging source code")} +[0] {t("Back")} """ while True: status = click.prompt(help_info) @@ -272,7 +272,7 @@ class TODO: if status is not False: return else: - print(t("cmd_not_found")) + print(t("Command not found !")) def prompt_install(self): print("Detect first installation from code source.") @@ -352,7 +352,7 @@ class TODO: ), "0": ( "0", - f"0: {t('menu_quit')}", + f"0: {t('Quit')}", ), } commands_end = {} @@ -370,7 +370,7 @@ class TODO: label += " - Installed" if odoo_version == odoo_installed_version: label += " - Actual" - if version_info.get("default"): + if version_info.get("Default"): label += " - Default" if version_info.get("is_deprecated"): label += " - Deprecated" @@ -388,11 +388,11 @@ class TODO: odoo_version_input = "" while odoo_version_input not in install_commands: if odoo_version_input: - print(f"{t('error_value')} '{odoo_version_input}'") + print(f"{t('Error, cannot understand value')} '{odoo_version_input}'") str_input_dyn_odoo_version = ( - f"💬 {t('choose_version')}\n\t" + f"💬 {t('Choose a version:')}\n\t" + "\n\t".join([a[1] for a in install_commands.values()]) - + f"\n{t('selection')}" + + f"\n{t('Select: ')}" ) odoo_version_input = ( input(str_input_dyn_odoo_version).strip().lower() @@ -402,7 +402,7 @@ class TODO: return cmd_intern = install_commands.get(odoo_version_input)[2] - print(f"{t('will_execute')}\n{cmd_intern}") + print(f"{t('Will execute:')}\n{cmd_intern}") # TODO use external script to detect terminal to use on system # TODO check script open_terminal_code_generator.sh @@ -412,7 +412,7 @@ class TODO: cmd_intern, shell=True, executable="/bin/bash", check=True ) except subprocess.CalledProcessError as e: - print(f"{t('script_failed')} {e.returncode}.") + print(f"{t('The Bash script failed with return code')} {e.returncode}.") print("Wait after installation and open projects by terminal.") print("make open_terminal") self.restart_script(str(e)) @@ -458,12 +458,12 @@ class TODO: bash_command = instance.get("bash_command") if bash_command: - print(f"{t('will_execute')} {bash_command}") + print(f"{t('Will execute:')} {bash_command}") self.execute.exec_command_live( bash_command, source_erplibre=False ) - command = instance.get("command") + command = instance.get("Command:") if command: self.prompt_execute_selenium( command=command, extra_cmd_web_login=extra_cmd_web_login @@ -474,8 +474,8 @@ class TODO: callback(instance) def fill_help_info(self, choices): - help_info = t("command") + "\n" - help_end = f"[0] {t('back')}\n" + help_info = t("Command:") + "\n" + help_end = f"[0] {t('Back')}\n" for i, instance in enumerate(choices): desc_key = instance.get("prompt_description_key") if desc_key: @@ -496,14 +496,14 @@ class TODO: # Support mobile ERPLibre if os.path.exists(MOBILE_HOME_PATH): menu_entry = { - "prompt_description": t("mobile_compile_run"), + "prompt_description": t("Mobile - Compile and run software"), "callback": self.callback_make_mobile_home, } choices.append(menu_entry) # Support custom database to execute menu_entry = { - "prompt_description": t("choose_database"), + "prompt_description": t("Choose your database"), "callback": self.callback_execute_custom_database, } choices.insert(0, menu_entry) @@ -520,7 +520,7 @@ class TODO: int_cmd = int(status) if 1 < int_cmd <= init_len: cmd_no_found = False - status = click.confirm(t("new_instance_confirm")) + status = click.confirm(t("Do you want a new instance?")) instance = choices[int_cmd - 1] self.execute_from_configuration( instance, @@ -537,7 +537,7 @@ class TODO: except ValueError: pass if cmd_no_found: - print(t("cmd_not_found")) + print(t("Command not found !")) def prompt_execute_function(self): choices = self.config_file.get_config("function") @@ -559,11 +559,11 @@ class TODO: except ValueError: pass if cmd_no_found: - print(t("cmd_not_found")) + print(t("Command not found !")) def prompt_execute_update(self): # self.execute.exec_command_live(f"make {makefile_cmd}") - print(f"🤖 {t('update_dev')}") + print(f"🤖 {t('Development update')}") # TODO détecter les modules en modification pour faire la mise à jour en cours # TODO demander sur quel BD faire la mise à jour # TODO proposer les modules manuelles selon la configuration à mettre à jour @@ -574,11 +574,11 @@ class TODO: choices = self.config_file.get_config("update_from_makefile") menu_entry = { - "prompt_description": t("upgrade_odoo_migration"), + "prompt_description": t("Upgrade Odoo - Migration Database"), } choices.append(menu_entry) poetry_entry = { - "prompt_description": t("upgrade_poetry_dependency"), + "prompt_description": t("Upgrade Poetry - Dependency of Odoo"), } choices.append(poetry_entry) help_info = self.fill_help_info(choices) @@ -604,10 +604,10 @@ class TODO: except ValueError: pass if cmd_no_found: - print(t("cmd_not_found")) + print(t("Command not found !")) def prompt_execute_code(self): - print(f"🤖 {t('code_need')}") + print(f"🤖 {t('What do you need for development?')}") # help_info = """Commande : # [1] Status Git local et distant # [2] Démarrer le générateur de code @@ -623,18 +623,18 @@ class TODO: choices = self.config_file.get_config("code_from_makefile") menu_entry = { - "prompt_description": t("open_shell"), + "prompt_description": t("Open SHELL"), } choices.append(menu_entry) menu_entry = { - "prompt_description": t("upgrade_module"), + "prompt_description": t("Upgrade Module"), } choices.append(menu_entry) choices.append( { - "prompt_description": t("debug"), + "prompt_description": t("Debug"), } ) @@ -662,13 +662,13 @@ class TODO: except ValueError: pass if cmd_no_found: - print(t("cmd_not_found")) + print(t("Command not found !")) def prompt_execute_git(self): - print(f"🤖 {t('git_manage')}") + print(f"🤖 {t('Git management tools!')}") choices = [ - {"prompt_description": t("git_local_server")}, - {"prompt_description": t("git_add_remote")}, + {"prompt_description": t("Local git server")}, + {"prompt_description": t("Add a remote to a local repository")}, ] # Append config-driven entries @@ -698,31 +698,31 @@ class TODO: except ValueError: pass if cmd_no_found: - print(t("cmd_not_found")) + print(t("Command not found !")) def _git_add_remote(self): remote_name = ( - input(t("git_add_remote_name_prompt")).strip() or "localhost" + input(t("Remote name (default: localhost): ")).strip() or "localhost" ) - remote_url = input(t("git_add_remote_url_prompt")).strip() + remote_url = input(t("Repository address (e.g.: git://192.168.1.100/my-repo.git): ")).strip() if not remote_url: - print(t("git_add_remote_url_required")) + print(t("Repository address is required!")) return cmd = f"git remote add {remote_name} {remote_url}" - print(f"{t('will_execute')} {cmd}") + print(f"{t('Will execute:')} {cmd}") try: self.execute.exec_command_live( cmd, source_erplibre=False ) - print(t("git_add_remote_success")) + print(t("Remote added successfully!")) except Exception as e: - print(f"{t('git_add_remote_error')}{e}") + print(f"{t('Error adding remote: ')}{e}") def prompt_execute_git_local_server(self): - print(f"🤖 {t('git_repo_manage')}") + print(f"🤖 {t('Manage local git repository server!')}") choices = [ - {"prompt_description": t("git_repo_deploy_local")}, - {"prompt_description": t("git_repo_deploy_production")}, + {"prompt_description": t("Deploy a local git server (~/.git-server)")}, + {"prompt_description": t("Deploy a production git server (/srv/git, root required)")}, ] help_info = self.fill_help_info(choices) @@ -736,21 +736,21 @@ class TODO: elif status == "2": self._prompt_git_server_actions(production_ready=True) else: - print(t("cmd_not_found")) + print(t("Command not found !")) def _prompt_git_server_actions(self, production_ready=False): mode = ( - t("git_mode_production") + t("Production mode (/srv/git, root required)") if production_ready - else t("git_mode_local") + else t("Local mode (~/.git-server)") ) print(f"🤖 {mode}") choices = [ - {"prompt_description": t("git_action_all")}, - {"prompt_description": t("git_action_init")}, - {"prompt_description": t("git_action_remote")}, - {"prompt_description": t("git_action_push")}, - {"prompt_description": t("git_action_serve")}, + {"prompt_description": t("Run all (init + remote + push + serve)")}, + {"prompt_description": t("Init - Create bare repos")}, + {"prompt_description": t("Remote - Add local remotes")}, + {"prompt_description": t("Push - Push to local server")}, + {"prompt_description": t("Serve - Start git daemon")}, ] help_info = self.fill_help_info(choices) @@ -785,10 +785,10 @@ class TODO: action="serve", ) else: - print(t("cmd_not_found")) + print(t("Command not found !")) def _deploy_git_server(self, production_ready=False, action="all"): - print(t("git_repo_deploy_starting")) + print(t("Starting git server deployment...")) cmd = ( "python3 ./script/git/git_local_server.py -v" f" --action {action}" ) @@ -800,11 +800,11 @@ class TODO: ) def prompt_execute_gpt_code(self): - print(f"🤖 {t('gpt_code_manage')}") + print(f"🤖 {t('AI assistant tools for development!')}") choices = [ - {"prompt_description": t("gpt_code_claude_configs")}, - {"prompt_description": t("gpt_code_claude_add_automation")}, - {"prompt_description": t("menu_rtk")}, + {"prompt_description": t("Configure Claude Code configurations")}, + {"prompt_description": t("Add an automation with Claude in todo.py")}, + {"prompt_description": t("RTK - CLI proxy to reduce LLM token consumption")}, ] help_info = self.fill_help_info(choices) @@ -820,20 +820,20 @@ class TODO: elif status == "3": self.prompt_execute_rtk() else: - print(t("cmd_not_found")) + print(t("Command not found !")) def _prompt_claude_configs(self): - print(f"🤖 {t('gpt_code_claude_configs_manage')}") + print(f"🤖 {t('Deploy Claude Code commands!')}") choices = [ - {"prompt_description": t("gpt_code_claude_commit")}, + {"prompt_description": t("Commit - OCA/Odoo commit command")}, { "prompt_description": t( - "gpt_code_claude_todo_add_command" + "Todo Add Command - Add a command to todo.py menu" ) }, { "prompt_description": t( - "gpt_code_claude_list_commands" + "Show installed custom commands" ) }, ] @@ -858,12 +858,12 @@ class TODO: elif status == "3": self._list_claude_commands() else: - print(t("cmd_not_found")) + print(t("Command not found !")) def _list_claude_commands(self): commands_dir = os.path.expanduser("~/.claude/commands") if not os.path.isdir(commands_dir): - print(t("gpt_code_claude_no_commands")) + print(t("No custom commands found in ~/.claude/commands/")) return files = sorted( f @@ -871,9 +871,9 @@ class TODO: if f.endswith(".md") ) if not files: - print(t("gpt_code_claude_no_commands")) + print(t("No custom commands found in ~/.claude/commands/")) return - print(t("gpt_code_claude_list_header")) + print(t("Claude Code custom commands:")) print("-" * 50) for f in files: filepath = os.path.join(commands_dir, f) @@ -885,7 +885,7 @@ class TODO: print(f" /{name:<30} {date_str}") print("-" * 50) print( - f"{t('gpt_code_claude_list_total')}" + f"{t('Total:')}" f" {len(files)}" ) @@ -896,12 +896,12 @@ class TODO: dest_file = os.path.join(dest_dir, f"{command_name}.md") if os.path.exists(dest_file): - print(f"{t('gpt_code_cmd_exists')}{dest_file}") + print(f"{t('File already exists: ')}{dest_file}") overwrite = input( - t("gpt_code_cmd_overwrite") + t("Do you want to overwrite the file? (y/Y): ") ).strip() if overwrite not in ("y", "Y"): - print(t("gpt_code_cmd_nothing_to_do")) + print(t("Nothing to do.")) return template_path = os.path.join( @@ -916,8 +916,8 @@ class TODO: content = f.read() if personalize: - name = input(t("gpt_code_enter_name")).strip() - email = input(t("gpt_code_enter_email")).strip() + name = input(t("Enter your full name: ")).strip() + email = input(t("Enter your email: ")).strip() content = content.replace( "Your Name ", f"{name} <{email}>", @@ -931,24 +931,24 @@ class TODO: with open(dest_file, "w") as f: f.write(content) - print(f"{t('gpt_code_cmd_created')}{dest_file}") + print(f"{t('File created successfully: ')}{dest_file}") except Exception as e: - print(f"{t('gpt_code_cmd_error')}{e}") + print(f"{t('Error creating file: ')}{e}") def _claude_add_automation(self): description = input( - t("gpt_code_claude_add_automation_prompt") + t("Description of the command to add: ") ).strip() if not description: return command = input( - t("gpt_code_claude_add_automation_cmd_prompt") + t("Bash command to execute: ") ).strip() if not command: return section = ( input( - t("gpt_code_claude_add_automation_section_prompt") + t("Menu section (git/code/config/network/process): ") ).strip() or "git" ) @@ -970,17 +970,17 @@ class TODO: with open(config_path, "w") as f: json.dump(config, f, indent=4, ensure_ascii=False) f.write("\n") - print(t("gpt_code_claude_add_automation_success")) + print(t("Automation added successfully in todo.json!")) except Exception as e: - print(f"{t('gpt_code_claude_add_automation_error')}{e}") + print(f"{t('Error adding automation: ')}{e}") def prompt_execute_doc(self): - print(f"🤖 {t('doc_search')}") + print(f"🤖 {t('Looking for documentation?')}") choices = [ - {"prompt_description": t("migration_module_coverage")}, - {"prompt_description": t("what_change_between_version")}, - {"prompt_description": t("oca_guidelines")}, - {"prompt_description": t("oca_migration_odoo_19")}, + {"prompt_description": t("Migration module coverage")}, + {"prompt_description": t("What change between version")}, + {"prompt_description": t("OCA guidelines")}, + {"prompt_description": t("OCA migration Odoo 19 milestone")}, ] help_info = self.fill_help_info(choices) @@ -1021,14 +1021,14 @@ class TODO: elif status == "4": print("https://github.com/OCA/maintainer-tools/issues/658") else: - print(t("cmd_not_found")) + print(t("Command not found !")) def prompt_execute_database(self): - print(f"🤖 {t('db_modify')}") + print(f"🤖 {t('Make changes to databases!')}") choices = [ - {"prompt_description": t("download_db_backup")}, - {"prompt_description": t("restore_from_backup")}, - {"prompt_description": t("create_backup")}, + {"prompt_description": t("Download database to create backup (.zip)")}, + {"prompt_description": t("Restore from backup (.zip)")}, + {"prompt_description": t("Create backup (.zip)")}, ] help_info = self.fill_help_info(choices) @@ -1044,13 +1044,13 @@ class TODO: elif status == "3": self.db_manager.create_backup_from_database() else: - print(t("cmd_not_found")) + print(t("Command not found !")) def prompt_execute_process(self): - print(f"🤖 {t('process_manage')}") + print(f"🤖 {t('Manage execution processes!')}") choices = [ - {"prompt_description": t("kill_process_port")}, - {"prompt_description": t("kill_git_daemon")}, + {"prompt_description": t("Kill Odoo process from actual port")}, + {"prompt_description": t("Kill git daemon server process")}, ] help_info = self.fill_help_info(choices) @@ -1064,24 +1064,24 @@ class TODO: elif status == "2": self.process_kill_git_daemon() else: - print(t("cmd_not_found")) + print(t("Command not found !")) def process_kill_git_daemon(self): self.execute.exec_command_live( "pkill -f 'git daemon'", source_erplibre=False, ) - print(t("kill_git_daemon_done")) + print(t("Git daemon process killed.")) def prompt_execute_rtk(self): - print(f"🤖 {t('rtk_manage')}") + print(f"🤖 {t('Manage RTK (Rust Token Killer) for token optimization!')}") choices = [ - {"prompt_description": t("rtk_install")}, - {"prompt_description": t("rtk_version")}, - {"prompt_description": t("rtk_gain")}, - {"prompt_description": t("rtk_discover")}, - {"prompt_description": t("rtk_init_global")}, - {"prompt_description": t("rtk_status")}, + {"prompt_description": t("Install RTK")}, + {"prompt_description": t("Check RTK version")}, + {"prompt_description": t("Show cumulative token savings")}, + {"prompt_description": t("Discover optimization opportunities")}, + {"prompt_description": t("Initialize global auto-rewrite hook")}, + {"prompt_description": t("Check RTK status")}, ] help_info = self.fill_help_info(choices) @@ -1103,14 +1103,14 @@ class TODO: elif status == "6": self.rtk_check_status() else: - print(t("cmd_not_found")) + print(t("Command not found !")) def rtk_install(self): - print(f"🤖 {t('rtk_install_method')}") + print(f"🤖 {t('Installation method:')}") choices = [ - {"prompt_description": t("rtk_install_curl")}, - {"prompt_description": t("rtk_install_brew")}, - {"prompt_description": t("rtk_install_cargo")}, + {"prompt_description": t("curl - Automatic install script")}, + {"prompt_description": t("brew - Homebrew (macOS/Linux)")}, + {"prompt_description": t("cargo - Build from source (Rust required)")}, ] help_info = self.fill_help_info(choices) status = click.prompt(help_info) @@ -1133,7 +1133,7 @@ class TODO: source_erplibre=False, ) else: - print(t("cmd_not_found")) + print(t("Command not found !")) def rtk_check_version(self): self.execute.exec_command_live( @@ -1162,7 +1162,7 @@ class TODO: def rtk_check_status(self): rtk_path = shutil.which("rtk") if rtk_path is None: - print(t("rtk_not_installed")) + print(t("RTK is not installed. Use option 1 to install it.")) return result = self.execute.exec_command_live( @@ -1173,24 +1173,24 @@ class TODO: ) if isinstance(result, tuple) and result[0] == 0: version_output = " ".join(result[1]).strip() - print(f"{t('rtk_installed_version')}{version_output}") + print(f"{t('RTK is installed, version: ')}{version_output}") else: - print(f"{t('rtk_installed_version')}?") + print(f"{t('RTK is installed, version: ')}?") config_path = os.path.expanduser("~/.config/rtk/config.toml") if os.path.exists(config_path): - print(t("rtk_hook_active")) + print(t("Global auto-rewrite hook: active")) else: - print(t("rtk_hook_inactive")) + print(t("Global auto-rewrite hook: inactive")) def prompt_execute_config(self): - print(f"🤖 {t('config_manage')}") + print(f"🤖 {t('Manage ERPLibre and Odoo configuration!')}") choices = [ - {"prompt_description": t("generate_all_config")}, - {"prompt_description": t("generate_from_preconfig")}, - {"prompt_description": t("generate_from_backup")}, - {"prompt_description": t("generate_from_database")}, - {"prompt_description": t("setup_queue_job_for_parallelism")}, + {"prompt_description": t("Generate all configuration")}, + {"prompt_description": t("Generate from pre-configuration")}, + {"prompt_description": t("Generate from backup file")}, + {"prompt_description": t("Generate from database")}, + {"prompt_description": t("Setup queue job for parallelism")}, ] help_info = self.fill_help_info(choices) @@ -1210,15 +1210,15 @@ class TODO: elif status == "5": self.generate_config_queue_job() else: - print(t("cmd_not_found")) + print(t("Command not found !")) def prompt_execute_network(self): - print(f"🤖 {t('network_tools')}") + print(f"🤖 {t('Network tools!')}") choices = [ - {"prompt_description": t("ssh_port_forwarding")}, + {"prompt_description": t("SSH port-forwarding")}, { "prompt_description": t( - "network_performance_request_per_second" + "Network performance request per second" ) }, ] @@ -1234,7 +1234,7 @@ class TODO: elif status == "2": self.generate_network_performance_test() else: - print(t("cmd_not_found")) + print(t("Command not found !")) def generate_network_port_forwarding(self, add_arg=None): # ssh -L local_port:localhost:remote_port SSH_connection @@ -1261,9 +1261,9 @@ class TODO: ) def prompt_execute_security(self): - print(f"🤖 {t('security_audit')}") + print(f"🤖 {t('Dependency security audit!')}") choices = [ - {"prompt_description": t("pip_audit_desc")}, + {"prompt_description": t("pip-audit - Check vulnerabilities on Python environments")}, ] help_info = self.fill_help_info(choices) @@ -1275,14 +1275,14 @@ class TODO: elif status == "1": self.execute_pip_audit() else: - print(t("cmd_not_found")) + print(t("Command not found !")) def prompt_execute_test(self): - print(f"🤖 {t('test_description')}") + print(f"🤖 {t('Test an Odoo module on a temporary database!')}") choices = [ - {"prompt_description": t("test_run_module")}, - {"prompt_description": t("test_run_module_coverage")}, - {"prompt_description": t("test_run_unit_tests")}, + {"prompt_description": t("Test a module")}, + {"prompt_description": t("Test a module with code coverage")}, + {"prompt_description": t("ERPLibre unit tests")}, ] help_info = self.fill_help_info(choices) @@ -1298,25 +1298,25 @@ class TODO: elif status == "3": self.execute_unit_tests() else: - print(t("cmd_not_found")) + print(t("Command not found !")) def execute_test_module(self, coverage=False): # Module name - module_name = input(t("test_enter_module_name")).strip() + module_name = input(t("Module name to test: ")).strip() if not module_name: - print(t("test_module_required")) + print(t("Module name is required!")) return # Database name - db_name = input(t("test_db_name")).strip() + db_name = input(t("Temporary database name (default: test_todo_tmp): ")).strip() if not db_name: db_name = "test_todo_tmp" # Extra modules - extra_modules = input(t("test_install_extra_modules")).strip() + extra_modules = input(t("Extra modules to install (comma-separated, empty for none): ")).strip() # Log level - log_level = input(t("test_log_level")).strip() + log_level = input(t("Log level (default: test): ")).strip() if not log_level: log_level = "test" @@ -1326,7 +1326,7 @@ class TODO: modules_to_install += f",{extra_modules}" # Step 1: Create temp DB - print(f"\n--- {t('test_creating_db')} '{db_name}' ---") + print(f"\n--- {t('Creating temporary database')} '{db_name}' ---") cmd_restore = f"./script/database/db_restore.py --database {db_name}" self.execute.exec_command_live( cmd_restore, @@ -1336,7 +1336,7 @@ class TODO: # Step 2: Install modules print( - f"\n--- {t('test_installing_modules')}: {modules_to_install} ---" + f"\n--- {t('Installing modules')}: {modules_to_install} ---" ) cmd_install = ( f"./script/addons/install_addons.sh" @@ -1349,7 +1349,7 @@ class TODO: ) # Step 3: Run tests - print(f"\n--- {t('test_running')}: {module_name} ---") + print(f"\n--- {t('Running tests')}: {module_name} ---") cmd_test = ( f"ODOO_MODE_TEST=true" f" ./run.sh" @@ -1367,18 +1367,18 @@ class TODO: ) if status_code == 0: - print(f"\n✅ {t('test_success')}") + print(f"\n✅ {t('Tests completed successfully!')}") else: - print(f"\n❌ {t('test_failed')} {status_code}") + print(f"\n❌ {t('Tests failed with return code')} {status_code}") # Step 4: Cleanup lang = get_lang() - keep_input = input(t("test_keep_db")).strip().lower() + keep_input = input(t("Keep the temporary database? (y/N): ")).strip().lower() keep = keep_input in (("o", "oui") if lang == "fr" else ("y", "yes")) if keep: - print(f"{t('test_db_kept')}: {db_name}") + print(f"{t('Database kept')}: {db_name}") else: - print(f"\n--- {t('test_cleaning_db')} '{db_name}' ---") + print(f"\n--- {t('Cleaning up temporary database')} '{db_name}' ---") cmd_drop = f"./odoo_bin.sh db --drop --database {db_name}" self.execute.exec_command_live( cmd_drop, @@ -1387,7 +1387,7 @@ class TODO: ) def execute_unit_tests(self): - print(f"\n--- {t('test_unit_running')} ---") + print(f"\n--- {t('Running unit tests')} ---") cmd = ( ".venv.erplibre/bin/python -m unittest discover" " -s test -p 'test_*.py' -v" @@ -1398,9 +1398,9 @@ class TODO: return_status_and_output=True, ) if status_code == 0: - print(f"\n✅ {t('test_unit_success')}") + print(f"\n✅ {t('All unit tests passed')}") else: - print(f"\n❌ {t('test_unit_failed')}: {status_code}") + print(f"\n❌ {t('Some unit tests failed, exit code')}: {status_code}") def execute_pip_audit(self): versions, installed_versions, odoo_installed_version = ( @@ -1423,9 +1423,9 @@ class TODO: key_s = str(key_i) label = f"{key_s}: {erplibre_version}" if odoo_version == odoo_installed_version: - label += f" - {t('current')}" - if version_info.get("default"): - label += f" - {t('default')}" + label += f" - {t('Current')}" + if version_info.get("Default"): + label += f" - {t('Default')}" environments[key_s] = { "label": label, @@ -1435,20 +1435,20 @@ class TODO: } if not environments: - print(t("no_env_installed")) + print(t("No installed environment found. Install an Odoo version first.")) return # Show selection menu str_input = ( - f"💬 {t('choose_env_audit')}\n\t" + f"💬 {t('Choose an environment for the audit:')}\n\t" + "\n\t".join([v["label"] for v in environments.values()]) - + f"\n\t0: {t('back')}" - + f"\n{t('selection')}" + + f"\n\t0: {t('Back')}" + + f"\n{t('Select: ')}" ) env_input = "" while env_input not in environments and env_input != "0": if env_input: - print(f"{t('error_value')}" f" '{env_input}'") + print(f"{t('Error, cannot understand value')}" f" '{env_input}'") env_input = input(str_input).strip() if env_input == "0": @@ -1459,12 +1459,12 @@ class TODO: req_path = selected["req_path"] if not os.path.isfile(req_path): - print(f"{t('dep_file_not_found')}{req_path}") + print(f"{t('Dependencies file not found: ')}{req_path}") return # TODO support bash from parameter if open gnome-terminal cmd = f"pip-audit -r {req_path} -l;bash" - print(f"{t('execution')}{cmd}") + print(f"{t('Execution: ')}{cmd}") self.execute.exec_command_live( cmd, source_erplibre=True, @@ -1491,10 +1491,10 @@ class TODO: def generate_config_from_preconfiguration(self): choices = [ - {"prompt_description": t("preconfig_base")}, - {"prompt_description": t("preconfig_base_code_generator")}, - {"prompt_description": t("preconfig_base_image_db")}, - {"prompt_description": t("preconfig_all")}, + {"prompt_description": t("base")}, + {"prompt_description": t("base + code_generator")}, + {"prompt_description": t("base + image_db")}, + {"prompt_description": t("all")}, # {"prompt_description": "base + migration"}, ] help_info = self.fill_help_info(choices) @@ -1523,11 +1523,11 @@ class TODO: # str_group = f"--group {group}" # self.generate_config(add_arg=str_group) else: - print(t("cmd_not_found")) + print(t("Command not found !")) def debug_ide(self): choices = [ - {"prompt_description": t("debug_todo_py")}, + {"prompt_description": t("Debug todo.py")}, ] help_info = self.fill_help_info(choices) @@ -1542,7 +1542,7 @@ class TODO: os.path.join(os.getcwd(), "script/todo/todo.py"), ) else: - print(t("cmd_not_found")) + print(t("Command not found !")) def generate_config_from_backup(self): file_name = self.db_manager.open_file_image_db() @@ -1738,7 +1738,7 @@ class TODO: ) def restart_script(self, last_error): - print(f"🤖 {t('reboot_todo')}") + print(f"🤖 {t('Reboot TODO ...')}") # os.execv(sys.executable, ['python'] + sys.argv) # TODO mettre check que le répertoire est créé, s'il existe, auto-loop à corriger if os.path.exists(VENV_ERPLIBRE) and not os.path.exists( @@ -1906,13 +1906,13 @@ if __name__ == "__main__": todo.crash_diagnostic(CRASH_E) todo.run() except KeyboardInterrupt: - print(t("keyboard_interrupt")) + print(t("Keyboard interrupt")) finally: end_time = time.time() duration_sec = end_time - start_time if humanize: duration_delta = datetime.timedelta(seconds=duration_sec) humain_time = humanize.precisedelta(duration_delta) - print(f"\n{t('execution_time')} {humain_time}\n") + print(f"\n{t('TODO execution time')} {humain_time}\n") else: - print(f"\n{t('execution_time')} {duration_sec:.2f} sec.\n") + print(f"\n{t('TODO execution time')} {duration_sec:.2f} sec.\n") diff --git a/script/todo/todo_i18n.py b/script/todo/todo_i18n.py index f75c2b5..28c5726 100644 --- a/script/todo/todo_i18n.py +++ b/script/todo/todo_i18n.py @@ -15,715 +15,699 @@ TRANSLATIONS = { "fr": "L'importation est un succès!", "en": "Importation success!", }, - "opening": { + "Opening TODO ...": { "fr": "Ouverture de TODO en cours ...", "en": "Opening TODO ...", }, - "enter_directives": { + "=> Enter your choice by number and press Enter!": { "fr": "=> Entre tes directives par son chiffre et fait Entrée!", "en": "=> Enter your choice by number and press Enter!", }, - "command": { + "Command:": { "fr": "Commande :", "en": "Command:", }, - "menu_execute": { + "Execute": { "fr": "Exécution", "en": "Execute", }, - "menu_install": { + "Install": { "fr": "Installation", "en": "Install", }, - "menu_question": { + "Question": { "fr": "Question", "en": "Question", }, - "menu_fork": { + "Fork - Open TODO in a new tab": { "fr": "Fork - Ouvre TODO dans une nouvelle tabulation", "en": "Fork - Open TODO in a new tab", }, - "menu_quit": { + "Quit": { "fr": "Quitter", "en": "Quit", }, - "cmd_not_found": { + "Command not found !": { "fr": "Commande non trouvée !", "en": "Command not found !", }, - "back": { + "Back": { "fr": "Retour", "en": "Back", }, # Execute submenu - "menu_run": { + "Run - Execute and install an instance": { "fr": "Run - Exécuter et installer une instance", "en": "Run - Execute and install an instance", }, - "menu_automation": { + "Automation - Demonstration of developed features": { "fr": "Automatisation - Demonstration des fonctions développées", "en": "Automation - Demonstration of developed features", }, - "menu_update": { + "Update - Update all developed staging source code": { "fr": "Mise à jour - Update all developed staging source code", "en": "Update - Update all developed staging source code", }, - "menu_code": { + "Code - Developer tools": { "fr": "Code - Outil pour développeur", "en": "Code - Developer tools", }, - "menu_doc": { + "Doc - Documentation search": { "fr": "Doc - Recherche de documentation", "en": "Doc - Documentation search", }, - "menu_database": { + "Database - Database tools": { "fr": "Database - Outils sur les bases de données", "en": "Database - Database tools", }, - "menu_process": { + "Process - Execution tools": { "fr": "Process - Outils sur les executions", "en": "Process - Execution tools", }, - "menu_config": { + "Config - Configuration file management": { "fr": "Config - Traitement du fichier de configuration", "en": "Config - Configuration file management", }, - "menu_network": { + "Network - Network tools": { "fr": "Réseau - Outil réseautique", "en": "Network - Network tools", }, - "menu_security": { + "Security - Dependency security audit": { "fr": "Sécurité - Audit de sécurité des dépendances", "en": "Security - Dependency security audit", }, - "menu_rtk": { + "RTK - CLI proxy to reduce LLM token consumption": { "fr": "RTK - Proxy CLI pour réduire la consommation de tokens LLM", "en": "RTK - CLI proxy to reduce LLM token consumption", }, - "menu_lang": { + "Language - Change language / Changer la langue": { "fr": "Langue - Changer la langue / Change language", "en": "Language - Change language / Changer la langue", }, # RTK (Rust Token Killer) - "rtk_manage": { + "Manage RTK (Rust Token Killer) for token optimization!": { "fr": "Gérer RTK (Rust Token Killer) pour optimiser les tokens!", "en": "Manage RTK (Rust Token Killer) for token optimization!", }, - "rtk_install": { + "Install RTK": { "fr": "Installer RTK", "en": "Install RTK", }, - "rtk_version": { + "Check RTK version": { "fr": "Vérifier la version de RTK", "en": "Check RTK version", }, - "rtk_gain": { + "Show cumulative token savings": { "fr": "Afficher les économies de tokens cumulées", "en": "Show cumulative token savings", }, - "rtk_discover": { + "Discover optimization opportunities": { "fr": "Identifier les opportunités d'optimisation", "en": "Discover optimization opportunities", }, - "rtk_init_global": { + "Initialize global auto-rewrite hook": { "fr": "Initialiser le hook auto-rewrite global", "en": "Initialize global auto-rewrite hook", }, - "rtk_status": { + "Check RTK status": { "fr": "Vérifier le statut de RTK", "en": "Check RTK status", }, - "rtk_not_installed": { + "RTK is not installed. Use option 1 to install it.": { "fr": "RTK n'est pas installé. Utilisez l'option 1 pour l'installer.", "en": "RTK is not installed. Use option 1 to install it.", }, - "rtk_installed_version": { + "RTK is installed, version: ": { "fr": "RTK est installé, version : ", "en": "RTK is installed, version: ", }, - "rtk_hook_active": { + "Global auto-rewrite hook: active": { "fr": "Hook auto-rewrite global : actif", "en": "Global auto-rewrite hook: active", }, - "rtk_hook_inactive": { + "Global auto-rewrite hook: inactive": { "fr": "Hook auto-rewrite global : inactif", "en": "Global auto-rewrite hook: inactive", }, - "rtk_install_method": { + "Installation method:": { "fr": "Méthode d'installation :", "en": "Installation method:", }, - "rtk_install_curl": { + "curl - Automatic install script": { "fr": "curl - Script d'installation automatique", "en": "curl - Automatic install script", }, - "rtk_install_brew": { + "brew - Homebrew (macOS/Linux)": { "fr": "brew - Homebrew (macOS/Linux)", "en": "brew - Homebrew (macOS/Linux)", }, - "rtk_install_cargo": { + "cargo - Build from source (Rust required)": { "fr": "cargo - Compilation depuis les sources (Rust requis)", "en": "cargo - Build from source (Rust required)", }, # Prompts and messages - "enter_password": { + "Enter your password: ": { "fr": "Entrez votre mot de passe : ", "en": "Enter your password: ", }, - "ia_prompt": { + "Write your question ": { "fr": "Écrit moi ta question ", "en": "Write your question ", }, - "new_instance_confirm": { + "Do you want a new instance?": { "fr": "Voulez-vous une nouvelle instance?", "en": "Do you want a new instance?", }, - "ssh_port_forwarding": { + "SSH port-forwarding": { "fr": "SSH port-forwarding", "en": "SSH port-forwarding", }, - "network_performance_request_per_second": { + "Network performance request per second": { "fr": "Performance réseau en requêtes par seconde", "en": "Network performance request per second", }, - "setup_queue_job_for_parallelism": { + "Setup queue job for parallelism": { "fr": "Configurer la file d'attente pour l'exécution parallèle", "en": "Setup queue job for parallelism", }, - "choose_database": { + "Choose your database": { "fr": "Choisir sa base de données", "en": "Choose your database", }, - "update_dev": { + "Development update": { "fr": "Mise à jour du développement", "en": "Development update", }, - "code_need": { + "What do you need for development?": { "fr": "Qu'avez-vous de besoin pour développer?", "en": "What do you need for development?", }, - "doc_search": { + "Looking for documentation?": { "fr": "Vous cherchez de la documentation?", "en": "Looking for documentation?", }, - "db_modify": { + "Make changes to databases!": { "fr": "Faites des modifications sur les bases de données!", "en": "Make changes to databases!", }, - "process_manage": { + "Manage execution processes!": { "fr": "Manipuler les processus d'exécution!", "en": "Manage execution processes!", }, - "config_manage": { + "Manage ERPLibre and Odoo configuration!": { "fr": "Manipuler la configuration ERPLibre et Odoo!", "en": "Manage ERPLibre and Odoo configuration!", }, - "network_tools": { + "Network tools!": { "fr": "Outil réseautique!", "en": "Network tools!", }, - "security_audit": { + "Dependency security audit!": { "fr": "Audit de securite des dépendances!", "en": "Dependency security audit!", }, - "script_failed": { + "The Bash script failed with return code": { "fr": "Le script Bash a échoué avec le code de retour", "en": "The Bash script failed with return code", }, - "no_env_installed": { + "No installed environment found. Install an Odoo version first.": { "fr": "Aucun environnement installe trouve. Installez d'abord une version d'Odoo.", "en": "No installed environment found. Install an Odoo version first.", }, - "choose_env_audit": { + "Choose an environment for the audit:": { "fr": "Choisir un environnement pour l'audit :", "en": "Choose an environment for the audit:", }, - "selection": { + "Select: ": { "fr": "Sélection : ", "en": "Select: ", }, - "error_value": { + "Error, cannot understand value": { "fr": "Erreur, impossible de comprendre la valeur", "en": "Error, cannot understand value", }, - "dep_file_not_found": { + "Dependencies file not found: ": { "fr": "Fichier de dépendances introuvable : ", "en": "Dependencies file not found: ", }, - "execution": { + "Execution: ": { "fr": "Execution : ", "en": "Execution: ", }, - "current": { + "Current": { "fr": "Actuel", "en": "Current", }, - "default": { + "Default": { "fr": "Défaut", "en": "Default", }, - "reboot_todo": { + "Reboot TODO ...": { "fr": "Reboot TODO ...", "en": "Reboot TODO ...", }, - "pip_audit_desc": { + "pip-audit - Check vulnerabilities on Python environments": { "fr": "pip-audit - Verifier les vulnérabilités sur les environnements Python", "en": "pip-audit - Check vulnerabilities on Python environments", }, - "will_execute": { + "Will execute:": { "fr": "Va exécuter :", "en": "Will execute:", }, - "choose_version": { + "Choose a version:": { "fr": "Choisir une version :", "en": "Choose a version:", }, - "error_cannot_understand": { - "fr": "Erreur, impossible de comprendre la valeur", - "en": "Error, cannot understand value", - }, # todo.json translatable prompt_descriptions - "json_instance_test": { + "Test - Minimal base instance": { "fr": "Test - Instance de base minimale", "en": "Test - Minimal base instance", }, - "json_robot_minimal": { + "Open RobotLibre 🤖 minimal": { "fr": "Ouvrir RobotLibre 🤖 minimal", "en": "Open RobotLibre 🤖 minimal", }, - "json_robot_search": { + "Open RobotLibre 🤖 with search enabled": { "fr": "Ouvrir RobotLibre 🤖 en activant la recherche", "en": "Open RobotLibre 🤖 with search enabled", }, - "json_open_erplibre_todo": { + "Open ERPLibre with TODO 🤖": { "fr": "Ouvrir ERPLibre avec TODO 🤖", "en": "Open ERPLibre with TODO 🤖", }, - "json_update_erplibre_base_test": { + "Update all erplibre_base on database test": { "fr": "Mise à jour de tous les erplibre_base sur la base de données test", "en": "Update all erplibre_base on database test", }, - "json_show_code_status": { + "Show code status": { "fr": "Afficher le statut du code", "en": "Show code status", }, - "json_stash_all_code": { + "Stash all code": { "fr": "Remiser tout le code", "en": "Stash all code", }, - "json_format_modified_code": { + "Format modified code": { "fr": "Formater le code modifié", "en": "Format modified code", }, # todo.py hardcoded prompt_descriptions - "mobile_compile_run": { + "Mobile - Compile and run software": { "fr": "Mobile - Compiler et exécuter le logiciel", "en": "Mobile - Compile and run software", }, - "upgrade_odoo_migration": { + "Upgrade Odoo - Migration Database": { "fr": "Mise à jour Odoo - Migration de base de données", "en": "Upgrade Odoo - Migration Database", }, - "upgrade_poetry_dependency": { + "Upgrade Poetry - Dependency of Odoo": { "fr": "Mise à jour Poetry - Dépendances d'Odoo", "en": "Upgrade Poetry - Dependency of Odoo", }, - "open_shell": { + "Open SHELL": { "fr": "Ouvrir le SHELL", "en": "Open SHELL", }, - "upgrade_module": { + "Upgrade Module": { "fr": "Mise à jour de module", "en": "Upgrade Module", }, - "debug": { + "Debug": { "fr": "Débogage", "en": "Debug", }, - "migration_module_coverage": { + "Migration module coverage": { "fr": "Couverture de migration des modules", "en": "Migration module coverage", }, - "what_change_between_version": { + "What change between version": { "fr": "Quels changements entre les versions", "en": "What change between version", }, - "oca_guidelines": { + "OCA guidelines": { "fr": "Directives OCA", "en": "OCA guidelines", }, - "oca_migration_odoo_19": { + "OCA migration Odoo 19 milestone": { "fr": "Migration OCA Odoo 19 - Jalons", "en": "OCA migration Odoo 19 milestone", }, - "download_db_backup": { + "Download database to create backup (.zip)": { "fr": "Télécharger une base de données pour créer une sauvegarde (.zip)", "en": "Download database to create backup (.zip)", }, - "restore_from_backup": { + "Restore from backup (.zip)": { "fr": "Restaurer a partir d'une sauvegarde (.zip)", "en": "Restore from backup (.zip)", }, - "create_backup": { + "Create backup (.zip)": { "fr": "Créer une sauvegarde (.zip)", "en": "Create backup (.zip)", }, - "kill_process_port": { + "Kill Odoo process from actual port": { "fr": "Terminer le processus Odoo du port actuel", "en": "Kill Odoo process from actual port", }, - "kill_git_daemon": { + "Kill git daemon server process": { "fr": "Terminer le processus du serveur git daemon", "en": "Kill git daemon server process", }, - "kill_git_daemon_done": { + "Git daemon process killed.": { "fr": "Processus git daemon terminé.", "en": "Git daemon process killed.", }, - "generate_all_config": { + "Generate all configuration": { "fr": "Générer toute la configuration", "en": "Generate all configuration", }, - "generate_from_preconfig": { + "Generate from pre-configuration": { "fr": "Générer a partir de la pre-configuration", "en": "Generate from pre-configuration", }, - "generate_from_backup": { + "Generate from backup file": { "fr": "Générer a partir d'un fichier de sauvegarde", "en": "Generate from backup file", }, - "generate_from_database": { + "Generate from database": { "fr": "Générer a partir de la base de données", "en": "Generate from database", }, - "preconfig_base": { + "base": { "fr": "base", "en": "base", }, - "preconfig_base_code_generator": { + "base + code_generator": { "fr": "base + code_generator", "en": "base + code_generator", }, - "preconfig_base_image_db": { + "base + image_db": { "fr": "base + image_db", "en": "base + image_db", }, - "preconfig_all": { + "all": { "fr": "tout", "en": "all", }, - "debug_todo_py": { + "Debug todo.py": { "fr": "Débogage todo.py", "en": "Debug todo.py", }, # Test section - "menu_test": { + "Test - Test an Odoo module": { "fr": "Test - Tester un module Odoo", "en": "Test - Test an Odoo module", }, - "test_description": { + "Test an Odoo module on a temporary database!": { "fr": "Tester un module Odoo sur une base de données temporaire!", "en": "Test an Odoo module on a temporary database!", }, - "test_run_module": { + "Test a module": { "fr": "Tester un module", "en": "Test a module", }, - "test_run_module_coverage": { + "Test a module with code coverage": { "fr": "Tester un module avec couverture de code", "en": "Test a module with code coverage", }, - "test_run_unit_tests": { + "ERPLibre unit tests": { "fr": "Tests unitaires ERPLibre", "en": "ERPLibre unit tests", }, - "test_unit_running": { + "Running unit tests": { "fr": "Exécution des tests unitaires", "en": "Running unit tests", }, - "test_unit_success": { + "All unit tests passed": { "fr": "Tous les tests unitaires ont réussi", "en": "All unit tests passed", }, - "test_unit_failed": { + "Some unit tests failed, exit code": { "fr": "Des tests unitaires ont échoué, code de sortie", "en": "Some unit tests failed, exit code", }, - "test_enter_module_name": { + "Module name to test: ": { "fr": "Nom du module à tester : ", "en": "Module name to test: ", }, - "test_db_name": { + "Temporary database name (default: test_todo_tmp): ": { "fr": "Nom de la base de données temporaire (défaut: test_todo_tmp) : ", "en": "Temporary database name (default: test_todo_tmp): ", }, - "test_install_extra_modules": { + "Extra modules to install (comma-separated, empty for none): ": { "fr": "Modules supplémentaires à installer (séparés par des virgules, vide pour aucun) : ", "en": "Extra modules to install (comma-separated, empty for none): ", }, - "test_log_level": { + "Log level (default: test): ": { "fr": "Niveau de log (défaut: test) : ", "en": "Log level (default: test): ", }, - "test_creating_db": { + "Creating temporary database": { "fr": "Création de la base de données temporaire", "en": "Creating temporary database", }, - "test_installing_modules": { + "Installing modules": { "fr": "Installation des modules", "en": "Installing modules", }, - "test_running": { + "Running tests": { "fr": "Exécution des tests", "en": "Running tests", }, - "test_cleaning_db": { + "Cleaning up temporary database": { "fr": "Suppression de la base de données temporaire", "en": "Cleaning up temporary database", }, - "test_keep_db": { + "Keep the temporary database? (y/N): ": { "fr": "Conserver la base de données temporaire? (o/N) : ", "en": "Keep the temporary database? (y/N): ", }, - "test_db_kept": { + "Database kept": { "fr": "Base de données conservée", "en": "Database kept", }, - "test_success": { + "Tests completed successfully!": { "fr": "Tests terminés avec succès!", "en": "Tests completed successfully!", }, - "test_failed": { + "Tests failed with return code": { "fr": "Les tests ont échoué avec le code de retour", "en": "Tests failed with return code", }, - "test_module_required": { + "Module name is required!": { "fr": "Le nom du module est requis!", "en": "Module name is required!", }, # Git section - "menu_git": { + "Git - Git tools": { "fr": "Git - Outils Git", "en": "Git - Git tools", }, - "git_manage": { + "Git management tools!": { "fr": "Outils de gestion Git!", "en": "Git management tools!", }, - "git_local_server": { + "Local git server": { "fr": "Serveur git local", "en": "Local git server", }, - "git_repo_manage": { + "Manage local git repository server!": { "fr": "Gérer le serveur de dépôts git local!", "en": "Manage local git repository server!", }, - "git_repo_deploy_local": { + "Deploy a local git server (~/.git-server)": { "fr": "Déployer un serveur git local (~/.git-server)", "en": "Deploy a local git server (~/.git-server)", }, - "git_repo_deploy_production": { + "Deploy a production git server (/srv/git, root required)": { "fr": "Déployer un serveur git production (/srv/git, root requis)", "en": "Deploy a production git server (/srv/git, root required)", }, - "git_repo_deploy_starting": { + "Starting git server deployment...": { "fr": "Démarrage du déploiement du serveur git...", "en": "Starting git server deployment...", }, - "git_mode_local": { + "Local mode (~/.git-server)": { "fr": "Mode local (~/.git-server)", "en": "Local mode (~/.git-server)", }, - "git_mode_production": { + "Production mode (/srv/git, root required)": { "fr": "Mode production (/srv/git, root requis)", "en": "Production mode (/srv/git, root required)", }, - "git_action_all": { + "Run all (init + remote + push + serve)": { "fr": "Tout exécuter (init + remote + push + serve)", "en": "Run all (init + remote + push + serve)", }, - "git_action_init": { + "Init - Create bare repos": { "fr": "Init - Créer les bare repos", "en": "Init - Create bare repos", }, - "git_action_remote": { + "Remote - Add local remotes": { "fr": "Remote - Ajouter les remotes locaux", "en": "Remote - Add local remotes", }, - "git_action_push": { + "Push - Push to local server": { "fr": "Push - Pousser vers le serveur local", "en": "Push - Push to local server", }, - "git_action_serve": { + "Serve - Start git daemon": { "fr": "Serve - Démarrer le daemon git", "en": "Serve - Start git daemon", }, # Git remote add - "git_add_remote": { + "Add a remote to a local repository": { "fr": "Ajouter un remote vers un dépôt local", "en": "Add a remote to a local repository", }, - "git_add_remote_name_prompt": { + "Remote name (default: localhost): ": { "fr": "Nom du remote (défaut: localhost) : ", "en": "Remote name (default: localhost): ", }, - "git_add_remote_url_prompt": { + "Repository address (e.g.: git://192.168.1.100/my-repo.git): ": { "fr": "Adresse du dépôt (ex: git://192.168.1.100/mon-repo.git) : ", "en": "Repository address (e.g.: git://192.168.1.100/my-repo.git): ", }, - "git_add_remote_url_required": { + "Repository address is required!": { "fr": "L'adresse du dépôt est requise!", "en": "Repository address is required!", }, - "git_add_remote_success": { + "Remote added successfully!": { "fr": "Remote ajouté avec succès!", "en": "Remote added successfully!", }, - "git_add_remote_error": { + "Error adding remote: ": { "fr": "Erreur lors de l'ajout du remote : ", "en": "Error adding remote: ", }, # Git config vim - "git_config_vim": { + "Configure git local editor to vim": { "fr": "Configuration git local par vim", "en": "Configure git local editor to vim", }, - "git_config_vim_success": { + "Git editor configured to vim successfully!": { "fr": "Éditeur git configuré sur vim avec succès!", "en": "Git editor configured to vim successfully!", }, - "git_config_vim_error": { + "Error during configuration: ": { "fr": "Erreur lors de la configuration : ", "en": "Error during configuration: ", }, # GPT code - Claude automation - "gpt_code_claude_add_automation": { + "Add an automation with Claude in todo.py": { "fr": "Ajouter une automatisation avec Claude dans todo.py", "en": "Add an automation with Claude in todo.py", }, - "gpt_code_claude_add_automation_prompt": { + "Description of the command to add: ": { "fr": "Description de la commande à ajouter : ", "en": "Description of the command to add: ", }, - "gpt_code_claude_add_automation_cmd_prompt": { + "Bash command to execute: ": { "fr": "Commande bash à exécuter : ", "en": "Bash command to execute: ", }, - "gpt_code_claude_add_automation_section_prompt": { + "Menu section (git/code/config/network/process): ": { "fr": "Section du menu (git/code/config/network/process) : ", "en": "Menu section (git/code/config/network/process): ", }, - "gpt_code_claude_add_automation_success": { + "Automation added successfully in todo.json!": { "fr": "Automatisation ajoutée avec succès dans todo.json!", "en": "Automation added successfully in todo.json!", }, - "gpt_code_claude_add_automation_error": { + "Error adding automation: ": { "fr": "Erreur lors de l'ajout de l'automatisation : ", "en": "Error adding automation: ", }, # Language selection - "lang_prompt": { + "Choose language / Choisir la langue": { "fr": "Choisir la langue / Choose language", "en": "Choose language / Choisir la langue", }, - "lang_french": { + "French": { "fr": "Francais", "en": "French", }, - "lang_english": { + "English": { "fr": "Anglais", "en": "English", }, - "lang_changed": { + "Language changed to: English": { "fr": "Langue changée pour : Francais", "en": "Language changed to: English", }, - "execution_time": { + "TODO execution time": { "fr": "Temps d'exécution TODO", "en": "TODO execution time", }, - "keyboard_interrupt": { + "Keyboard interrupt": { "fr": "Interruption clavier", "en": "Keyboard interrupt", }, # GPT code section - "menu_gpt_code": { + "GPT code - AI assistant tools": { "fr": "GPT code - Outils d'assistant IA", "en": "GPT code - AI assistant tools", }, - "gpt_code_manage": { + "AI assistant tools for development!": { "fr": "Outils d'assistant IA pour le développement!", "en": "AI assistant tools for development!", }, - "gpt_code_claude_configs": { + "Configure Claude Code configurations": { "fr": "Configurer les configurations Claude Code", "en": "Configure Claude Code configurations", }, - "gpt_code_claude_commit": { + "Commit - OCA/Odoo commit command": { "fr": "Commit - Commande de commit OCA/Odoo", "en": "Commit - OCA/Odoo commit command", }, - "gpt_code_claude_todo_add_command": { + "Todo Add Command - Add a command to todo.py menu": { "fr": "Todo Add Command - Ajouter une commande au menu todo.py", "en": "Todo Add Command - Add a command to todo.py menu", }, - "gpt_code_enter_name": { + "Enter your full name: ": { "fr": "Entrez votre nom complet : ", "en": "Enter your full name: ", }, - "gpt_code_enter_email": { + "Enter your email: ": { "fr": "Entrez votre courriel : ", "en": "Enter your email: ", }, - "gpt_code_claude_configs_manage": { + "Deploy Claude Code commands!": { "fr": "Déployer les commandes Claude Code!", "en": "Deploy Claude Code commands!", }, - "gpt_code_claude_list_commands": { + "Show installed custom commands": { "fr": "Afficher les commandes personnalisées installées", "en": "Show installed custom commands", }, - "gpt_code_claude_no_commands": { + "No custom commands found in ~/.claude/commands/": { "fr": "Aucune commande personnalisée trouvée dans ~/.claude/commands/", "en": "No custom commands found in ~/.claude/commands/", }, - "gpt_code_claude_list_header": { + "Claude Code custom commands:": { "fr": "Commandes personnalisées Claude Code :", "en": "Claude Code custom commands:", }, - "gpt_code_claude_list_total": { + "Total:": { "fr": "Total :", "en": "Total:", }, - "gpt_code_cmd_exists": { + "File already exists: ": { "fr": "Le fichier existe déjà : ", "en": "File already exists: ", }, - "gpt_code_cmd_overwrite": { + "Do you want to overwrite the file? (y/Y): ": { "fr": "Voulez-vous écraser le fichier? (y/Y) : ", "en": "Do you want to overwrite the file? (y/Y): ", }, - "gpt_code_cmd_nothing_to_do": { + "Nothing to do.": { "fr": "Rien à faire.", "en": "Nothing to do.", }, - "gpt_code_cmd_created": { + "File created successfully: ": { "fr": "Fichier créé avec succès : ", "en": "File created successfully: ", }, - "gpt_code_cmd_error": { - "fr": "Erreur lors de la création du fichier : ", - "en": "Error creating file: ", - }, - "gpt_code_commit_exists": { - "fr": "Le fichier ~/.claude/commands/commit.md existe déjà. Aucune action effectuée.", - "en": "File ~/.claude/commands/commit.md already exists. No action taken.", - }, - "gpt_code_commit_created": { - "fr": "Fichier ~/.claude/commands/commit.md créé avec succès!", - "en": "File ~/.claude/commands/commit.md created successfully!", - }, - "gpt_code_commit_error": { + "Error creating file: ": { "fr": "Erreur lors de la création du fichier : ", "en": "Error creating file: ", },