From 7a79a8bbf75ae4fe2816302a4802b76c913f9412 Mon Sep 17 00:00:00 2001 From: pycook Date: Mon, 25 Dec 2023 21:51:44 +0800 Subject: [PATCH] feat(api): i18n feat(api): i18n --- .gitignore | 3 +- cmdb-api/Pipfile | 2 + cmdb-api/api/app.py | 12 +- cmdb-api/api/commands/common.py | 39 +- cmdb-api/api/extensions.py | 2 + cmdb-api/api/lib/cmdb/resp_format.py | 203 ++++--- cmdb-api/api/lib/perm/acl/resp_format.py | 68 ++- cmdb-api/api/lib/resp_format.py | 41 +- .../translations/zh/LC_MESSAGES/messages.mo | Bin 0 -> 12036 bytes .../translations/zh/LC_MESSAGES/messages.po | 564 ++++++++++++++++++ cmdb-api/babel.cfg | 1 + cmdb-api/requirements.txt | 1 + 12 files changed, 797 insertions(+), 139 deletions(-) create mode 100644 cmdb-api/api/translations/zh/LC_MESSAGES/messages.mo create mode 100644 cmdb-api/api/translations/zh/LC_MESSAGES/messages.po create mode 100644 cmdb-api/babel.cfg diff --git a/.gitignore b/.gitignore index 6c63d75..e43370d 100755 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,8 @@ cmdb-api/api/uploaded_files cmdb-api/migrations/versions # Translations -*.mo +#*.mo +messages.pot # Mr Developer .mr.developer.cfg diff --git a/cmdb-api/Pipfile b/cmdb-api/Pipfile index fb2e52e..46e4b40 100644 --- a/cmdb-api/Pipfile +++ b/cmdb-api/Pipfile @@ -27,6 +27,8 @@ Flask-Cors = ">=3.0.8" ldap3 = "==2.9.1" pycryptodome = "==3.12.0" cryptography = ">=41.0.2" +# i18n +flask-babel = "==4.0.0" # Caching Flask-Caching = ">=1.0.0" # Environment variable parsing diff --git a/cmdb-api/api/app.py b/cmdb-api/api/app.py index 6c9d15f..b6857ba 100644 --- a/cmdb-api/api/app.py +++ b/cmdb-api/api/app.py @@ -12,12 +12,14 @@ from pathlib import Path from flask import Flask from flask import jsonify from flask import make_response +from flask import request from flask.blueprints import Blueprint from flask.cli import click from flask.json.provider import DefaultJSONProvider +from flask_babel.speaklater import LazyString import api.views.entry -from api.extensions import (bcrypt, cache, celery, cors, db, es, login_manager, migrate, rd) +from api.extensions import (bcrypt, babel, cache, celery, cors, db, es, login_manager, migrate, rd) from api.extensions import inner_secrets from api.lib.perm.authentication.cas import CAS from api.lib.perm.authentication.oauth2 import OAuth2 @@ -72,7 +74,7 @@ class ReverseProxy(object): class MyJSONEncoder(DefaultJSONProvider): def default(self, o): - if isinstance(o, (decimal.Decimal, datetime.date, datetime.time)): + if isinstance(o, (decimal.Decimal, datetime.date, datetime.time, LazyString)): return str(o) if isinstance(o, datetime.datetime): @@ -117,7 +119,13 @@ def configure_upload_dir(app): def register_extensions(app): """Register Flask extensions.""" + + def get_locale(): + accept_languages = app.config.get('ACCEPT_LANGUAGES', ['en', 'zh']) + return request.accept_languages.best_match(accept_languages) + bcrypt.init_app(app) + babel.init_app(app, locale_selector=get_locale) cache.init_app(app) db.init_app(app) cors.init_app(app) diff --git a/cmdb-api/api/commands/common.py b/cmdb-api/api/commands/common.py index 6313ef6..7d9029f 100644 --- a/cmdb-api/api/commands/common.py +++ b/cmdb-api/api/commands/common.py @@ -5,9 +5,7 @@ from glob import glob from subprocess import call import click -from flask import current_app from flask.cli import with_appcontext -from werkzeug.exceptions import MethodNotAllowed, NotFound from api.extensions import db @@ -90,3 +88,40 @@ def db_setup(): """create tables """ db.create_all() + + +@click.group() +def translate(): + """Translation and localization commands.""" + + +@translate.command() +@click.argument('lang') +def init(lang): + """Initialize a new language.""" + + if os.system('pybabel extract -F babel.cfg -k _l -o messages.pot .'): + raise RuntimeError('extract command failed') + if os.system( + 'pybabel init -i messages.pot -d api/translations -l ' + lang): + raise RuntimeError('init command failed') + os.remove('messages.pot') + + +@translate.command() +def update(): + """Update all languages.""" + + if os.system('pybabel extract -F babel.cfg -k _l -o messages.pot .'): + raise RuntimeError('extract command failed') + if os.system('pybabel update -i messages.pot -d api/translations'): + raise RuntimeError('update command failed') + os.remove('messages.pot') + + +@translate.command() +def compile(): + """Compile all languages.""" + + if os.system('pybabel compile -d api/translations'): + raise RuntimeError('compile command failed') diff --git a/cmdb-api/api/extensions.py b/cmdb-api/api/extensions.py index 2c3ff5f..96b9ac6 100644 --- a/cmdb-api/api/extensions.py +++ b/cmdb-api/api/extensions.py @@ -2,6 +2,7 @@ from celery import Celery +from flask_babel import Babel from flask_bcrypt import Bcrypt from flask_caching import Cache from flask_cors import CORS @@ -14,6 +15,7 @@ from api.lib.utils import ESHandler from api.lib.utils import RedisHandler bcrypt = Bcrypt() +babel = Babel() login_manager = LoginManager() db = SQLAlchemy(session_options={"autoflush": False}) migrate = Migrate() diff --git a/cmdb-api/api/lib/cmdb/resp_format.py b/cmdb-api/api/lib/cmdb/resp_format.py index 12a532f..320deb3 100644 --- a/cmdb-api/api/lib/cmdb/resp_format.py +++ b/cmdb-api/api/lib/cmdb/resp_format.py @@ -1,103 +1,138 @@ # -*- coding:utf-8 -*- +from flask_babel import lazy_gettext as _l + from api.lib.resp_format import CommonErrFormat class ErrFormat(CommonErrFormat): - ci_type_config = "模型配置" + ci_type_config = _l("CI Model") # 模型配置 - invalid_relation_type = "无效的关系类型: {}" - ci_type_not_found = "模型不存在!" - argument_attributes_must_be_list = "参数 attributes 类型必须是列表" - argument_file_not_found = "文件似乎并未上传" + invalid_relation_type = _l("Invalid relation type: {}") # 无效的关系类型: {} + ci_type_not_found = _l("CIType is not found") # 模型不存在! - attribute_not_found = "属性 {} 不存在!" - attribute_is_unique_id = "该属性是模型的唯一标识,不能被删除!" - attribute_is_ref_by_type = "该属性被模型 {} 引用, 不能删除!" - attribute_value_type_cannot_change = "属性的值类型不允许修改!" - attribute_list_value_cannot_change = "多值不被允许修改!" - attribute_index_cannot_change = "修改索引 非管理员不被允许!" - attribute_index_change_failed = "索引切换失败!" - invalid_choice_values = "预定义值的类型不对!" - attribute_name_duplicate = "重复的属性名 {}" - add_attribute_failed = "创建属性 {} 失败!" - update_attribute_failed = "修改属性 {} 失败!" - cannot_edit_attribute = "您没有权限修改该属性!" - cannot_delete_attribute = "目前只允许 属性创建人、管理员 删除属性!" - attribute_name_cannot_be_builtin = "属性字段名不能是内置字段: id, _id, ci_id, type, _type, ci_type" - attribute_choice_other_invalid = "预定义值: 其他模型请求参数不合法!" + # 参数 attributes 类型必须是列表 + argument_attributes_must_be_list = _l("The type of parameter attributes must be a list") + argument_file_not_found = _l("The file doesn't seem to be uploaded") # 文件似乎并未上传 - ci_not_found = "CI {} 不存在" - unique_constraint = "多属性联合唯一校验不通过: {}" - unique_value_not_found = "模型的主键 {} 不存在!" - unique_key_required = "主键字段 {} 缺失" - ci_is_already_existed = "CI 已经存在!" - relation_constraint = "关系约束: {}, 校验失败 " - m2m_relation_constraint = "多对多关系 限制: 模型 {} <-> {} 已经存在多对多关系!" - relation_not_found = "CI关系: {} 不存在" - ci_search_Parentheses_invalid = "搜索表达式里小括号前不支持: 或、非" + attribute_not_found = _l("Attribute {} does not exist!") # 属性 {} 不存在! + attribute_is_unique_id = _l( + "This attribute is the unique identifier of the model and cannot be deleted!") # 该属性是模型的唯一标识,不能被删除! + attribute_is_ref_by_type = _l( + "This attribute is referenced by model {} and cannot be deleted!") # 该属性被模型 {} 引用, 不能删除! + attribute_value_type_cannot_change = _l( + "The value type of the attribute is not allowed to be modified!") # 属性的值类型不允许修改! + attribute_list_value_cannot_change = _l("Multiple values are not allowed to be modified!") # 多值不被允许修改! + # 修改索引 非管理员不被允许! + attribute_index_cannot_change = _l("Modifying the index is not allowed for non-administrators!") + attribute_index_change_failed = _l("Index switching failed!") # 索引切换失败! + invalid_choice_values = _l("The predefined value is of the wrong type!") # 预定义值的类型不对! + attribute_name_duplicate = _l("Duplicate attribute name {}") # 重复的属性名 {} + add_attribute_failed = _l("Failed to create attribute {}!") # 创建属性 {} 失败! + update_attribute_failed = _l("Modify attribute {} failed!") # 修改属性 {} 失败! + cannot_edit_attribute = _l("You do not have permission to modify this attribute!") # 您没有权限修改该属性! + cannot_delete_attribute = _l( + "Only creators and administrators are allowed to delete attributes!") # 目前只允许 属性创建人、管理员 删除属性! + # 属性字段名不能是内置字段: id, _id, ci_id, type, _type, ci_type + attribute_name_cannot_be_builtin = _l( + "Attribute field names cannot be built-in fields: id, _id, ci_id, type, _type, ci_type") + attribute_choice_other_invalid = _l( + "Predefined value: Other model request parameters are illegal!") # 预定义值: 其他模型请求参数不合法! - ci_type_not_found2 = "模型 {} 不存在" - ci_type_is_already_existed = "模型 {} 已经存在" - unique_key_not_define = "主键未定义或者已被删除" - only_owner_can_delete = "只有创建人才能删除它!" - ci_exists_and_cannot_delete_type = "因为CI已经存在,不能删除模型" - ci_relation_view_exists_and_cannot_delete_type = "因为关系视图 {} 引用了该模型,不能删除模型" - ci_type_group_not_found = "模型分组 {} 不存在" - ci_type_group_exists = "模型分组 {} 已经存在" - ci_type_relation_not_found = "模型关系 {} 不存在" - ci_type_attribute_group_duplicate = "属性分组 {} 已存在" - ci_type_attribute_group_not_found = "属性分组 {} 不存在" - ci_type_group_attribute_not_found = "属性组<{0}> - 属性<{1}> 不存在" - unique_constraint_duplicate = "唯一约束已经存在!" - unique_constraint_invalid = "唯一约束的属性不能是 JSON 和 多值" - ci_type_trigger_duplicate = "重复的触发器" - ci_type_trigger_not_found = "触发器 {} 不存在" + ci_not_found = _l("CI {} does not exist") # CI {} 不存在 + unique_constraint = _l("Multiple attribute joint unique verification failed: {}") # 多属性联合唯一校验不通过: {} + unique_value_not_found = _l("The model's primary key {} does not exist!") # 模型的主键 {} 不存在! + unique_key_required = _l("Primary key {} is missing") # 主键字段 {} 缺失 + ci_is_already_existed = _l("CI already exists!") # CI 已经存在! + relation_constraint = _l("Relationship constraint: {}, verification failed") # 关系约束: {}, 校验失败 + # 多对多关系 限制: 模型 {} <-> {} 已经存在多对多关系! + m2m_relation_constraint = _l( + "Many-to-many relationship constraint: Model {} <-> {} already has a many-to-many relationship!") - record_not_found = "操作记录 {} 不存在" - cannot_delete_unique = "不能删除唯一标识" - cannot_delete_default_order_attr = "不能删除默认排序的属性" + relation_not_found = _l("CI relationship: {} does not exist") # CI关系: {} 不存在 - preference_relation_view_node_required = "没有选择节点" - preference_search_option_not_found = "该搜索选项不存在!" - preference_search_option_exists = "该搜索选项命名重复!" + # 搜索表达式里小括号前不支持: 或、非 + ci_search_Parentheses_invalid = _l("In search expressions, not supported before parentheses: or, not") - relation_type_exists = "关系类型 {} 已经存在" - relation_type_not_found = "关系类型 {} 不存在" + ci_type_not_found2 = _l("Model {} does not exist") # 模型 {} 不存在 + ci_type_is_already_existed = _l("Model {} already exists") # 模型 {} 已经存在 + unique_key_not_define = _l("The primary key is undefined or has been deleted") # 主键未定义或者已被删除 + only_owner_can_delete = _l("Only the creator can delete it!") # 只有创建人才能删除它! + ci_exists_and_cannot_delete_type = _l( + "The model cannot be deleted because the CI already exists") # 因为CI已经存在,不能删除模型 - attribute_value_invalid = "无效的属性值: {}" - attribute_value_invalid2 = "{} 无效的值: {}" - not_in_choice_values = "{} 不在预定义值里" - attribute_value_unique_required = "属性 {} 的值必须是唯一的, 当前值 {} 已存在" - attribute_value_required = "属性 {} 值必须存在" - attribute_value_unknown_error = "新增或者修改属性值未知错误: {}" + # 因为关系视图 {} 引用了该模型,不能删除模型 + ci_relation_view_exists_and_cannot_delete_type = _l( + "The model cannot be deleted because the model is referenced by the relational view {}") + ci_type_group_not_found = _l("Model group {} does not exist") # 模型分组 {} 不存在 + ci_type_group_exists = _l("Model group {} already exists") # 模型分组 {} 已经存在 + ci_type_relation_not_found = _l("Model relationship {} does not exist") # 模型关系 {} 不存在 + ci_type_attribute_group_duplicate = _l("Attribute group {} already exists") # 属性分组 {} 已存在 + ci_type_attribute_group_not_found = _l("Attribute group {} does not exist") # 属性分组 {} 不存在 + # 属性组<{0}> - 属性<{1}> 不存在 + ci_type_group_attribute_not_found = _l("Attribute group <{0}> - attribute <{1}> does not exist") + unique_constraint_duplicate = _l("The unique constraint already exists!") # 唯一约束已经存在! + # 唯一约束的属性不能是 JSON 和 多值 + unique_constraint_invalid = _l("Uniquely constrained attributes cannot be JSON and multi-valued") + ci_type_trigger_duplicate = _l("Duplicated trigger") # 重复的触发器 + ci_type_trigger_not_found = _l("Trigger {} does not exist") # 触发器 {} 不存在 - custom_name_duplicate = "订制名重复" + record_not_found = _l("Operation record {} does not exist") # 操作记录 {} 不存在 + cannot_delete_unique = _l("Unique identifier cannot be deleted") # 不能删除唯一标识 + cannot_delete_default_order_attr = _l("Cannot delete default sorted attributes") # 不能删除默认排序的属性 - limit_ci_type = "模型数超过限制: {}" - limit_ci = "CI数超过限制: {}" + preference_relation_view_node_required = _l("No node selected") # 没有选择节点 + preference_search_option_not_found = _l("This search option does not exist!") # 该搜索选项不存在! + preference_search_option_exists = _l("This search option has a duplicate name!") # 该搜索选项命名重复! - adr_duplicate = "自动发现规则: {} 已经存在!" - adr_not_found = "自动发现规则: {} 不存在!" - adr_referenced = "该自动发现规则被模型引用, 不能删除!" - ad_duplicate = "自动发现规则的应用不能重复定义!" - ad_not_found = "您要修改的自动发现: {} 不存在!" - ad_not_unique_key = "属性字段没有包括唯一标识: {}" - adc_not_found = "自动发现的实例不存在!" - adt_not_found = "模型并未关联该自动发现!" - adt_secret_no_permission = "只有创建人才能修改Secret!" - cannot_delete_adt = "该规则已经有自动发现的实例, 不能被删除!" - adr_default_ref_once = "该默认的自动发现规则 已经被模型 {} 引用!" - adr_unique_key_required = "unique_key方法必须返回非空字符串!" - adr_plugin_attributes_list_required = "attributes方法必须返回的是list" - adr_plugin_attributes_list_no_empty = "attributes方法返回的list不能为空!" - adt_target_all_no_permission = "只有管理员才可以定义执行机器为: 所有节点!" - adt_target_expr_no_permission = "执行机器权限检查不通过: {}" + relation_type_exists = _l("Relationship type {} already exists") # 关系类型 {} 已经存在 + relation_type_not_found = _l("Relationship type {} does not exist") # 关系类型 {} 不存在 - ci_filter_name_cannot_be_empty = "CI过滤授权 必须命名!" - ci_filter_perm_cannot_or_query = "CI过滤授权 暂时不支持 或 查询" - ci_filter_perm_attr_no_permission = "您没有属性 {} 的操作权限!" - ci_filter_perm_ci_no_permission = "您没有该CI的操作权限!" + attribute_value_invalid = _l("Invalid attribute value: {}") # 无效的属性值: {} + attribute_value_invalid2 = _l("{} Invalid value: {}") # {} 无效的值: {} + not_in_choice_values = _l("{} is not in the predefined values") # {} 不在预定义值里 + # 属性 {} 的值必须是唯一的, 当前值 {} 已存在 + attribute_value_unique_required = _l("The value of attribute {} must be unique, {} already exists") + attribute_value_required = _l("Attribute {} value must exist") # 属性 {} 值必须存在 - password_save_failed = "保存密码失败: {}" - password_load_failed = "获取密码失败: {}" + # 新增或者修改属性值未知错误: {} + attribute_value_unknown_error = _l("Unknown error when adding or modifying attribute value: {}") + + custom_name_duplicate = _l("Duplicate custom name") # 订制名重复 + + limit_ci_type = _l("Number of models exceeds limit: {}") # 模型数超过限制: {} + limit_ci = _l("The number of CIs exceeds the limit: {}") # CI数超过限制: {} + + adr_duplicate = _l("Auto-discovery rule: {} already exists!") # 自动发现规则: {} 已经存在! + adr_not_found = _l("Auto-discovery rule: {} does not exist!") # 自动发现规则: {} 不存在! + # 该自动发现规则被模型引用, 不能删除! + adr_referenced = _l("This auto-discovery rule is referenced by the model and cannot be deleted!") + # 自动发现规则的应用不能重复定义! + ad_duplicate = _l("The application of auto-discovery rules cannot be defined repeatedly!") + ad_not_found = _l("The auto-discovery you want to modify: {} does not exist!") # 您要修改的自动发现: {} 不存在! + ad_not_unique_key = _l("Attribute does not include unique identifier: {}") # 属性字段没有包括唯一标识: {} + adc_not_found = _l("The auto-discovery instance does not exist!") # 自动发现的实例不存在! + adt_not_found = _l("The model is not associated with this auto-discovery!") # 模型并未关联该自动发现! + adt_secret_no_permission = _l("Only the creator can modify the Secret!") # 只有创建人才能修改Secret! + # 该规则已经有自动发现的实例, 不能被删除! + cannot_delete_adt = _l("This rule already has auto-discovery instances and cannot be deleted!") + # 该默认的自动发现规则 已经被模型 {} 引用! + adr_default_ref_once = _l("The default auto-discovery rule is already referenced by model {}!") + # unique_key方法必须返回非空字符串! + adr_unique_key_required = _l("The unique_key method must return a non-empty string!") + adr_plugin_attributes_list_required = _l("The attributes method must return a list") # attributes方法必须返回的是list + # attributes方法返回的list不能为空! + adr_plugin_attributes_list_no_empty = _l("The list returned by the attributes method cannot be empty!") + # 只有管理员才可以定义执行机器为: 所有节点! + adt_target_all_no_permission = _l("Only administrators can define execution targets as: all nodes!") + adt_target_expr_no_permission = _l("Execute targets permission check failed: {}") # 执行机器权限检查不通过: {} + + ci_filter_name_cannot_be_empty = _l("CI filter authorization must be named!") # CI过滤授权 必须命名! + ci_filter_perm_cannot_or_query = _l( + "CI filter authorization is currently not supported or query") # CI过滤授权 暂时不支持 或 查询 + # 您没有属性 {} 的操作权限! + ci_filter_perm_attr_no_permission = _l("You do not have permission to operate attribute {}!") + ci_filter_perm_ci_no_permission = _l("You do not have permission to operate this CI!") # 您没有该CI的操作权限! + + password_save_failed = _l("Failed to save password: {}") # 保存密码失败: {} + password_load_failed = _l("Failed to get password: {}") # 获取密码失败: {} diff --git a/cmdb-api/api/lib/perm/acl/resp_format.py b/cmdb-api/api/lib/perm/acl/resp_format.py index 9ea6c5b..8304f87 100644 --- a/cmdb-api/api/lib/perm/acl/resp_format.py +++ b/cmdb-api/api/lib/perm/acl/resp_format.py @@ -1,46 +1,50 @@ # -*- coding:utf-8 -*- +from flask_babel import lazy_gettext as _l + from api.lib.resp_format import CommonErrFormat class ErrFormat(CommonErrFormat): - login_succeed = "登录成功" - ldap_connection_failed = "连接LDAP服务失败" - invalid_password = "密码验证失败" - auth_only_with_app_token_failed = "应用 Token验证失败" - session_invalid = "您不是应用管理员 或者 session失效(尝试一下退出重新登录)" + login_succeed = _l("login successful") # 登录成功 + ldap_connection_failed = _l("Failed to connect to LDAP service") # 连接LDAP服务失败 + invalid_password = _l("Password verification failed") # 密码验证失败 + auth_only_with_app_token_failed = _l("Application Token verification failed") # 应用 Token验证失败 + # 您不是应用管理员 或者 session失效(尝试一下退出重新登录) + session_invalid = _l( + "You are not the application administrator or the session has expired (try logging out and logging in again)") - resource_type_not_found = "资源类型 {} 不存在!" - resource_type_exists = "资源类型 {} 已经存在!" - resource_type_cannot_delete = "因为该类型下有资源的存在, 不能删除!" + resource_type_not_found = _l("Resource type {} does not exist!") # 资源类型 {} 不存在! + resource_type_exists = _l("Resource type {} already exists!") # 资源类型 {} 已经存在! + # 因为该类型下有资源的存在, 不能删除! + resource_type_cannot_delete = _l("Because there are resources under this type, they cannot be deleted!") - user_not_found = "用户 {} 不存在!" - user_exists = "用户 {} 已经存在!" - role_not_found = "角色 {} 不存在!" - role_exists = "角色 {} 已经存在!" - global_role_not_found = "全局角色 {} 不存在!" - global_role_exists = "全局角色 {} 已经存在!" + user_not_found = _l("User {} does not exist!") # 用户 {} 不存在! + user_exists = _l("User {} already exists!") # 用户 {} 已经存在! + role_not_found = _l("Role {} does not exist!") # 角色 {} 不存在! + role_exists = _l("Role {} already exists!") # 角色 {} 已经存在! + global_role_not_found = _l("Global role {} does not exist!") # 全局角色 {} 不存在! + global_role_exists = _l("Global role {} already exists!") # 全局角色 {} 已经存在! - resource_no_permission = "您没有资源: {} 的 {} 权限" - admin_required = "需要管理员权限" - role_required = "需要角色: {}" - user_role_delete_invalid = "删除用户角色, 请在 用户管理 页面操作!" + resource_no_permission = _l("You do not have {} permission on resource: {}") # 您没有资源: {} 的 {} 权限 + admin_required = _l("Requires administrator permissions") # 需要管理员权限 + role_required = _l("Requires role: {}") # 需要角色: {} + # 删除用户角色, 请在 用户管理 页面操作! + user_role_delete_invalid = _l("To delete a user role, please operate on the User Management page!") - app_is_ready_existed = "应用 {} 已经存在" - app_not_found = "应用 {} 不存在!" - app_secret_invalid = "应用的Secret无效" + app_is_ready_existed = _l("Application {} already exists") # 应用 {} 已经存在 + app_not_found = _l("Application {} does not exist!") # 应用 {} 不存在! + app_secret_invalid = _l("The Secret is invalid") # 应用的Secret无效 - resource_not_found = "资源 {} 不存在!" - resource_exists = "资源 {} 已经存在!" + resource_not_found = _l("Resource {} does not exist!") # 资源 {} 不存在! + resource_exists = _l("Resource {} already exists!") # 资源 {} 已经存在! - resource_group_not_found = "资源组 {} 不存在!" - resource_group_exists = "资源组 {} 已经存在!" + resource_group_not_found = _l("Resource group {} does not exist!") # 资源组 {} 不存在! + resource_group_exists = _l("Resource group {} already exists!") # 资源组 {} 已经存在! - inheritance_dead_loop = "继承检测到了死循环" - role_relation_not_found = "角色关系 {} 不存在!" + inheritance_dead_loop = _l("Inheritance detected infinite loop") # 继承检测到了死循环 + role_relation_not_found = _l("Role relationship {} does not exist!") # 角色关系 {} 不存在! - trigger_not_found = "触发器 {} 不存在!" - trigger_exists = "触发器 {} 已经存在!" - trigger_disabled = "触发器 {} 已经被禁用!" - - invalid_password = "密码不正确!" + trigger_not_found = _l("Trigger {} does not exist!") # 触发器 {} 不存在! + trigger_exists = _l("Trigger {} already exists!") # 触发器 {} 已经存在! + trigger_disabled = _l("Trigger {} has been disabled!") # Trigger {} has been disabled! diff --git a/cmdb-api/api/lib/resp_format.py b/cmdb-api/api/lib/resp_format.py index 5a7c852..48eca6f 100644 --- a/cmdb-api/api/lib/resp_format.py +++ b/cmdb-api/api/lib/resp_format.py @@ -1,29 +1,34 @@ # -*- coding:utf-8 -*- +from flask_babel import lazy_gettext as _l + + class CommonErrFormat(object): - unauthorized = "未认证" - unknown_error = "未知错误" + unauthorized = _l("unauthorized") # 未认证 + unknown_error = _l("unknown error") # 未知错误 - invalid_request = "不合法的请求" - invalid_operation = "无效的操作" + invalid_request = _l("Illegal request") # 不合法的请求 + invalid_operation = _l("Invalid operation") # 无效的操作 - not_found = "不存在" + not_found = _l("does not exist") # 不存在 - circular_dependency_error = "存在循环依赖!" + circular_dependency_error = _l("There is a circular dependency!") # 存在循环依赖! - unknown_search_error = "未知搜索错误" + unknown_search_error = _l("Unknown search error") # 未知搜索错误 - invalid_json = "json格式似乎不正确了, 请仔细确认一下!" + # json格式似乎不正确了, 请仔细确认一下! + invalid_json = _l("The json format seems to be incorrect, please confirm carefully!") - datetime_argument_invalid = "参数 {} 格式不正确, 格式必须是: yyyy-mm-dd HH:MM:SS" + # 参数 {} 格式不正确, 格式必须是: yyyy-mm-dd HH:MM:SS + datetime_argument_invalid = _l("The format of parameter {} is incorrect, the format must be: yyyy-mm-dd HH:MM:SS") - argument_value_required = "参数 {} 的值不能为空!" - argument_required = "请求缺少参数 {}" - argument_invalid = "参数 {} 的值无效" - argument_str_length_limit = "参数 {} 的长度必须 <= {}" + argument_value_required = _l("The value of parameter {} cannot be empty!") # 参数 {} 的值不能为空! + argument_required = _l("The request is missing parameters {}") # 请求缺少参数 {} + argument_invalid = _l("Invalid value for parameter {}") # 参数 {} 的值无效 + argument_str_length_limit = _l("The length of parameter {} must be <= {}") # 参数 {} 的长度必须 <= {} - role_required = "角色 {} 才能操作!" - user_not_found = "用户 {} 不存在" - no_permission = "您没有资源: {} 的{}权限!" - no_permission2 = "您没有操作权限!" - no_permission_only_owner = "只有创建人或者管理员才有权限!" + role_required = _l("Role {} can only operate!") # 角色 {} 才能操作! + user_not_found = _l("User {} does not exist") # 用户 {} 不存在 + no_permission = _l("You do not have {} permission for resource: {}!") # 您没有资源: {} 的{}权限! + no_permission2 = _l("You do not have permission to operate!") # 您没有操作权限! + no_permission_only_owner = _l("Only the creator or administrator has permission!") # 只有创建人或者管理员才有权限! diff --git a/cmdb-api/api/translations/zh/LC_MESSAGES/messages.mo b/cmdb-api/api/translations/zh/LC_MESSAGES/messages.mo new file mode 100644 index 0000000000000000000000000000000000000000..a82f9bfa360be2aabbc18ba57bc57a99fe3b4aaf GIT binary patch literal 12036 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%0D)bk#fx{ z>VZ`#$W?$x930&X5{~gONP&;H#y3UbU?{sar5n14Jz39M;1bI%##d>>^ck1<$MDAWv(&2|{kbz{Q<>z=-08EYb+mUZtQ%v- zEz_sXcS~jJQf>vkzRfJ#YsPVX5MRc+C_8bEi-QC2qPHXQ{8jIRNt2;U*1t0c`SJGRPEbG;}`fc zc=L31Y%qB3nc%>Q)bhmHoqDas2u>Xe`;P~&Jsl3e5uP3j4{Qx~Yznu(8tfUFINKi{ z-clRctRf>#80_8&i`vHX;WHz_=1tY}!IKEf#HHGn7)B zP$t$y3!S`a+#}S+NQB9Pfy0ygUu-eL6GMtjl*L|{2CZJ|h(A+lJ!E9(XPo8`UBxf2x4TMZ4Y%2KNOco2!STBv4!?E*=!)H!cU8 zP6Vg=Ysa6gZ9T2Hq_Tu)X?UA8OR#$&e0?u^*GAq9Pi-*5-3O}QK2jSxQM+&<7$2P6 zvLiS-DETw^X0TPVM0>1FT=uX1k4+vtWI!K`?+pgFggcLDy;_Xw*zs`dMX|&i+k=6V z6Qi5M*T#YiFIRVs7~#{0!@UD_Q}>T6<&x#_shtz&52VPH%XKI!%3yFqxc8)JDopyv z^-d#r@!4SHocvT9Ok9EUkW@vckVjut)1le0DURbH$;C8r6j=3_i7n$d`s68svC%Kl z23f8%nYcI{?m5>S4tibN*~H}4;i2m8&A}7Tu(fvNm0;6jwc)dP8r4-a*B;x0U*nQD zL@|Xh6^%mJKc3#KPe6NBGAH}DhTC7NZQD@Ya4r%QgV)Y%BAjEZk{!X|%hZKLm~iXP zU~pt&>}W9j?8LdP>BOL#;D@dKQbrV4BILPY0tyyddQ(dtsDzjp9VNCB#-^?@ngTV| zu?Z!|CS@oX-gt@kTEY1HW+RJ%eYO5g$$4-@P@T+}M1^B*_+)T?Z`NHp5i_l7^2p;_ zd+gh02Aj@IjP29$r}ImPu6SJKom8f=$vsiK5$@ITQF4f+l`>ZyJr*8(UShu03=fMR zon>IG;5O2wd&!Q@EQF^B{Cw?^rpQI}4IMLor)2D>d69`2`$4OLIn){`c9W|`5 zm)O(ILHoVMNQQ7f+;@)JsykTi;-28SLu_QkP#+G{T!r88p@|E0+Qg#ah7Qw_>Mvm&H2A?#Yo&ciYpia~aA@!P3i`d?`Wn%2i#Q6Bcxn04zGvR@kC(dr0 z7(Yyo#U(a8JWd}#u<*4PszbvPh_axyLYb+*`+d%ouYS>9#XjLcFK9K%hKaE~)v?X6 zq#HAuF=R;U#>b+{Ie6}Z3L|AAgvGj=aO&Oqoi-jkD7|b*dm(NqXrz<9!F%)Dr>d>#Lc-2? z5Zg(Idw2Y?sBGY`sMe|ihN{vH)Idg1NI#cya`K79tg(UXb~H8T#GS#w(=>lW_YPfu z(iUvt(k1^HL%y3ehqtt*mqwYLtFIoLIC~l=sCFa@qXQ+eevBH&S!^|f^G``5=pR>B zug}EkP>8zK#`B4H6=Th`ZX4AH<5s3ilb$&yE*z}Au}@`6)FGR*p>d$ajhdDq*G`t> zQrCzi9ulLg1Jb_N8JMJ=PP-`%(sbI;(j!yJE{Cex5O2$#rsp*p_T?G6%`>AfN5!ahPFhruJ!dqqZDnjM%HgQ!4r~2T_v8`WO7EN_!ANxooV={ z;N-#D$X;CsC;R(@Eu(k~6{`Ekm^*G3ZhAJ;Ok%ewcg=EL4~>zmoC;UFdu(?t_TViiNH6AtVSwmmOar}lHtkL<4{{!hy2N3`O literal 0 HcmV?d00001 diff --git a/cmdb-api/api/translations/zh/LC_MESSAGES/messages.po b/cmdb-api/api/translations/zh/LC_MESSAGES/messages.po new file mode 100644 index 0000000..a4e8a9e --- /dev/null +++ b/cmdb-api/api/translations/zh/LC_MESSAGES/messages.po @@ -0,0 +1,564 @@ +# Chinese translations for PROJECT. +# Copyright (C) 2023 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2023-12-25 20:21+0800\n" +"PO-Revision-Date: 2023-12-25 20:21+0800\n" +"Last-Translator: FULL NAME \n" +"Language: zh\n" +"Language-Team: zh \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.13.1\n" + +#: api/lib/resp_format.py:7 +msgid "unauthorized" +msgstr "未认证" + +#: api/lib/resp_format.py:8 +msgid "unknown error" +msgstr "未知错误" + +#: api/lib/resp_format.py:10 +msgid "Illegal request" +msgstr "不合法的请求" + +#: api/lib/resp_format.py:11 +msgid "Invalid operation" +msgstr "无效的操作" + +#: api/lib/resp_format.py:13 +msgid "does not exist" +msgstr "不存在" + +#: api/lib/resp_format.py:15 +msgid "There is a circular dependency!" +msgstr "存在循环依赖!" + +#: api/lib/resp_format.py:17 +msgid "Unknown search error" +msgstr "未知搜索错误" + +#: api/lib/resp_format.py:20 +msgid "The json format seems to be incorrect, please confirm carefully!" +msgstr "# json格式似乎不正确了, 请仔细确认一下!" + +#: api/lib/resp_format.py:23 +msgid "" +"The format of parameter {} is incorrect, the format must be: yyyy-mm-dd " +"HH:MM:SS" +msgstr "参数 {} 格式不正确, 格式必须是: yyyy-mm-dd HH:MM:SS" + +#: api/lib/resp_format.py:25 +msgid "The value of parameter {} cannot be empty!" +msgstr "参数 {} 的值不能为空!" + +#: api/lib/resp_format.py:26 +msgid "The request is missing parameters {}" +msgstr "请求缺少参数 {}" + +#: api/lib/resp_format.py:27 +msgid "Invalid value for parameter {}" +msgstr "参数 {} 的值无效" + +#: api/lib/resp_format.py:28 +msgid "The length of parameter {} must be <= {}" +msgstr "参数 {} 的长度必须 <= {}" + +#: api/lib/resp_format.py:30 +msgid "Role {} can only operate!" +msgstr "角色 {} 才能操作!" + +#: api/lib/resp_format.py:31 +msgid "User {} does not exist" +msgstr "用户 {} 不存在" + +#: api/lib/resp_format.py:32 +msgid "You do not have {} permission for resource: {}!" +msgstr "您没有资源: {} 的{}权限!" + +#: api/lib/resp_format.py:33 +msgid "You do not have permission to operate!" +msgstr "您没有操作权限!" + +#: api/lib/resp_format.py:34 +msgid "Only the creator or administrator has permission!" +msgstr "只有创建人或者管理员才有权限!" + +#: api/lib/cmdb/resp_format.py:9 +msgid "CI Model" +msgstr "模型配置" + +#: api/lib/cmdb/resp_format.py:11 +msgid "Invalid relation type: {}" +msgstr "无效的关系类型: {}" + +#: api/lib/cmdb/resp_format.py:12 +msgid "CIType is not found" +msgstr "模型不存在!" + +#: api/lib/cmdb/resp_format.py:15 +msgid "The type of parameter attributes must be a list" +msgstr "参数 attributes 类型必须是列表" + +#: api/lib/cmdb/resp_format.py:16 +msgid "The file doesn't seem to be uploaded" +msgstr "文件似乎并未上传" + +#: api/lib/cmdb/resp_format.py:18 +msgid "Attribute {} does not exist!" +msgstr "属性 {} 不存在!" + +#: api/lib/cmdb/resp_format.py:19 +msgid "" +"This attribute is the unique identifier of the model and cannot be " +"deleted!" +msgstr "该属性是模型的唯一标识,不能被删除!" + +#: api/lib/cmdb/resp_format.py:21 +msgid "This attribute is referenced by model {} and cannot be deleted!" +msgstr "该属性被模型 {} 引用, 不能删除!" + +#: api/lib/cmdb/resp_format.py:23 +msgid "The value type of the attribute is not allowed to be modified!" +msgstr "属性的值类型不允许修改!" + +#: api/lib/cmdb/resp_format.py:25 +msgid "Multiple values are not allowed to be modified!" +msgstr "多值不被允许修改!" + +#: api/lib/cmdb/resp_format.py:27 +msgid "Modifying the index is not allowed for non-administrators!" +msgstr "修改索引 非管理员不被允许!" + +#: api/lib/cmdb/resp_format.py:28 +msgid "Index switching failed!" +msgstr "索引切换失败!" + +#: api/lib/cmdb/resp_format.py:29 +msgid "The predefined value is of the wrong type!" +msgstr "预定义值的类型不对!" + +#: api/lib/cmdb/resp_format.py:30 +msgid "Duplicate attribute name {}" +msgstr "重复的属性名 {}" + +#: api/lib/cmdb/resp_format.py:31 +msgid "Failed to create attribute {}!" +msgstr "创建属性 {} 失败!" + +#: api/lib/cmdb/resp_format.py:32 +msgid "Modify attribute {} failed!" +msgstr "修改属性 {} 失败!" + +#: api/lib/cmdb/resp_format.py:33 +msgid "You do not have permission to modify this attribute!" +msgstr "您没有权限修改该属性!" + +#: api/lib/cmdb/resp_format.py:34 +msgid "Only creators and administrators are allowed to delete attributes!" +msgstr "目前只允许 属性创建人、管理员 删除属性!" + +#: api/lib/cmdb/resp_format.py:37 +msgid "" +"Attribute field names cannot be built-in fields: id, _id, ci_id, type, " +"_type, ci_type" +msgstr "属性字段名不能是内置字段: id, _id, ci_id, type, _type, ci_type" + +#: api/lib/cmdb/resp_format.py:39 +msgid "Predefined value: Other model request parameters are illegal!" +msgstr "预定义值: 其他模型请求参数不合法!" + +#: api/lib/cmdb/resp_format.py:42 +msgid "CI {} does not exist" +msgstr "CI {} 不存在" + +#: api/lib/cmdb/resp_format.py:43 +msgid "Multiple attribute joint unique verification failed: {}" +msgstr "多属性联合唯一校验不通过: {}" + +#: api/lib/cmdb/resp_format.py:44 +msgid "The model's primary key {} does not exist!" +msgstr "模型的主键 {} 不存在!" + +#: api/lib/cmdb/resp_format.py:45 +msgid "Primary key {} is missing" +msgstr "主键字段 {} 缺失" + +#: api/lib/cmdb/resp_format.py:46 +msgid "CI already exists!" +msgstr "CI 已经存在!" + +#: api/lib/cmdb/resp_format.py:47 +msgid "Relationship constraint: {}, verification failed" +msgstr "关系约束: {}, 校验失败" + +#: api/lib/cmdb/resp_format.py:49 +msgid "" +"Many-to-many relationship constraint: Model {} <-> {} already has a many-" +"to-many relationship!" +msgstr "多对多关系 限制: 模型 {} <-> {} 已经存在多对多关系!" + +#: api/lib/cmdb/resp_format.py:52 +msgid "CI relationship: {} does not exist" +msgstr "CI关系: {} 不存在" + +#: api/lib/cmdb/resp_format.py:55 +msgid "In search expressions, not supported before parentheses: or, not" +msgstr "搜索表达式里小括号前不支持: 或、非" + +#: api/lib/cmdb/resp_format.py:57 +msgid "Model {} does not exist" +msgstr "模型 {} 不存在" + +#: api/lib/cmdb/resp_format.py:58 +msgid "Model {} already exists" +msgstr "模型 {} 已经存在" + +#: api/lib/cmdb/resp_format.py:59 +msgid "The primary key is undefined or has been deleted" +msgstr "主键未定义或者已被删除" + +#: api/lib/cmdb/resp_format.py:60 +msgid "Only the creator can delete it!" +msgstr "只有创建人才能删除它!" + +#: api/lib/cmdb/resp_format.py:61 +msgid "The model cannot be deleted because the CI already exists" +msgstr "因为CI已经存在,不能删除模型" + +#: api/lib/cmdb/resp_format.py:65 +msgid "" +"The model cannot be deleted because the model is referenced by the " +"relational view {}" +msgstr "因为关系视图 {} 引用了该模型,不能删除模型" + +#: api/lib/cmdb/resp_format.py:67 +msgid "Model group {} does not exist" +msgstr "模型分组 {} 不存在" + +#: api/lib/cmdb/resp_format.py:68 +msgid "Model group {} already exists" +msgstr "模型分组 {} 已经存在" + +#: api/lib/cmdb/resp_format.py:69 +msgid "Model relationship {} does not exist" +msgstr "模型关系 {} 不存在" + +#: api/lib/cmdb/resp_format.py:70 +msgid "Attribute group {} already exists" +msgstr "属性分组 {} 已存在" + +#: api/lib/cmdb/resp_format.py:71 +msgid "Attribute group {} does not exist" +msgstr "属性分组 {} 不存在" + +#: api/lib/cmdb/resp_format.py:73 +msgid "Attribute group <{0}> - attribute <{1}> does not exist" +msgstr "属性组<{0}> - 属性<{1}> 不存在" + +#: api/lib/cmdb/resp_format.py:74 +msgid "The unique constraint already exists!" +msgstr "唯一约束已经存在!" + +#: api/lib/cmdb/resp_format.py:76 +msgid "Uniquely constrained attributes cannot be JSON and multi-valued" +msgstr "唯一约束的属性不能是 JSON 和 多值" + +#: api/lib/cmdb/resp_format.py:77 +msgid "Duplicated trigger" +msgstr "重复的触发器" + +#: api/lib/cmdb/resp_format.py:78 +msgid "Trigger {} does not exist" +msgstr "触发器 {} 不存在" + +#: api/lib/cmdb/resp_format.py:80 +msgid "Operation record {} does not exist" +msgstr "操作记录 {} 不存在" + +#: api/lib/cmdb/resp_format.py:81 +msgid "Unique identifier cannot be deleted" +msgstr "不能删除唯一标识" + +#: api/lib/cmdb/resp_format.py:82 +msgid "Cannot delete default sorted attributes" +msgstr "不能删除默认排序的属性" + +#: api/lib/cmdb/resp_format.py:84 +msgid "No node selected" +msgstr "没有选择节点" + +#: api/lib/cmdb/resp_format.py:85 +msgid "This search option does not exist!" +msgstr "该搜索选项不存在!" + +#: api/lib/cmdb/resp_format.py:86 +msgid "This search option has a duplicate name!" +msgstr "该搜索选项命名重复!" + +#: api/lib/cmdb/resp_format.py:88 +msgid "Relationship type {} already exists" +msgstr "关系类型 {} 已经存在" + +#: api/lib/cmdb/resp_format.py:89 +msgid "Relationship type {} does not exist" +msgstr "关系类型 {} 不存在" + +#: api/lib/cmdb/resp_format.py:91 +msgid "Invalid attribute value: {}" +msgstr "无效的属性值: {}" + +#: api/lib/cmdb/resp_format.py:92 +msgid "{} Invalid value: {}" +msgstr "无效的值: {}" + +#: api/lib/cmdb/resp_format.py:93 +msgid "{} is not in the predefined values" +msgstr "{} 不在预定义值里" + +#: api/lib/cmdb/resp_format.py:95 +msgid "The value of attribute {} must be unique, {} already exists" +msgstr "属性 {} 的值必须是唯一的, 当前值 {} 已存在" + +#: api/lib/cmdb/resp_format.py:96 +msgid "Attribute {} value must exist" +msgstr "属性 {} 值必须存在" + +#: api/lib/cmdb/resp_format.py:99 +msgid "Unknown error when adding or modifying attribute value: {}" +msgstr "新增或者修改属性值未知错误: {}" + +#: api/lib/cmdb/resp_format.py:101 +msgid "Duplicate custom name" +msgstr "订制名重复" + +#: api/lib/cmdb/resp_format.py:103 +msgid "Number of models exceeds limit: {}" +msgstr "模型数超过限制: {}" + +#: api/lib/cmdb/resp_format.py:104 +msgid "The number of CIs exceeds the limit: {}" +msgstr "CI数超过限制: {}" + +#: api/lib/cmdb/resp_format.py:106 +msgid "Auto-discovery rule: {} already exists!" +msgstr "自动发现规则: {} 已经存在!" + +#: api/lib/cmdb/resp_format.py:107 +msgid "Auto-discovery rule: {} does not exist!" +msgstr "自动发现规则: {} 不存在!" + +#: api/lib/cmdb/resp_format.py:109 +msgid "This auto-discovery rule is referenced by the model and cannot be deleted!" +msgstr "该自动发现规则被模型引用, 不能删除!" + +#: api/lib/cmdb/resp_format.py:111 +msgid "The application of auto-discovery rules cannot be defined repeatedly!" +msgstr "自动发现规则的应用不能重复定义!" + +#: api/lib/cmdb/resp_format.py:112 +msgid "The auto-discovery you want to modify: {} does not exist!" +msgstr "您要修改的自动发现: {} 不存在!" + +#: api/lib/cmdb/resp_format.py:113 +msgid "Attribute does not include unique identifier: {}" +msgstr "属性字段没有包括唯一标识: {}" + +#: api/lib/cmdb/resp_format.py:114 +msgid "The auto-discovery instance does not exist!" +msgstr "自动发现的实例不存在!" + +#: api/lib/cmdb/resp_format.py:115 +msgid "The model is not associated with this auto-discovery!" +msgstr "模型并未关联该自动发现!" + +#: api/lib/cmdb/resp_format.py:116 +msgid "Only the creator can modify the Secret!" +msgstr "只有创建人才能修改Secret!" + +#: api/lib/cmdb/resp_format.py:118 +msgid "This rule already has auto-discovery instances and cannot be deleted!" +msgstr "该规则已经有自动发现的实例, 不能被删除!" + +#: api/lib/cmdb/resp_format.py:120 +msgid "The default auto-discovery rule is already referenced by model {}!" +msgstr "该默认的自动发现规则 已经被模型 {} 引用!" + +#: api/lib/cmdb/resp_format.py:122 +msgid "The unique_key method must return a non-empty string!" +msgstr "unique_key方法必须返回非空字符串!" + +#: api/lib/cmdb/resp_format.py:123 +msgid "The attributes method must return a list" +msgstr "attributes方法必须返回的是list" + +#: api/lib/cmdb/resp_format.py:125 +msgid "The list returned by the attributes method cannot be empty!" +msgstr "attributes方法返回的list不能为空!" + +#: api/lib/cmdb/resp_format.py:127 +msgid "Only administrators can define execution targets as: all nodes!" +msgstr "只有管理员才可以定义执行机器为: 所有节点!" + +#: api/lib/cmdb/resp_format.py:128 +msgid "Execute targets permission check failed: {}" +msgstr "执行机器权限检查不通过: {}" + +#: api/lib/cmdb/resp_format.py:130 +msgid "CI filter authorization must be named!" +msgstr "CI过滤授权 必须命名!" + +#: api/lib/cmdb/resp_format.py:131 +msgid "CI filter authorization is currently not supported or query" +msgstr "CI过滤授权 暂时不支持 或 查询" + +#: api/lib/cmdb/resp_format.py:134 +msgid "You do not have permission to operate attribute {}!" +msgstr "您没有属性 {} 的操作权限!" + +#: api/lib/cmdb/resp_format.py:135 +msgid "You do not have permission to operate this CI!" +msgstr "您没有该CI的操作权限!" + +#: api/lib/cmdb/resp_format.py:137 +msgid "Failed to save password: {}" +msgstr "保存密码失败: {}" + +#: api/lib/cmdb/resp_format.py:138 +msgid "Failed to get password: {}" +msgstr "获取密码失败: {}" + +#: api/lib/common_setting/employee.py:1349 +msgid "Not a valid date value." +msgstr "" + +#: api/lib/perm/acl/resp_format.py:9 +msgid "login successful" +msgstr "登录成功" + +#: api/lib/perm/acl/resp_format.py:10 +msgid "Failed to connect to LDAP service" +msgstr "连接LDAP服务失败" + +#: api/lib/perm/acl/resp_format.py:11 +msgid "Password verification failed" +msgstr "密码验证失败" + +#: api/lib/perm/acl/resp_format.py:12 +msgid "Application Token verification failed" +msgstr "应用 Token验证失败" + +#: api/lib/perm/acl/resp_format.py:14 +msgid "" +"You are not the application administrator or the session has expired (try" +" logging out and logging in again)" +msgstr "您不是应用管理员 或者 session失效(尝试一下退出重新登录)" + +#: api/lib/perm/acl/resp_format.py:17 +msgid "Resource type {} does not exist!" +msgstr "资源类型 {} 不存在!" + +#: api/lib/perm/acl/resp_format.py:18 +msgid "Resource type {} already exists!" +msgstr "资源类型 {} 已经存在!" + +#: api/lib/perm/acl/resp_format.py:20 +msgid "Because there are resources under this type, they cannot be deleted!" +msgstr "因为该类型下有资源的存在, 不能删除!" + +#: api/lib/perm/acl/resp_format.py:22 +msgid "User {} does not exist!" +msgstr "用户 {} 不存在!" + +#: api/lib/perm/acl/resp_format.py:23 +msgid "User {} already exists!" +msgstr "用户 {} 已经存在!" + +#: api/lib/perm/acl/resp_format.py:24 +msgid "Role {} does not exist!" +msgstr "角色 {} 不存在!" + +#: api/lib/perm/acl/resp_format.py:25 +msgid "Role {} already exists!" +msgstr "角色 {} 已经存在!" + +#: api/lib/perm/acl/resp_format.py:26 +msgid "Global role {} does not exist!" +msgstr "全局角色 {} 不存在!" + +#: api/lib/perm/acl/resp_format.py:27 +msgid "Global role {} already exists!" +msgstr "全局角色 {} 已经存在!" + +#: api/lib/perm/acl/resp_format.py:29 +msgid "You do not have {} permission on resource: {}" +msgstr "您没有资源: {} 的 {} 权限" + +#: api/lib/perm/acl/resp_format.py:30 +msgid "Requires administrator permissions" +msgstr "需要管理员权限" + +#: api/lib/perm/acl/resp_format.py:31 +msgid "Requires role: {}" +msgstr "需要角色: {}" + +#: api/lib/perm/acl/resp_format.py:33 +msgid "To delete a user role, please operate on the User Management page!" +msgstr "删除用户角色, 请在 用户管理 页面操作!" + +#: api/lib/perm/acl/resp_format.py:35 +msgid "Application {} already exists" +msgstr "应用 {} 已经存在" + +#: api/lib/perm/acl/resp_format.py:36 +msgid "Application {} does not exist!" +msgstr "应用 {} 不存在!" + +#: api/lib/perm/acl/resp_format.py:37 +msgid "The Secret is invalid" +msgstr "应用的Secret无效" + +#: api/lib/perm/acl/resp_format.py:39 +msgid "Resource {} does not exist!" +msgstr "资源 {} 不存在!" + +#: api/lib/perm/acl/resp_format.py:40 +msgid "Resource {} already exists!" +msgstr "资源 {} 已经存在!" + +#: api/lib/perm/acl/resp_format.py:42 +msgid "Resource group {} does not exist!" +msgstr "资源组 {} 不存在!" + +#: api/lib/perm/acl/resp_format.py:43 +msgid "Resource group {} already exists!" +msgstr "资源组 {} 已经存在!" + +#: api/lib/perm/acl/resp_format.py:45 +msgid "Inheritance detected infinite loop" +msgstr "继承检测到了死循环" + +#: api/lib/perm/acl/resp_format.py:46 +msgid "Role relationship {} does not exist!" +msgstr "角色关系 {} 不存在!" + +#: api/lib/perm/acl/resp_format.py:48 +msgid "Trigger {} does not exist!" +msgstr "触发器 {} 不存在!" + +#: api/lib/perm/acl/resp_format.py:49 +msgid "Trigger {} already exists!" +msgstr "触发器 {} 已经存在!" + +#: api/lib/perm/acl/resp_format.py:50 +msgid "Trigger {} has been disabled!" +msgstr "Trigger {} has been disabled!" + diff --git a/cmdb-api/babel.cfg b/cmdb-api/babel.cfg new file mode 100644 index 0000000..991e57e --- /dev/null +++ b/cmdb-api/babel.cfg @@ -0,0 +1 @@ +[python: api/**.py] diff --git a/cmdb-api/requirements.txt b/cmdb-api/requirements.txt index 849bf9c..516f93d 100644 --- a/cmdb-api/requirements.txt +++ b/cmdb-api/requirements.txt @@ -10,6 +10,7 @@ environs==4.2.0 flasgger==0.9.5 Flask==2.3.2 Flask-Bcrypt==1.0.1 +flask-babel==4.0.0 Flask-Caching==2.0.2 Flask-Cors==4.0.0 Flask-Login>=0.6.2