-
+
- {{$item.FileName}} {{end}} @@ -106,20 +106,20 @@
-
{{range $index,$item := .Model.AttachList}}
diff --git a/commands/command.go b/commands/command.go index 28d85636..7a50be69 100644 --- a/commands/command.go +++ b/commands/command.go @@ -22,6 +22,7 @@ import ( "github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" + "github.com/beego/i18n" "github.com/howeyc/fsnotify" "github.com/lifei6671/gocaptcha" "github.com/mindoc-org/mindoc/cache" @@ -268,6 +269,19 @@ func RegisterFunction() { logs.Error("注册函数 date_format 出错 ->", err) os.Exit(-1) } + + err = web.AddFuncMap("i18n", i18n.Tr) + if err != nil { + logs.Error("注册函数 i18n 出错 ->", err) + os.Exit(-1) + } + langs := strings.Split("en-us|zh-cn", "|") + for _, lang := range langs { + if err := i18n.SetMessage(lang, "conf/lang/"+lang+".ini"); err != nil { + logs.Error("Fail to set message file: " + err.Error()) + return + } + } } //解析命令 diff --git a/commands/install.go b/commands/install.go index 2b53694c..6cabc387 100644 --- a/commands/install.go +++ b/commands/install.go @@ -10,6 +10,8 @@ import ( "github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/core/logs" + "github.com/beego/beego/v2/server/web" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/models" "github.com/mindoc-org/mindoc/utils" @@ -96,11 +98,16 @@ func ModifyPassword() { func initialization() { err := models.NewOption().Init() - if err != nil { panic(err.Error()) } + lang, _ := web.AppConfig.String("default_lang") + err = i18n.SetMessage(lang, "conf/lang/"+lang+".ini") + if err != nil { + panic(fmt.Errorf("initialize locale error: %s", err)) + } + member, err := models.NewMember().FindByFieldFirst("account", "admin") if errors.Is(err, orm.ErrNoRows) { @@ -122,10 +129,10 @@ func initialization() { book := models.NewBook() book.MemberId = member.MemberId - book.BookName = "MinDoc演示项目" + book.BookName = i18n.Tr(lang, "init.default_proj_name") //"MinDoc演示项目" book.Status = 0 book.ItemId = 1 - book.Description = "这是一个MinDoc演示项目,该项目是由系统初始化时自动创建。" + book.Description = i18n.Tr(lang, "init.default_proj_desc") //"这是一个MinDoc演示项目,该项目是由系统初始化时自动创建。" book.CommentCount = 0 book.PrivatelyOwned = 0 book.CommentStatus = "closed" @@ -137,7 +144,7 @@ func initialization() { book.Editor = "markdown" book.Theme = "default" - if err := book.Insert(); err != nil { + if err := book.Insert(lang); err != nil { panic("初始化项目失败 -> " + err.Error()) } } else if err != nil { @@ -146,7 +153,7 @@ func initialization() { if !models.NewItemsets().Exist(1) { item := models.NewItemsets() - item.ItemName = "默认项目空间" + item.ItemName = i18n.Tr(lang, "init.default_proj_space") //"默认项目空间" item.MemberId = 1 if err := item.Save(); err != nil { panic("初始化项目空间失败 -> " + err.Error()) diff --git a/conf/app.conf.example b/conf/app.conf.example index 4483a70c..91872dbe 100644 --- a/conf/app.conf.example +++ b/conf/app.conf.example @@ -230,6 +230,7 @@ dingtalk_qr_key="${MINDOC_DINGTALK_QRKEY}" # 钉钉扫码登录Secret dingtalk_qr_secret="${MINDOC_DINGTALK_QRSECRET}" - +# i18n config +default_lang="zh-cn" diff --git a/conf/lang/en-us.ini b/conf/lang/en-us.ini new file mode 100644 index 00000000..b03bd961 --- /dev/null +++ b/conf/lang/en-us.ini @@ -0,0 +1,570 @@ +[common] +title = mindoc +home = Home +blog = Blog +project_space = Project Space +person_center = Personal Center +my_project = My Project +my_blog = My Article +manage = Management +login = Log In +logout = Log Out +official_website = Official Website +feedback = Feedback +source_code = Source Code +manual = Manual +username = Username +account = Account +email = Email +password = Password +role = Role +captcha = Captcha +keep_login = Stay signed in +forgot_password = Forgot password? +register = Create New Account +dingtalk_login = DingTalk QrCode login +account_recovery = Account recovery +new_password = New password +confirm_password = Confirm password +new_account = Create New Account +setting = Setting +save = Save +edit = Edit +delete = Delete +cancel = Cancel +create = Create +confirm_delete = Confirm +upload_lang = en +js_lang = en +remove = Remove +operate = Operate +confirm = Confirm +creator = Creator +administrator = Administrator +editor = Editor +observer = Observer +back = Back +detail = Detail +admin_right = Reading, writing and management +editor_right = Reading and writing +observer_right = Reading only +yes = yes +no = no +read = Read +generate = Generate + +[init] +default_proj_name = MinDoc Demo Project +default_proj_desc = This is a MinDoc demo project, which is automatically created when the system is initialized. +default_proj_space = Default Project Space +blank_doc = Blank document + +[message] +tips = Tips +page_not_existed = The page does not exist +no_permission = No enough permissions +keyword_placeholder = input keyword please... +wrong_account_password = Incorrect username or password +wrong_password = Wrong password +click_to_change = Click to change one +logging_in = logging in... +need_relogin = Relogin please. +return_account_login = Return account password login +no_account_yet = No account yet? +has_account = Already have an account? +account_empty = Account cannot be empty +email_empty = Email cannot be empty +password_empty = Password cannot be empty +captcha_empty = Captcha cannot be empty +system_error = System error +processing = Processing... +email_sent = The email is sent successfully, please log in to check it. +confirm_password_empty = Confirm password cannot be empty +incorrect_confirm_password = Incorrect confirm password +illegal_request = Illegal request +account_or_password_empty = Account or Password cannot be empty +captcha_wrong = Incorrect captcha +password_length_invalid = The password cannot be empty and must be between 6-50 characters +mail_expired = Mail has expired +captcha_expired = The verification code has expired, please try again. +user_not_existed = User does not exist +email_not_exist = Email does not exist +failed_save_password = Failed to save password +mail_service_not_enable = Mail service is not enabled +account_disable = Account has been disabled +failed_send_mail = Failed to send mail +sent_too_many_times = Send too many times, please try again later +account_not_support_retrieval = The current user does not support password retrieval +username_invalid_format = The account number can only be composed of English alphanumerics and 3-50 characters +email_invalid_format = Email format is incorrect +account_existed = Username already existed +failed_register = Registration failed, please contact the system administrator +failed_obtain_user_info = Failed to obtain identity information +dingtalk_auto_login_not_enable = DingTalk automatic login function is not enabled +failed_auto_login = Automatic login failed +no_project = No Project +item_not_exist = Item does not exist or has been deleted +item_not_exist_or_no_permit = Item does not exist or has insufficient permissions +doc_not_exist = Document does not exist or has been deleted +doc_not_exist_or_no_permit = Document does not exist or has insufficient permissions +unknown_exception = Unknown Exception +no_data = No Data +project_must_belong_space = Project must belong to a project space, and the administrator can manage it +project_title_placeholder = Title (limit in 30 words) +project_title_tips = Project name cannot exceed 100 characters +project_id_placeholder = Project ID (limit in 30 characters) +project_id_tips = The ID can only contain lowercase letters, numbers, and "-", "." and "_" symbols. +project_desc_placeholder = Project description cannot exceed 500 characters +project_public_desc = (Anyone can access) +project_private_desc = (Only participants or use tokens can access) +project_cover_desc = The Cover can be edit in the settings +confirm_delete_project = Are you sure you want to delete the project? +warning_delete_project = Remove items will not be retrieved. +project_space_empty = Please select project space +project_title_empty = Project title cannot be empty +project_id_empty = Project ID cannot be empty +project_id_existed = Project ID already in use +project_id_error = Project ID error +project_id_length = Project ID must be less than 50 characters +import_file_empty = Please select the file to upload +file_type_placeholder = Please select a Zip file +publish_to_queue = The publish task has been pushed to the task queue and will be executed soon. +team_name_empty = Team name cannot be empty +operate_failed = Operation failed +project_id_desc = The project ID is used to mark the uniqueness of the item and cannot be modified. +history_record_amount_desc = When document history enabled, this value limits the number of history saved per document +corp_id_desc = The footer that appears when the document PDF document is exported +project_desc_desc = The description information is no more than 500 characters, supports markdown syntax +project_desc_tips = The description information is no more than 500 characters +access_pass_desc = The password that needs to be provided to access the project without permit +auto_publish_desc = Enable for each save is automatically published to the latest version +enable_export_desc = Configure the exporter before you start the export, also enable the export function in the profile +enable_share_desc = Sharing is only available for public projects, and private projects do not support sharing +auto_save_desc = Save automatically every 30 seconds +confirm_into_private = Are you sure you want to make your project private? +into_private_notice = Private project need provide access token +confirm_into_public = Are you sure you want to make your project public? +into_public_notice = Public project could be visit by anyone +project_name_empty = Project name cannot be empty +success = Success +failed = Failed +receive_account_empty = The recipient account cannot be empty +receive_account_not_exist = The recipient account not exist +receive_account_disabled = The recipient account disable +cannot_preview = Cannot preview +upload_failed = Upload failed +upload_file_size_limit = The file must be less than 2MB +upload_file_empty = Upload file is empty +uploda_file_type_error = upload file type is wrong +choose_pic_file = Please select a picture +no_doc_in_cur_proj = No documents for the current project +build_doc_tree_error = There was an error building the project document tree +param_error = Parameter error +doc_name_empty = Document name cannot empty +parent_id_not_existed = Parent ID not existed +doc_not_belong_project = The document does not belong to the specified project` +attachment_not_exist = Attachment does not exist +read_file_error = Load file error +confirm_override_doc = The document has been modified, are you sure to override it? +doc_auto_published = The document was automatically published +export_func_disable = The export function is disable +cur_project_export_func_disable = The export function is disable for current Project +cur_project_not_support_md = The Markdown editor is not supported for the current project +export_failed = The export failed, check the system logs +file_converting = The document is being converted in the background, please download it later +unsupport_file_type = Unsupport file type +no_exportable_file = The project has no exportable file +gen_qrcode_failed = Generate QrCode failed +search_result_error = Search error +get_doc_his_failed = Fail to get document history +project_space_not_exist = Project space does not exist +search_placeholder = input keyword please +no_search_result = No search results! +user_exist_in_proj = The user already exists in the project +cannot_change_own_priv = Cannot change own permissions +cannot_delete_self = Cannot delete myself +cannot_handover_myself = Cannot handover to myself +confirm_delete_blog = Confirm delete blog? +delete_blog_tips = Deleted blog cannot be retrieved. +input_proj_id_pls = input project ID please +input_doc_id_pls = input document ID please +blog_digest_tips = blog digest cannot exceed 500 characters +blog_title_empty = blog title cannot be empty +blog_not_exist = Blog does not exist or has been deleted +blog_pwd_incorrect = Access password incorrect +set_pwd_pls = please set password for encrypt blog +unknown_blog_type = unknown blog type +blog_title_tips = blog title cannot exceed 200 characters +ref_doc_prj_not_existed = The Project of reference document not existed +query_ref_doc_error = query reference document failed +ref_doc_not_exist_or_no_permit = reference document does not exist or has insufficient permissions +blog_id_existed = blog id already existed +query_failed = query failed +blog_has_modified = The article has been modified +cur_user_cannot_change_pwd = The current user does not support changing the password +origin_pwd_empty = The origin password cannot be empty +new_pwd_empty = The new password cannot be empty +confirm_pwd_empty = The confirm password cannot be empty +pwd_length = Password must be between 6-18 characters +pwd_length_tips = Password must be between 6-50 characters +wrong_origin_pwd = The origin password incorrect +wrong_confirm_pwd = The confirm passwrod incorrect +same_pwd = The new password must different from the origin +pwd_encrypt_failed = Password encryption failed +team_name_empty = Team name cannot be emtpy +proj_empty = Project cannot be empty +site_name_empty = Site name cannot be empty +proj_space_name_empty = Project space name cannot be empty +proj_space_id_empty = Project space id cannot be empty +proj_space_id_tips = The project space id can only consist of letters and numbers and be between 2-100 characters +project_order_desc = Number only, sort from largest to smallest +project_label_desc = Allows up to 10 labels, use ";" to separate multiple tags +cannot_change_own_status = Cannot change own status +cannot_change_super_status = Cannot change super administrator status +cannot_change_super_priv = Cannot change super administrator permissions + +[blog] +author = Author +project_list = Project List +add_project = Add Project +import_project = Import Project +delete_project = Delete Project +project_summary = Project summary +read = Read +edit = Edit +delete = Delete +copy = Copy +view = View +publish = Publish +edit_doc = Edit Document +default_cover = Default Cover +create_time = Create Time +update_time = Update Time +creator = Creator +doc_amount = Number of documents +doc_unit = +project_role = Project Role +last_edit = Last Edited +project_title = Project Title +project_id = Project ID +project_desc = Project description +public = Public +private = Private +public_project = Public Project +private_project = Private Project +summary = Summary +member = Member +team = Team +comment_amount = Number of comments +comment_unit = +member_manage = Member Manage +add_member = Add Member +administrator = Administrator +editor = Editor +observer = Observer +team_manage = Team Manage +add_team = Add Team +team_name = Team name +member_amount = Number of members +join_time = Join Time +project_setting = Project setting +handover_project = Hanover +make_public = Into Public +make_private = Into Privete +history_record_amount = Number of history records +corp_id = corp name +text_editor = editor +project_label = Project Label +project_order = Project Order +access_pass = Access Password +access_token = Access Token +auto_publish = Auto publish +enable_export = Enable Export +enable_share = Enable Share +set_first_as_home = Set the first document as the default homepage +auto_save = Auto Save +cover = Cover +click_change_cover = Click to change the cover +change_cover = Change Cover +preview = Preview +choose = Choose +upload = Upload +recipient_account = Recipient +blog_list = Blog List +add_blog = Add Blog +encryption = encryption +encrypt = encrypt +edit_blog = Edit blog +delete_blog = Delete blog +setting_blog = Setting Blog +no_blog = No Blog +blog_setting = Blog Setting +title = Blog Title +type = Blog Type +normal_blog = Normal Blog +link_blog = Link Blog +ref_doc = Reference Document +blog_status = Blog Status +blog_pwd = Blog Password +blog_digest = Blog Digest +posted_on = Posted on +modified_on = Modified on +prev = prev +next = next +no = no +edit_title = Edit Blog + +[doc] +modify_doc = Modify Document +comparison = Comparison +save_merge = Save Merge +prev_diff = Previous difference +next_diff = Next difference +merge_to_left = Merge to left +merge_to_right = Merge to right +exchange_left_right = Exchange left and right +print = Print +download = Download +share = Share +share_project = Share project +share_url = Project URL +contents = Contents +search = Search +expand = Unfold +fold = Fold +close = Close +doc_publish_by = Document is Published by +doc_publish = +edit_doc = Edit Document +backward = backward +save = save +save_as_tpl = save as template +undo = undo +redo = redo +bold = bold +italic = italic +strikethrough = strikethrough +h1 = head 1 +h2 = head 2 +h3 = head 3 +h4 = head 4 +h5 = head 5 +h6 = head 6 +unorder_list = disorder list +order_list = order list +hline = horizontal line +link = link +ref_link = reference link +add_pic = add picture +code = code +code_block = code block +table = add table +quote = quote +gfm_task = GFM task +attachment = attachment +json_to_table = Json converted to table +template = template +close_preview = disable preview +modify_history = modify history +sidebar = sidebar +help = help +publish = publish +document = document +create_doc = create document +attachments = attachments +doc_name = Document name +doc_name_tips = Right-click on the document name of the directory to delete and modify the document name and add subordinate documents +doc_id = Document ID +doc_id_tips = The document ID can only contain lowercase letters, numbers, and "-" and "_" symbols, and can only start with a lowercase letter +expand_desc = (Expand nodes when reading) +fold_desc = (Fold nodes when reading) +empty_contents = Empty contents +empty_contents_desc = Click to expand the subordinate nodes +upload_attachment = Upload attachment +doc_history = Document history +choose_template_type = Choose template type please +normal_tpl = Normal +api_tpl = API +data_dict = Data Dictionary +custom_tpl = Custom +tpl_default_type = Default type +tpl_plain_text = Plain Text +for_api_doc = Used for API Document +code_highlight = support code highlighting +for_data_dict = Used for data dictionary +form_support = Form Support +any_type_doc = Support any type of document +as_global_tpl = Can be set as a global template +tpl_name = Template name +tpl_type = Template type +creator = Creator +create_time = Create time +operation = Operation +global_tpl = Global +global_tpl_desc = (Any Project is available) +project_tpl = Project +project_tpl_desc = (Only the current Project is available) +insert = insert +uploading = Uploading +his_ver = Historic version +update_time = Update time +updater = Updater +version = Version +delete = Delete +recover = Recover +merge = Merge +comparison_title = Document comparison [the left is the historical document, the right is the current document, please merge the documents to the right] +font_size = font size +underscore = underscore +right_intent = right intent +left_intent = left intent +subscript = subscript +superscript = superscript +clean_format = clear format +add_video = add video +formula = formula +font_color = font color +bg_color = background color +input_pwd = input password please +read_pwd = read password +commit = commit +ft_author = Author: +ft_last_editor = Last editor: +ft_create_time = Create time: +ft_update_time = Update time: +view_count = Number of views + +[project] +prj_space_list = Project Space List +prj_space_list_of = List of Project Space %s +search_title = Show Items of Project Space "%s" +author = Author +no_project = No Project +prj_amount = Project Count +creator = Creator +create_time = Create time +no_project_space = No Project Space + +[search] +title = Search +search_title = Show search result for %s +doc = document +prj = project +blog = blog +from_proj = from project +from_blog = from blog +author = author +update_time = update time +no_result = No search result + +[page] +first = first +last = last +prev = prev +next = next + +[uc] +user_center = User Center +base_info = Basic Info +change_pwd = Change Password +username = Username +nickname = Nickname +realname = Real name +email = Email +mobile = Mobile +description = Description +description_tips = Description cannot exceed 500 characters +avatar = Avatar +change_avatar = Change avatar +password = Password +origin_pwd = Origin password +new_pwd = New password +confirm_pwd = Confirm password +role = Role +type = Type +status = Status +super_admin = Super administrator +admin = Administrator +user = User +normal = Normal +disable = Disable +enable = Enable +create_user = Create User +edit_user = Edit User +pwd_tips = Please leave it blank if you do not change the password, only local users can change the password + +[mgr] +dashboard_menu = Dashboard +user_menu = User +team_menu = Team +project_menu = Project +project_space_menu = Project Space +comment_menu = Comment +config_menu = Configure +attachment_menu = Attachment +label_menu = Label +dashboard_mgr = Dashboard +user_mgr = User Management +team_mgr = Team Management +project_mgr = Project Management +project_space_mgr = Project Space Management +comment_mgr = Comment Management +config_mgr = Configure Management +config_file = Configure File +attachment_mgr = Attachment Management +label_mgr = Label Management +label_name = Label name +used_quantity = Used Quantity +proj_amount = Number Of Project +blog_amount = Number Of Blog +member_amount = Number Of Member +comment_amount = Number Of Comment +attachment_amount = Number Of Attachment +member_mgr = Member Management +add_member = Add Member +create_team = Create Team +team_name = Team Name +proj = Project +member = Member +edit_team = Edit Team +team_member_mgr = Team Member Management +team_proj = Team Project +add_proj = Add Project +proj_name = Project name +proj_author = Project author +join_time = Join Time +join_proj = Join +file_name = File name +is_exist = Is Exist +exist = Exist +deleted = Deleted +proj_blog_name = Project/Blog name +doc_name = Document name +file_path = File path +download_url = Download URL +file_size = File size +upload_time = Upload time +download = Download +download_title = Download to local +attachment_name = Attachment name +site_name = Site Name +domain_icp = Domain ICP +site_desc = Site Description +site_desc_tips = Description cannot exceed 500 characters +enable_anonymous_access = Enable anonymous access +enable = Enable +disable = Disable +enable_register = Enable Registration +enable_captcha = Enable Captcha +enable_doc_his = Enable Document Historic +proj_space_name = Project space name +proj_space_id = Project space ID +create_proj_space = Create Project Space +edit_proj_space = Edit Project Space +proj_list = Project List +edit_proj = Edit Project +create_time = Create Time +creator = Creator +doc_amount = Number of Document +last_edit = Last Edit +delete_project = Delete Project \ No newline at end of file diff --git a/conf/lang/zh-cn.ini b/conf/lang/zh-cn.ini new file mode 100644 index 00000000..adf045de --- /dev/null +++ b/conf/lang/zh-cn.ini @@ -0,0 +1,570 @@ +[common] +title = 文档在线管理系统 +home = 首页 +blog = 文章 +project_space = 项目空间 +person_center = 个人中心 +my_project = 我的项目 +my_blog = 我的文章 +manage = 管理后台 +login = 登录 +logout = 退出登录 +official_website = 官方网站 +feedback = 意见反馈 +source_code = 项目源码 +manual = 使用手册 +username = 用户名 +account = 账号 +email = 邮箱 +password = 密码 +role = 角色 +captcha = 验证码 +keep_login = 保持登录 +forgot_password = 忘记密码? +register = 立即注册 +dingtalk_login = 扫码登录 +account_recovery = 找回密码 +new_password = 新密码 +confirm_password = 确认密码 +new_account = 用户注册 +setting = 设置 +save = 保存 +edit = 编辑 +delete = 删除 +cancel = 取消 +create = 创建 +confirm_delete = 确定删除 +upload_lang = zh +js_lang = zh-CN +remove = 移除 +operate = 操作 +confirm = 确定 +creator = 创始人 +administrator = 管理员 +editor = 编辑者 +observer = 观察者 +back = 返回 +detail = 详情 +admin_right = 拥有阅读、写作和管理权限 +editor_right = 拥有阅读和写作权限 +observer_right = 拥有阅读权限 +yes = 是 +no = 否 +read = 阅读 +generate = 生成 + +[init] +default_proj_name = MinDoc演示项目 +default_proj_desc = 这是一个MinDoc演示项目,该项目是由系统初始化时自动创建。 +default_proj_space = 默认项目空间 +blank_doc = 空白文档 + +[message] +tips = 友情提示 +page_not_existed = 页面不存在 +no_permission = 权限不足 +keyword_placeholder = 请输入关键词... +wrong_account_password = 账号或密码错误 +wrong_password = 密码错误 +click_to_change = 点击换一张 +logging_in = 正在登录... +need_relogin = 请重新登录。 +return_account_login = 返回账号密码登录 +no_account_yet = 还没有账号? +has_account = 已有账号? +account_empty = 账号不能为空 +email_empty = 邮箱不能为空 +password_empty = 密码不能为空 +captcha_empty = 验证码不能为空 +system_error = 系统错误 +processing = 正在处理... +email_sent = 邮件发送成功,请登录邮箱查看。 +confirm_password_empty = 确认密码不能为空 +incorrect_confirm_password = 确认密码输入不正确 +illegal_request = 非法请求 +account_or_password_empty = 账号或密码不能为空 +captcha_wrong = 验证码不正确 +password_length_invalid = 密码不能为空且必须在6-50个字符之间 +mail_expired = 邮件已失效 +captcha_expired = 验证码已过期,请重新操作。 +user_not_existed = 用户不存在 +email_not_exist = 邮箱不存在 +failed_save_password = 保存密码失败 +mail_service_not_enable = 未启用邮件服务 +account_disable = 账号已被禁用 +failed_send_mail = 发送邮件失败 +sent_too_many_times = 发送次数太多,请稍候再试 +account_not_support_retrieval = 当前用户不支持找回密码 +username_invalid_format = 账号只能由英文字母数字组成,且在3-50个字符 +email_invalid_format = 邮箱格式不正确 +account_existed = 账号已存在 +failed_register = 注册失败,请联系管理员 +failed_obtain_user_info = 获取身份信息失败 +dingtalk_auto_login_not_enable = 未开启钉钉自动登录功能 +failed_auto_login = 自动登录失败 +no_project = 暂无项目 +item_not_exist = 项目不存在或已删除 +item_not_exist_or_no_permit = 项目不存在或权限不足 +doc_not_exist = 文档不存在或已删除 +doc_not_exist_or_no_permit = 文档不存在或权限不足 +unknown_exception = 未知异常 +no_data = 暂无数据 +project_must_belong_space = 每个项目必须归属一个项目空间,超级管理员可在后台管理和维护 +project_title_placeholder = 项目标题(不超过100字) +project_title_tips = 项目标题不能超过100字符 +project_id_placeholder = 项目唯一标识(不超过50字) +project_id_tips = 文档标识只能包含小写字母、数字,以及“-”、“.”和“_”符号. +project_desc_placeholder = 描述信息不超过500个字符 +project_public_desc = (任何人都可以访问) +project_private_desc = (只有参与者或使用令牌才能访问) +project_cover_desc = 项目图片可在项目设置中修改 +confirm_delete_project = 确定删除项目吗? +warning_delete_project = 删除项目后将无法找回。 +project_space_empty = 请选择项目空间 +project_title_empty = 项目标题不能为空 +project_id_empty = 项目标识不能为空 +project_id_existed = 文档标识已被使用 +project_id_error = 项目标识有误 +project_id_length = 项目标识必须小于50字符 +import_file_empty = 请选择需要上传的文件 +file_type_placeholder = 请选择Zip文件 +publish_to_queue = 发布任务已推送到任务队列,稍后将在后台执行。 +team_name_empty = 团队名称不能为空 +operate_failed = 操作失败 +project_id_desc = 项目标识用来标记项目的唯一性,不可修改。 +history_record_amount_desc = 当开启文档历史时,该值会限制每个文档保存的历史数量 +corp_id_desc = 导出文档PDF文档时显示的页脚 +project_desc_desc = 描述信息不超过500个字符,支持Markdown语法 +project_desc_tips = 项目描述不能大于500字 +access_pass_desc = 没有访问权限访问项目时需要提供的密码 +auto_publish_desc = 开启后,每次保存会自动发布到最新版本 +enable_export_desc = 开启导出前请先配置导出程序,并在配置文件中同时开启导出功能 +enable_share_desc = 分享只对公开项目生效,私有项目不支持分享 +auto_save_desc = 开启后每隔30秒会自动保存 +confirm_into_private = 确定将项目转为私有吗? +into_private_notice = 转为私有后需要通过阅读令牌才能访问该项目。 +confirm_into_public = 确定将项目转为公有吗? +into_public_notice = 转为公有后所有人都可以访问该项目。 +project_name_empty = 项目名称不能为空 +success = 成功 +failed = 失败 +receive_account_empty = 接受者账号不能为空 +receive_account_not_exist = 接受用户不存在 +receive_account_disabled = 接受用户已被禁用 +cannot_preview = 不能预览 +upload_failed = 上传失败 +upload_file_size_limit = 文件必须小于2MB +upload_file_empty = 上传文件为空 +uploda_file_type_error = 文件类型有误 +choose_pic_file = 请选择图片 +no_doc_in_cur_proj = 当前项目没有文档 +build_doc_tree_error = 生成项目文档树时出错 +param_error = 参数错误 +doc_name_empty = 文档名称不能为空 +parent_id_not_existed = 父分类不存在 +doc_not_belong_project = 文档不属于指定的项目 +attachment_not_exist = 附件不存在或已删除 +read_file_error = 读取文档错误 +confirm_override_doc = 文档已被修改确定要覆盖吗? +doc_auto_published = 文档自动发布成功 +export_func_disable = 系统没有开启导出功能 +cur_project_export_func_disable = 当前项目没有开启导出功能 +cur_project_not_support_md = 当前项目不支持Markdown编辑器 +export_failed = 导出失败,请查看系统日志 +file_converting = 文档正在后台转换,请稍后再下载 +unsupport_file_type = 不支持的文件格式 +no_exportable_file = 项目没有导出文件 +gen_qrcode_failed = 生成二维码失败 +search_result_error = 搜索结果错误 +get_doc_his_failed = 获取历史失败 +project_space_not_exist = 项目空间不存在 +search_placeholder = 请输入搜索关键字 +no_search_result = 暂无相关搜索结果! +user_exist_in_proj = 用户已存在该项目中 +cannot_change_own_priv = 不能变更自己的权限 +cannot_delete_self = 不能删除自己 +cannot_handover_myself = 不能转让给自己 +confirm_delete_blog = 确定删除文章吗? +delete_blog_tips = 删除文章后将无法找回。 +input_proj_id_pls = 请输入项目标识 +input_doc_id_pls = 请输入文档标识 +blog_digest_tips = 文章摘要不超过500个字符 +blog_title_empty = 文章标题不能为空 +blog_not_exist = 文章不存在或已删除 +blog_pwd_incorrect = 文章密码不正确 +set_pwd_pls = 加密文章请设置密码 +unknown_blog_type = 未知的文章类型 +blog_title_tips = 文章标题不能大于200个字符 +ref_doc_prj_not_existed = 关联文档的项目不存在 +query_ref_doc_error = 查询关联项目文档时出错 +ref_doc_not_exist_or_no_permit = 关联文档不存在或权限不足 +blog_id_existed = 文章标识已存在 +query_failed = 查询失败 +blog_has_modified = 文章已被修改 +cur_user_cannot_change_pwd = 当前用户不支持修改密码 +origin_pwd_empty = 原密码不能为空 +new_pwd_empty = 新密码不能为空 +confirm_pwd_empty = 确认密码不能为空 +pwd_length = 密码必须在6-18字之间 +pwd_length_tips = 密码必须在6-50个字符之间 +wrong_origin_pwd = 原始密码不正确 +wrong_confirm_pwd = 确认密码不正确 +same_pwd = 新密码不能和原始密码相同 +pwd_encrypt_failed = 密码加密失败 +team_name_empty = 团队名称不能为空 +proj_empty = 项目不能为空 +site_name_empty = 网站标题不能为空 +proj_space_name_empty = 项目空间名称不能为空 +proj_space_id_empty = 项目空间标识不能为空 +proj_space_id_tips = 项目空间标识只能由字母和数字组成且在2-100字符之间 +project_order_desc = 只能是数字,序号越大排序越靠前 +project_label_desc = 最多允许添加10个标签,多个标签请用“;”分割 +cannot_change_own_status = 不能变更自己的状态 +cannot_change_super_status = 不能变更超级管理员的状态 +cannot_change_super_priv = 不能变更超级管理员的权限 + +[blog] +author = 作者 +project_list = 项目列表 +add_project = 添加项目 +import_project = 导入项目 +delete_project = 删除项目 +project_summary = 项目概要 +read = 阅读 +edit = 编辑 +delete = 删除 +copy = 复制 +view = 查看文档 +publish = 发布 +edit_doc = 编辑文档 +default_cover = 默认封面 +create_time = 创建时间 +update_time = 修改时间 +creator = 创建者 +doc_amount = 文档数量 +doc_unit = 篇 +project_role = 项目角色 +last_edit = 最后编辑 +project_title = 项目标题 +project_id = 项目标识 +project_desc = 项目描述 +public = 公开 +private = 私有 +public_project = 公开项目 +private_project = 私有项目 +summary = 概要 +member = 成员 +team = 团队 +comment_amount = 评论数量 +comment_unit = 条 +member_manage = 成员管理 +add_member = 添加成员 +administrator = 管理员 +editor = 编辑者 +observer = 观察者 +team_manage = 团队管理 +add_team = 添加团队 +team_name = 团队名称 +member_amount = 成员数量 +join_time = 加入时间 +project_setting = 项目设置 +handover_project = 转让项目 +make_public = 转为公有 +make_private = 转为私有 +history_record_amount = 历史记录数量 +corp_id = 公司名称 +text_editor = 编辑器 +project_label = 项目标签 +project_order = 项目排序 +access_pass = 访问密码 +access_token = 访问令牌 +auto_publish = 自动发布 +enable_export = 开启导出 +enable_share = 开启分享 +set_first_as_home = 设置第一篇文档为默认首页 +auto_save = 自动保存 +cover = 封面 +click_change_cover = 点击图片可修改项目封面 +change_cover = 修改封面 +preview = 预览 +choose = 选择 +upload = 上传 +recipient_account = 接收者账号 +blog_list = 文章列表 +add_blog = 添加文章 +encryption = 加密 +encrypt = 密 +edit_blog = 文章编辑 +delete_blog = 删除文章 +setting_blog = 文章设置 +no_blog = 暂无文章 +blog_setting = 文章设置 +title = 文章标题 +type = 文章类型 +normal_blog = 普通文章 +link_blog = 链接文章 +ref_doc = 关联文档 +blog_status = 文章状态 +blog_pwd = 文章密码 +blog_digest = 文章摘要 +posted_on = 发布于 +modified_on = 修改于 +prev = 上一篇 +next = 下一篇 +no = 无 +edit_title = 编辑文章 + +[doc] +modify_doc = 修改文档 +comparison = 文档比较 +save_merge = 保存合并 +prev_diff = 上一处差异 +next_diff = 下一处差异 +merge_to_left = 合并到左侧 +merge_to_right = 合并到右侧 +exchange_left_right = 左右切换 +print = 打印 +download = 下载 +share = 分享 +share_project = 项目分享 +share_url = 项目地址 +contents = 目录 +search = 搜索 +expand = 展开 +fold = 收起 +close = 关闭 +doc_publish_by = 本文档使用 +doc_publish = 发布 +edit_doc = 编辑文档 +backward = 返回 +save = 保存 +save_as_tpl = 保存为模板 +undo = 撤销 +redo = 重做 +bold = 粗体 +italic = 斜体 +strikethrough = 删除线 +h1 = 标题一 +h2 = 标题二 +h3 = 标题三 +h4 = 标题四 +h5 = 标题五 +h6 = 标题六 +unorder_list = 无序列表 +order_list = 有序列表 +hline = Horizontal line +link = 链接 +ref_link = 引用链接 +add_pic = 添加图片 +code = 行内代码 +code_block = 代码块 +table = 添加表格 +quote = 引用 +gfm_task = GFM 任务列表 +attachment = 附件 +json_to_table = Json转换为表格 +template = 模板 +close_preview = 关闭实时预览 +modify_history = 修改历史 +sidebar = 边栏 +help = 使用帮助 +publish = 发布 +document = 文档 +create_doc = 创建文档 +attachments = 个附件 +doc_name = 文档名称 +doc_name_tips = 在目录的文档名上右键可以删除和修改文档名称以及添加下级文档 +doc_id = 文档标识 +doc_id_tips = 文档标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头 +expand_desc = (在阅读时会自动展开节点) +fold_desc = (在阅读时会关闭节点) +empty_contents = 空目录 +empty_contents_desc = (单击时会展开下级节点) +upload_attachment = 上传附件 +doc_history = 文档历史记录 +choose_template_type = 请选择模板类型 +normal_tpl = 普通文档 +api_tpl = API文档 +data_dict = 数据字典 +custom_tpl = 自定义模板 +tpl_default_type = 默认类型 +tpl_plain_text = 简单的文本文档 +for_api_doc = 用于API文档速写 +code_highlight = 支持代码高亮 +for_data_dict = 用于数据字典显示 +form_support = 表格支持 +any_type_doc = 支持任意类型文档 +as_global_tpl = 可以设置为全局模板 +tpl_name = 模板名称 +tpl_type = 模板类型 +creator = 创建人 +create_time = 创建时间 +operation = 操作 +global_tpl = 全局 +global_tpl_desc = (任何项目都可用) +project_tpl = 项目 +project_tpl_desc = (只有当前项目可用) +insert = 插入 +uploading = 正在上传 +his_ver = 历史版本 +update_time = 修改时间 +updater = 修改人 +version = 版本 +delete = 删除 +recover = 恢复 +merge = 合并 +comparison_title = 文档比较【左侧为历史文档,右侧为当前文档,请将文档合并到右侧】 +font_size = 字号 +underscore = 下划线 +right_intent = 右缩进 +left_intent = 左缩进 +subscript = 下标 +superscript = 上标 +clean_format = 清空格式 +add_video = 添加视频 +formula = 公式 +font_color = 字体颜色 +bg_color = 背景颜色 +input_pwd = 请输入密码 +read_pwd = 浏览密码 +commit = 提交 +ft_author = 作者: +ft_last_editor = 最后编辑: +ft_create_time = 创建时间: +ft_update_time = 更新时间: +view_amount = 阅读次数 + +[project] +prj_space_list = 项目空间列表 +prj_space_list_of = 项目空间%s的项目列表 +search_title = 显示项目空间为"%s"的项目 +author = 作者 +no_project = 暂无项目 +prj_amount = 项目数量 +creator = 创建人 +create_time = 创建时间 +no_project_space = 没有项目空间 + +[search] +title = 搜索 +search_title = 显示"%s"的搜索结果 +doc = 文档 +prj = 项目 +blog = 文章 +from_proj = 来自项目 +from_blog = 来自文章 +author = 作者 +update_time = 更新时间 +no_result = 暂无相关搜索结果 + +[page] +first = 首页 +last = 末页 +prev = 上一页 +next = 下一页 + +[uc] +user_center = 用户中心 +base_info = 基本信息 +change_pwd = 修改密码 +username = 用户名 +nickname = 昵称 +realname = 真实姓名 +email = 邮箱 +mobile = 手机号 +description = 描述 +description_tips = 描述不能超过500字 +avatar = 头像 +change_avatar = 修改头像 +password = 密码 +origin_pwd = 原始密码 +new_pwd = 新密码 +confirm_pwd = 确认密码 +role = 角色 +type = 类型 +status = 状态 +super_admin = 超级管理员 +admin = 管理员 +user = 普通用户 +normal = 正常 +disable = 禁用 +enable = 启用 +create_user = 创建用户 +edit_user = 编辑用户 +pwd_tips = 不修改密码请留空,只支持本地用户修改密码 + +[mgr] +dashboard_menu = 仪表盘 +user_menu = 用户管理 +team_menu = 团队管理 +project_menu = 项目管理 +project_space_menu = 项目空间管理 +comment_menu = 评论管理 +config_menu = 配置管理 +attachment_menu = 附件管理 +label_menu = 标签管理 +dashboard_mgr = 仪表盘 +user_mgr = 用户管理 +team_mgr = 团队管理 +project_mgr = 项目管理 +project_space_mgr = 项目空间管理 +comment_mgr = 评论管理 +config_mgr = 配置管理 +config_file = 配置文件 +attachment_mgr = 附件管理 +label_mgr = 标签管理 +label_name = 标签名称 +used_quantity = 使用数量 +proj_amount = 项目数量 +blog_amount = 文章数量 +member_amount = 成员数量 +comment_amount = 评论数量 +attachment_amount = 附件数量 +member_mgr = 成员管理 +add_member = 添加成员 +create_team = 创建团队 +team_name = 团队名称 +proj = 项目 +member = 成员 +edit_team = 编辑团队 +team_member_mgr = 团队用户管理 +team_proj = 团队项目 +add_proj = 添加项目 +proj_name = 项目名称 +proj_author = 项目作者 +join_time = 加入时间 +join_proj = 加入项目 +file_name = 文件名称 +is_exist = 是否存在 +exist = 存在 +deleted = 已删除 +proj_blog_name = 项目/文章名称 +doc_name = 文档名称 +file_path = 文件路径 +download_url = 下载路径 +file_size = 文件大小 +upload_time = 上传时间 +download = 下载 +download_title = 下载到本地 +attachment_name = 附件名称 +site_name = 网站标题 +domain_icp = 域名备案 +site_desc = 网站描述 +site_desc_tips = 描述信息不超过500个字符 +enable_anonymous_access = 启用匿名访问 +enable = 开启 +disable = 关闭 +enable_register = 启用注册 +enable_captcha = 启用验证码 +enable_doc_his = 启用文档历史 +proj_space_name = 项目空间名称 +proj_space_id = 项目空间标识 +create_proj_space = 创建项目空间 +edit_proj_space = 编辑项目空间 +proj_list = 项目列表 +edit_proj = 编辑项目 +create_time = 创建时间 +creator = 创建者 +doc_amount = 文档数量 +last_edit = 最后编辑 +delete_project = 删除项目 \ No newline at end of file diff --git a/controllers/AccountController.go b/controllers/AccountController.go index 29851e7a..04ef1d84 100644 --- a/controllers/AccountController.go +++ b/controllers/AccountController.go @@ -1,6 +1,7 @@ package controllers import ( + "github.com/beego/i18n" "net/url" "regexp" "strings" @@ -55,17 +56,17 @@ func (c *AccountController) Prepare() { } if token == "" { if c.IsAjax() { - c.JsonResult(403, "非法请求") + c.JsonResult(403, i18n.Tr(c.Lang, "message.illegal_request")) } else { - c.ShowErrorPage(403, "非法请求") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.illegal_request")) } } xsrfToken := c.XSRFToken() if xsrfToken != token { if c.IsAjax() { - c.JsonResult(403, "非法请求") + c.JsonResult(403, i18n.Tr(c.Lang, "message.illegal_request")) } else { - c.ShowErrorPage(403, "非法请求") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.illegal_request")) } } } @@ -109,12 +110,12 @@ func (c *AccountController) Login() { if v, ok := c.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") { v, ok := c.GetSession(conf.CaptchaSessionName).(string) if !ok || !strings.EqualFold(v, captcha) { - c.JsonResult(6001, "验证码不正确") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.captcha_wrong")) } } if account == "" || password == "" { - c.JsonResult(6002, "账号或密码不能为空") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.account_or_password_empty")) } member, err := models.NewMember().Login(account, password) @@ -137,7 +138,7 @@ func (c *AccountController) Login() { c.JsonResult(0, "ok", c.referer()) } else { logs.Error("用户登录 ->", err) - c.JsonResult(500, "账号或密码错误", nil) + c.JsonResult(500, i18n.Tr(c.Lang, "message.wrong_account_password"), nil) } } else { c.Data["url"] = c.referer() @@ -150,7 +151,7 @@ func (c *AccountController) DingTalkLogin() { code := c.GetString("dingtalk_code") if code == "" { - c.JsonResult(500, "获取身份信息失败", nil) + c.JsonResult(500, i18n.Tr(c.Lang, "message.failed_obtain_user_info"), nil) } appKey, _ := web.AppConfig.String("dingtalk_app_key") @@ -158,7 +159,7 @@ func (c *AccountController) DingTalkLogin() { tmpReader, _ := web.AppConfig.String("dingtalk_tmp_reader") if appKey == "" || appSecret == "" || tmpReader == "" { - c.JsonResult(500, "未开启钉钉自动登录功能", nil) + c.JsonResult(500, i18n.Tr(c.Lang, "message.dingtalk_auto_login_not_enable"), nil) c.StopRun() } @@ -166,21 +167,21 @@ func (c *AccountController) DingTalkLogin() { err := dingtalkAgent.GetAccesstoken() if err != nil { logs.Warn("获取钉钉临时Token失败 ->", err) - c.JsonResult(500, "自动登录失败", nil) + c.JsonResult(500, i18n.Tr(c.Lang, "message.failed_auto_login"), nil) c.StopRun() } userid, err := dingtalkAgent.GetUserIDByCode(code) if err != nil { logs.Warn("获取钉钉用户ID失败 ->", err) - c.JsonResult(500, "自动登录失败", nil) + c.JsonResult(500, i18n.Tr(c.Lang, "message.failed_auto_login"), nil) c.StopRun() } username, avatar, err := dingtalkAgent.GetUserNameAndAvatarByUserID(userid) if err != nil { logs.Warn("获取钉钉用户信息失败 ->", err) - c.JsonResult(500, "自动登录失败", nil) + c.JsonResult(500, i18n.Tr(c.Lang, "message.failed_auto_login"), nil) c.StopRun() } @@ -309,29 +310,29 @@ func (c *AccountController) Register() { captcha := c.GetString("code") if ok, err := regexp.MatchString(conf.RegexpAccount, account); account == "" || !ok || err != nil { - c.JsonResult(6001, "账号只能由英文字母数字组成,且在3-50个字符") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.username_invalid_format")) } if l := strings.Count(password1, ""); password1 == "" || l > 50 || l < 6 { - c.JsonResult(6002, "密码必须在6-50个字符之间") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.password_length_invalid")) } if password1 != password2 { - c.JsonResult(6003, "确认密码不正确") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.incorrect_confirm_password")) } if ok, err := regexp.MatchString(conf.RegexpEmail, email); !ok || err != nil || email == "" { - c.JsonResult(6004, "邮箱格式不正确") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.email_invalid_format")) } // 如果开启了验证码 if v, ok := c.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") { v, ok := c.GetSession(conf.CaptchaSessionName).(string) if !ok || !strings.EqualFold(v, captcha) { - c.JsonResult(6001, "验证码不正确") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.captcha_wrong")) } } member := models.NewMember() if _, err := member.FindByAccount(account); err == nil && member.MemberId > 0 { - c.JsonResult(6005, "账号已存在") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.account_existed")) } member.Account = account @@ -342,7 +343,7 @@ func (c *AccountController) Register() { member.Email = email member.Status = 0 if err := member.Add(); err != nil { - c.JsonResult(6006, "注册失败,请联系系统管理员处理") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed_register")) } c.JsonResult(0, "ok", member) @@ -360,39 +361,39 @@ func (c *AccountController) FindPassword() { captcha := c.GetString("code") if email == "" { - c.JsonResult(6005, "邮箱地址不能为空") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.email_empty")) } if !mailConf.EnableMail { - c.JsonResult(6004, "未启用邮件服务") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.mail_service_not_enable")) } // 如果开启了验证码 if v, ok := c.Option["ENABLED_CAPTCHA"]; ok && strings.EqualFold(v, "true") { v, ok := c.GetSession(conf.CaptchaSessionName).(string) if !ok || !strings.EqualFold(v, captcha) { - c.JsonResult(6001, "验证码不正确") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.captcha_wrong")) } } member, err := models.NewMember().FindByFieldFirst("email", email) if err != nil { - c.JsonResult(6006, "邮箱不存在") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.email_not_exist")) } - if member.Status != 0 { - c.JsonResult(6007, "账号已被禁用") + if member == nil || member.Status != 0 { + c.JsonResult(6007, i18n.Tr(c.Lang, "message.account_disable")) } - if member.AuthMethod == conf.AuthMethodLDAP { - c.JsonResult(6011, "当前用户不支持找回密码") + if member == nil || member.AuthMethod == conf.AuthMethodLDAP { + c.JsonResult(6011, i18n.Tr(c.Lang, "message.account_not_support_retrieval")) } count, err := models.NewMemberToken().FindSendCount(email, time.Now().Add(-1*time.Hour), time.Now()) if err != nil { logs.Error(err) - c.JsonResult(6008, "发送邮件失败") + c.JsonResult(6008, i18n.Tr(c.Lang, "message.failed_send_mail")) } if count > mailConf.MailNumber { - c.JsonResult(6008, "发送次数太多,请稍候再试") + c.JsonResult(6008, i18n.Tr(c.Lang, "message.sent_too_many_times")) } memberToken := models.NewMemberToken() @@ -402,7 +403,7 @@ func (c *AccountController) FindPassword() { memberToken.MemberId = member.MemberId memberToken.IsValid = false if _, err := memberToken.InsertOrUpdate(); err != nil { - c.JsonResult(6009, "邮件发送失败") + c.JsonResult(6009, i18n.Tr(c.Lang, "message.failed_send_mail")) } data := map[string]interface{}{ @@ -414,7 +415,7 @@ func (c *AccountController) FindPassword() { body, err := c.ExecuteViewPathTemplate("account/mail_template.tpl", data) if err != nil { logs.Error(err) - c.JsonResult(6003, "邮件发送失败") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed_send_mail")) } go func(mailConf *conf.SmtpConf, email string, body string) { @@ -473,17 +474,16 @@ func (c *AccountController) FindPassword() { if token != "" && email != "" { memberToken, err := models.NewMemberToken().FindByFieldFirst("token", token) - if err != nil { logs.Error(err) - c.Data["ErrorMessage"] = "邮件已失效" + c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.mail_expired") c.TplName = "errors/error.tpl" return } subTime := time.Until(memberToken.SendTime) if !strings.EqualFold(memberToken.Email, email) || subTime.Minutes() > float64(mailConf.MailExpired) || !memberToken.ValidTime.IsZero() { - c.Data["ErrorMessage"] = "验证码已过期,请重新操作。" + c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.captcha_expired") c.TplName = "errors/error.tpl" return } @@ -504,48 +504,46 @@ func (c *AccountController) ValidEmail() { email := c.GetString("mail") if password1 == "" { - c.JsonResult(6001, "密码不能为空") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.password_empty")) } if l := strings.Count(password1, ""); l < 6 || l > 50 { - c.JsonResult(6001, "密码不能为空且必须在6-50个字符之间") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.password_length_invalid")) } if password2 == "" { - c.JsonResult(6002, "确认密码不能为空") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.confirm_password_empty")) } if password1 != password2 { - c.JsonResult(6003, "确认密码输入不正确") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.incorrect_confirm_password")) } if captcha == "" { - c.JsonResult(6004, "验证码不能为空") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.captcha_empty")) } v, ok := c.GetSession(conf.CaptchaSessionName).(string) if !ok || !strings.EqualFold(v, captcha) { - c.JsonResult(6001, "验证码不正确") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.captcha_wrong")) } mailConf := conf.GetMailConfig() memberToken, err := models.NewMemberToken().FindByFieldFirst("token", token) - if err != nil { logs.Error(err) - c.JsonResult(6007, "邮件已失效") + c.JsonResult(6007, i18n.Tr(c.Lang, "message.mail_expired")) } subTime := time.Until(memberToken.SendTime) if !strings.EqualFold(memberToken.Email, email) || subTime.Minutes() > float64(mailConf.MailExpired) || !memberToken.ValidTime.IsZero() { - c.JsonResult(6008, "验证码已过期,请重新操作。") + c.JsonResult(6008, i18n.Tr(c.Lang, "message.captcha_expired")) } member, err := models.NewMember().Find(memberToken.MemberId) if err != nil { logs.Error(err) - c.JsonResult(6005, "用户不存在") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.user_not_existed")) } hash, err := utils.PasswordHash(password1) - if err != nil { logs.Error(err) - c.JsonResult(6006, "保存密码失败") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed_save_password")) } member.Password = hash @@ -557,7 +555,7 @@ func (c *AccountController) ValidEmail() { if err != nil { logs.Error(err) - c.JsonResult(6006, "保存密码失败") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed_save_password")) } c.JsonResult(0, "ok", conf.URLFor("AccountController.Login")) } @@ -565,11 +563,8 @@ func (c *AccountController) ValidEmail() { // Logout 退出登录 func (c *AccountController) Logout() { c.SetMember(models.Member{}) - c.SetSecureCookie(conf.GetAppKey(), "login", "", -3600) - u := c.Ctx.Request.Header.Get("Referer") - c.Redirect(conf.URLFor("AccountController.Login", "url", u), 302) } @@ -579,11 +574,6 @@ func (c *AccountController) Captcha() { captchaImage := gocaptcha.NewCaptchaImage(140, 40, gocaptcha.RandLightColor()) - //if err != nil { - // logs.Error(err) - // c.Abort("500") - //} - captchaImage.DrawNoise(gocaptcha.CaptchaComplexLower) // captchaImage.DrawTextNoise(gocaptcha.CaptchaComplexHigh) diff --git a/controllers/BaseController.go b/controllers/BaseController.go index ff48bf96..7e2a5571 100644 --- a/controllers/BaseController.go +++ b/controllers/BaseController.go @@ -2,7 +2,6 @@ package controllers import ( "bytes" - "encoding/json" "io" "strings" @@ -14,6 +13,7 @@ import ( "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/models" "github.com/mindoc-org/mindoc/utils" @@ -25,6 +25,7 @@ type BaseController struct { Option map[string]string EnableAnonymous bool EnableDocumentHistory bool + Lang string } type CookieRemember struct { @@ -46,7 +47,6 @@ func (c *BaseController) Prepare() { c.EnableDocumentHistory = false if member, ok := c.GetSession(conf.LoginSessionName).(models.Member); ok && member.MemberId > 0 { - c.Member = &member c.Data["Member"] = c.Member } else { @@ -80,6 +80,7 @@ func (c *BaseController) Prepare() { c.Data["Scripts"] = template.HTML(string(b)) } + c.SetLang() } //判断用户是否登录. @@ -112,14 +113,16 @@ func (c *BaseController) JsonResult(errCode int, errMsg string, data ...interfac } returnJSON, err := json.Marshal(jsonData) - if err != nil { logs.Error(err) } c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json; charset=utf-8") c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache, no-store") - io.WriteString(c.Ctx.ResponseWriter, string(returnJSON)) + _, err = io.WriteString(c.Ctx.ResponseWriter, string(returnJSON)) + if err != nil { + logs.Error(err) + } c.StopRun() } @@ -136,14 +139,16 @@ func (c *BaseController) CheckJsonError(code int, err error) { jsonData["message"] = err.Error() returnJSON, err := json.Marshal(jsonData) - if err != nil { logs.Error(err) } c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json; charset=utf-8") c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache, no-store") - io.WriteString(c.Ctx.ResponseWriter, string(returnJSON)) + _, err = io.WriteString(c.Ctx.ResponseWriter, string(returnJSON)) + if err != nil { + logs.Error(err) + } c.StopRun() } @@ -201,3 +206,21 @@ func (c *BaseController) CheckErrorResult(code int, err error) { c.ShowErrorPage(code, err.Error()) } } + +func (c *BaseController) SetLang() { + hasCookie := false + lang := c.GetString("lang") + if len(lang) == 0 { + lang = c.Ctx.GetCookie("lang") + hasCookie = true + } + if len(lang) == 0 || + !i18n.IsExist(lang) { + lang, _ = web.AppConfig.String("default_lang") + } + if !hasCookie { + c.Ctx.SetCookie("lang", lang, 1<<31-1, "/") + } + c.Data["Lang"] = lang + c.Lang = lang +} diff --git a/controllers/BlogController.go b/controllers/BlogController.go index 5ff07b05..79cae45a 100644 --- a/controllers/BlogController.go +++ b/controllers/BlogController.go @@ -16,6 +16,7 @@ import ( "github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/models" "github.com/mindoc-org/mindoc/utils" @@ -40,20 +41,20 @@ func (c *BlogController) Index() { blogId, _ := strconv.Atoi(c.Ctx.Input.Param(":id")) if blogId <= 0 { - c.ShowErrorPage(404, "页面不存在") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.page_not_existed")) } blogReadSession := fmt.Sprintf("blog:read:%d", blogId) blog, err := models.NewBlog().FindFromCache(blogId) if err != nil { - c.ShowErrorPage(404, "文章不存在") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.blog_not_existed")) } if c.Ctx.Input.IsPost() { password := c.GetString("password") if blog.BlogStatus == "password" && password != blog.Password { - c.JsonResult(6001, "文章密码不正确") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.blog_pwd_incorrect")) } else if blog.BlogStatus == "password" && password == blog.Password { //如果密码输入正确,则存入session中 _ = c.CruSession.Set(context.TODO(), blogReadSession, blogId) @@ -160,33 +161,33 @@ func (c *BlogController) ManageSetting() { documentId := 0 if blogTitle == "" { - c.JsonResult(6001, "文章标题不能为空") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.blog_title_empty")) } if strings.Count(blogExcerpt, "") > 500 { - c.JsonResult(6008, "文章摘要必须小于500字符") + c.JsonResult(6008, i18n.Tr(c.Lang, "message.blog_digest_tips")) } if blogStatus != "public" && blogStatus != "password" && blogStatus != "draft" { blogStatus = "public" } if blogStatus == "password" && blogPassword == "" { - c.JsonResult(6010, "加密文章请设置密码") + c.JsonResult(6010, i18n.Tr(c.Lang, "message.set_pwd_pls")) } if blogType != 0 && blogType != 1 { - c.JsonResult(6005, "未知的文章类型") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.unknown_blog_type")) } if strings.Count(blogTitle, "") > 200 { - c.JsonResult(6002, "文章标题不能大于200个字符") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.blog_title_tips")) } //如果是关联文章,需要同步关联的文档 if blogType == 1 { book, err := models.NewBook().FindByIdentify(bookIdentify) if err != nil { - c.JsonResult(6011, "关联文档的项目不存在") + c.JsonResult(6011, i18n.Tr(c.Lang, "message.ref_doc_not_exist_or_no_permit")) } doc, err := models.NewDocument().FindByIdentityFirst(documentIdentify, book.BookId) if err != nil { - c.JsonResult(6003, "查询关联项目文档时出错") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.query_failed")) } documentId = doc.DocumentId @@ -195,7 +196,7 @@ func (c *BlogController) ManageSetting() { bookResult, err := models.NewBookResult().FindByIdentify(book.Identify, c.Member.MemberId) if err != nil || bookResult.RoleId == conf.BookObserver { - c.JsonResult(6002, "关联文档不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.ref_doc_not_exist_or_no_permit")) } } } @@ -211,13 +212,13 @@ func (c *BlogController) ManageSetting() { } if err != nil { - c.JsonResult(6003, "文章不存在") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.blog_not_exist")) } //如果设置了文章标识 if blogIdentify != "" { //如果查询到的文章标识存在并且不是当前文章的id if b, err := models.NewBlog().FindByIdentify(blogIdentify); err == nil && b.BlogId != blogId { - c.JsonResult(6004, "文章标识已存在") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.blog_id_existed")) } } blog.Modified = time.Now() @@ -226,7 +227,7 @@ func (c *BlogController) ManageSetting() { //如果设置了文章标识 if blogIdentify != "" { if models.NewBlog().IsExist(blogIdentify) { - c.JsonResult(6004, "文章标识已存在") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.blog_id_existed")) } } @@ -253,7 +254,7 @@ func (c *BlogController) ManageSetting() { if err := blog.Save(); err != nil { logs.Error("保存文章失败 -> ", err) - c.JsonResult(6011, "保存文章失败") + c.JsonResult(6011, i18n.Tr(c.Lang, "message.failed")) } else { c.JsonResult(0, "ok", blog) } @@ -287,7 +288,7 @@ func (c *BlogController) ManageEdit() { blogId, _ := c.GetInt("blogId", 0) if blogId <= 0 { - c.JsonResult(6001, "文章参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } blogContent := c.GetString("content", "") blogHtml := c.GetString("htmlContent", "") @@ -304,21 +305,21 @@ func (c *BlogController) ManageEdit() { } if err != nil { logs.Error("查询文章失败 ->", err) - c.JsonResult(6002, "查询文章失败") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.query_failed")) } if version > 0 && blog.Version != version && cover != "yes" { - c.JsonResult(6005, "文章已被修改") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.blog_has_modified")) } //如果是关联文章,需要同步关联的文档 if blog.BlogType == 1 { doc, err := models.NewDocument().Find(blog.DocumentId) if err != nil { logs.Error("查询关联项目文档时出错 ->", err) - c.JsonResult(6003, "查询关联项目文档时出错") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.query_failed")) } book, err := models.NewBook().Find(doc.BookId) if err != nil { - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } // 如果不是超级管理员,则校验权限 @@ -327,7 +328,7 @@ func (c *BlogController) ManageEdit() { if err != nil || bookResult.RoleId == conf.BookObserver { logs.Error("FindByIdentify => ", err) - c.JsonResult(6002, "关联文档不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.ref_doc_not_exist_or_no_permit")) } } @@ -338,7 +339,7 @@ func (c *BlogController) ManageEdit() { doc.ModifyAt = c.Member.MemberId if err := doc.InsertOrUpdate("markdown", "release", "content", "modify_time", "modify_at"); err != nil { logs.Error("保存关联文档时出错 ->", err) - c.JsonResult(6004, "保存关联文档时出错") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.failed")) } } @@ -349,7 +350,7 @@ func (c *BlogController) ManageEdit() { if err := blog.Save("blog_content", "blog_release", "modify_at", "modify_time", "version"); err != nil { logs.Error("保存文章失败 -> ", err) - c.JsonResult(6011, "保存文章失败") + c.JsonResult(6011, i18n.Tr(c.Lang, "message.failed")) } else { c.JsonResult(0, "ok", blog) } @@ -358,7 +359,7 @@ func (c *BlogController) ManageEdit() { blogId, _ := strconv.Atoi(c.Ctx.Input.Param(":id")) if blogId <= 0 { - c.ShowErrorPage(500, "参数错误") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.param_error")) } var blog *models.Blog var err error @@ -369,7 +370,7 @@ func (c *BlogController) ManageEdit() { blog, err = models.NewBlog().FindByIdAndMemberId(blogId, c.Member.MemberId) } if err != nil { - c.ShowErrorPage(404, "文章不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.blog_not_exist")) } blog.LinkAttach() @@ -397,7 +398,7 @@ func (c *BlogController) ManageDelete() { blogId, _ := c.GetInt("blog_id", 0) if blogId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } var blog *models.Blog var err error @@ -408,13 +409,13 @@ func (c *BlogController) ManageDelete() { blog, err = models.NewBlog().FindByIdAndMemberId(blogId, c.Member.MemberId) } if err != nil { - c.JsonResult(6002, "文章不存在或已删除") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.blog_not_exist")) } if err := blog.Delete(blogId); err != nil { - c.JsonResult(6003, "删除失败") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed")) } else { - c.JsonResult(0, "删除成功") + c.JsonResult(0, i18n.Tr(c.Lang, "message.success")) } } @@ -425,16 +426,16 @@ func (c *BlogController) Upload() { blogId, _ := c.GetInt("blogId") if blogId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } blog, err := models.NewBlog().Find(blogId) if err != nil { - c.JsonResult(6010, "文章不存在") + c.JsonResult(6010, i18n.Tr(c.Lang, "message.blog_not_exist")) } if !c.Member.IsAdministrator() && blog.MemberId != c.Member.MemberId { - c.JsonResult(6011, "没有文章的访问权限") + c.JsonResult(6011, i18n.Tr(c.Lang, "message.no_permission")) } name := "editormd-file-file" @@ -444,7 +445,7 @@ func (c *BlogController) Upload() { name = "editormd-image-file" file, moreFile, err = c.GetFile(name) if err == http.ErrMissingFile { - c.JsonResult(6003, "没有发现需要上传的图片") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_empty")) } } @@ -459,18 +460,18 @@ func (c *BlogController) Upload() { } if conf.GetUploadFileSize() > 0 && moreFile.Size > conf.GetUploadFileSize() { - c.JsonResult(6009, "查过文件允许的上传最大值") + c.JsonResult(6009, i18n.Tr(c.Lang, "message.upload_file_size_limit")) } ext := filepath.Ext(moreFile.Filename) if ext == "" { - c.JsonResult(6003, "无法解析文件的格式") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_type_error")) } //如果文件类型设置为 * 标识不限制文件类型 if web.AppConfig.DefaultString("upload_file_ext", "") != "*" { if !conf.IsAllowUploadFileExt(ext) { - c.JsonResult(6004, "不允许的文件类型") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.upload_file_type_error")) } } @@ -479,7 +480,7 @@ func (c *BlogController) Upload() { _, err := models.NewBlog().Find(blogId) if err != nil { - c.JsonResult(6006, "文档不存在或权限不足") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.doc_not_exist_or_no_permit")) } } else { @@ -488,7 +489,7 @@ func (c *BlogController) Upload() { if err != nil { logs.Error("查询文章时出错 -> ", err) if err == orm.ErrNoRows { - c.JsonResult(6006, "权限不足") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.no_permission")) } c.JsonResult(6001, err.Error()) @@ -507,7 +508,7 @@ func (c *BlogController) Upload() { if err != nil { logs.Error("SaveToFile => ", err) - c.JsonResult(6005, "保存文件失败") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed")) } var httpPath string @@ -540,14 +541,14 @@ func (c *BlogController) Upload() { if err := attachment.Insert(); err != nil { os.Remove(filePath) logs.Error("保存文件附件失败 -> ", err) - c.JsonResult(6006, "文件保存失败") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed")) } if attachment.HttpPath == "" { attachment.HttpPath = conf.URLForNotHost("BlogController.Download", ":id", blogId, ":attach_id", attachment.AttachmentId) if err := attachment.Update(); err != nil { logs.Error("保存文件失败 -> ", attachment.FilePath, err) - c.JsonResult(6005, "保存文件失败") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed")) } } result["attach"] = attachment @@ -570,21 +571,21 @@ func (c *BlogController) RemoveAttachment() { blogId, _ := strconv.Atoi(c.Ctx.Input.Param(":id")) if attachId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } blog, err := models.NewBlog().Find(blogId) if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(500, "文档不存在") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.doc_not_exist")) } else { - c.ShowErrorPage(500, "查询文章时异常") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.query_failed")) } } attach, err := models.NewAttachment().Find(attachId) if err != nil { logs.Error(err) - c.JsonResult(6002, "附件不存在") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.attachment_not_exist")) } if !c.Member.IsAdministrator() { @@ -592,19 +593,19 @@ func (c *BlogController) RemoveAttachment() { if err != nil { logs.Error(err) - c.JsonResult(6003, "文档不存在") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.doc_not_exist")) } } if blog.BlogType == 1 && attach.BookId != blog.BookId && attach.DocumentId != blog.DocumentId { - c.ShowErrorPage(404, "附件不存在") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist")) } else if attach.BookId != 0 || attach.DocumentId != blogId { - c.ShowErrorPage(404, "附件不存在") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist")) } if err := attach.Delete(); err != nil { logs.Error(err) - c.JsonResult(6005, "删除失败") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed")) } os.Remove(filepath.Join(conf.WorkingDirectory, attach.FilePath)) @@ -623,15 +624,15 @@ func (c *BlogController) Download() { blog, err := models.NewBlog().Find(blogId) if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(500, "文档不存在") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.doc_not_exist")) } else { - c.ShowErrorPage(500, "查询文章时异常") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.query_failed")) } } blogReadSession := fmt.Sprintf("blog:read:%d", blogId) //如果没有启动匿名访问,或者设置了访问密码 if (c.Member == nil && !c.EnableAnonymous) || (blog.BlogStatus == "password" && password != blog.Password && c.CruSession.Get(context.TODO(), blogReadSession) == nil) { - c.ShowErrorPage(403, "没有下载权限") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) } // 查找附件 @@ -639,18 +640,18 @@ func (c *BlogController) Download() { if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(404, "附件不存在") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist")) } else { logs.Error("查询附件时出现异常 -> ", err) - c.ShowErrorPage(500, "查询附件时出现异常") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.query_failed")) } } //如果是链接的文章,需要校验文档ID是否一致,如果不是,需要保证附件的项目ID为0且文档的ID等于博文ID if blog.BlogType == 1 && attachment.DocumentId != blog.DocumentId { - c.ShowErrorPage(404, "附件不存在") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist")) } else if blog.BlogType != 1 && (attachment.BookId != 0 || attachment.DocumentId != blogId) { - c.ShowErrorPage(404, "附件不存在") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist")) } c.Ctx.Output.Download(filepath.Join(conf.WorkingDirectory, attachment.FilePath), attachment.FileName) diff --git a/controllers/BookController.go b/controllers/BookController.go index 7e104cbd..669d3a29 100644 --- a/controllers/BookController.go +++ b/controllers/BookController.go @@ -13,6 +13,7 @@ import ( "strings" "time" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/utils/sqltil" "net/http" @@ -37,7 +38,7 @@ func (c *BookController) Index() { pageIndex, _ := c.GetInt("page", 1) - books, totalCount, err := models.NewBook().FindToPager(pageIndex, conf.PageSize, c.Member.MemberId) + books, totalCount, err := models.NewBook().FindToPager(pageIndex, conf.PageSize, c.Member.MemberId, c.Lang) if err != nil { logs.Error("BookController.Index => ", err) @@ -79,7 +80,7 @@ func (c *BookController) Dashboard() { c.Abort("404") } - book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId) + book, err := models.NewBookResult().SetLang(c.Lang).FindByIdentify(key, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { c.Abort("403") @@ -154,14 +155,14 @@ func (c *BookController) SaveBook() { itemId, _ := c.GetInt("itemId") if strings.Count(description, "") > 500 { - c.JsonResult(6004, "项目描述不能大于500字") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_desc_tips")) } if commentStatus != "open" && commentStatus != "closed" && commentStatus != "group_only" && commentStatus != "registered_only" { commentStatus = "closed" } if !models.NewItemsets().Exist(itemId) { - c.JsonResult(6006, "项目空间不存在") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_space_not_exist")) } if editor != "markdown" && editor != "html" { editor = "markdown" @@ -204,7 +205,7 @@ func (c *BookController) SaveBook() { book.AutoSave = 0 } if err := book.Update(); err != nil { - c.JsonResult(6006, "保存失败") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed")) } bookResult.BookName = bookName bookResult.Description = description @@ -221,7 +222,7 @@ func (c *BookController) PrivatelyOwned() { status := c.GetString("status") if status != "open" && status != "close" { - c.JsonResult(6003, "参数错误") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.param_error")) } state := 0 if status == "open" { @@ -238,13 +239,13 @@ func (c *BookController) PrivatelyOwned() { } //只有创始人才能变更私有状态 if bookResult.RoleId != conf.BookFounder { - c.JsonResult(6002, "权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.no_permission")) } book, err := models.NewBook().Find(bookResult.BookId) if err != nil { - c.JsonResult(6005, "项目不存在") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.item_not_exist")) return } book.PrivatelyOwned = state @@ -253,7 +254,7 @@ func (c *BookController) PrivatelyOwned() { if err != nil { logs.Error("PrivatelyOwned => ", err) - c.JsonResult(6004, "保存失败") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.failed")) } logs.Info("用户 【", c.Member.Account, "]修改了项目权限 ->", state) c.JsonResult(0, "ok") @@ -265,19 +266,19 @@ func (c *BookController) Transfer() { account := c.GetString("account") if account == "" { - c.JsonResult(6004, "接受者账号不能为空") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.receive_account_empty")) } member, err := models.NewMember().FindByAccount(account) if err != nil { logs.Error("FindByAccount => ", err) - c.JsonResult(6005, "接受用户不存在") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.receive_account_not_exist")) } if member.Status != 0 { - c.JsonResult(6006, "接受用户已被禁用") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.receive_account_disabled")) } if member.MemberId == c.Member.MemberId { - c.JsonResult(6007, "不能转让给自己") + c.JsonResult(6007, i18n.Tr(c.Lang, "message.cannot_handover_myself")) } bookResult, err := c.IsPermission() @@ -404,7 +405,7 @@ func (c *BookController) Users() { pageIndex, _ := c.GetInt("page", 1) if key == "" { - c.ShowErrorPage(404, "项目不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist")) } book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId) @@ -421,7 +422,7 @@ func (c *BookController) Users() { } c.Data["Model"] = *book - members, totalCount, err := models.NewMemberRelationshipResult().FindForUsersByBookId(book.BookId, pageIndex, conf.PageSize) + members, totalCount, err := models.NewMemberRelationshipResult().FindForUsersByBookId(c.Lang, book.BookId, pageIndex, conf.PageSize) if totalCount > 0 { pager := pagination.NewPagination(c.Ctx.Request, totalCount, conf.PageSize, c.BaseUrl()) @@ -450,25 +451,25 @@ func (c *BookController) Create() { itemId, _ := c.GetInt("itemId") if bookName == "" { - c.JsonResult(6001, "项目名称不能为空") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.project_name_empty")) } if identify == "" { - c.JsonResult(6002, "项目标识不能为空") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.project_id_empty")) } if ok, err := regexp.MatchString(`^[a-z]+[a-zA-Z0-9_\-]*$`, identify); !ok || err != nil { - c.JsonResult(6003, "项目标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.project_id_tips")) } if strings.Count(identify, "") > 50 { - c.JsonResult(6004, "文档标识不能超过50字") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_id_length")) } if strings.Count(description, "") > 500 { - c.JsonResult(6004, "项目描述不能大于500字") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_desc_tips")) } if privatelyOwned != 0 && privatelyOwned != 1 { privatelyOwned = 1 } if !models.NewItemsets().Exist(itemId) { - c.JsonResult(6005, "项目空间不存在") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.project_space_not_exist")) } if commentStatus != "open" && commentStatus != "closed" && commentStatus != "group_only" && commentStatus != "registered_only" { commentStatus = "closed" @@ -505,7 +506,7 @@ func (c *BookController) Create() { } if books, _ := book.FindByField("identify", identify, "book_id"); len(books) > 0 { - c.JsonResult(6006, "项目标识已存在") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_id_existed")) } book.BookName = bookName @@ -527,9 +528,9 @@ func (c *BookController) Create() { book.Editor = "markdown" book.Theme = "default" - if err := book.Insert(); err != nil { + if err := book.Insert(c.Lang); err != nil { logs.Error("Insert => ", err) - c.JsonResult(6005, "保存项目失败") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed")) } bookResult, err := models.NewBookResult().FindByIdentify(book.Identify, c.Member.MemberId) @@ -553,7 +554,7 @@ func (c *BookController) Copy() { identify := strings.TrimSpace(c.GetString("identify", "")) if identify == "" { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } book := models.NewBook() err := book.Copy(identify) @@ -586,22 +587,22 @@ func (c *BookController) Import() { itemId, _ := c.GetInt("itemId") if bookName == "" { - c.JsonResult(6001, "项目名称不能为空") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.project_name_empty")) } if len([]rune(bookName)) > 500 { c.JsonResult(6002, "项目名称不能大于500字") } if identify == "" { - c.JsonResult(6002, "项目标识不能为空") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.project_id_empty")) } if ok, err := regexp.MatchString(`^[a-z]+[a-zA-Z0-9_\-]*$`, identify); !ok || err != nil { - c.JsonResult(6003, "项目标识只能包含小写字母、数字,以及“-”和“_”符号,并且只能小写字母开头") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.project_id_tips")) } if !models.NewItemsets().Exist(itemId) { - c.JsonResult(6007, "项目空间不存在") + c.JsonResult(6007, i18n.Tr(c.Lang, "message.project_space_not_exist")) } if strings.Count(identify, "") > 50 { - c.JsonResult(6004, "文档标识不能超过50字") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_id_length")) } ext := filepath.Ext(moreFile.Filename) @@ -611,7 +612,7 @@ func (c *BookController) Import() { } if books, _ := models.NewBook().FindByField("identify", identify, "book_id"); len(books) > 0 { - c.JsonResult(6006, "项目标识已存在") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_id_existed")) } tempPath := filepath.Join(os.TempDir(), c.CruSession.SessionID(context.TODO())) @@ -641,7 +642,7 @@ func (c *BookController) Import() { book.Editor = "markdown" book.Theme = "default" - go book.ImportBook(tempPath) + go book.ImportBook(tempPath, c.Lang) logs.Info("用户[", c.Member.Account, "]导入了项目 ->", book) @@ -657,10 +658,10 @@ func (c *BookController) Import() { // // if err != nil { // if err == models.ErrPermissionDenied { -// c.JsonResult(403, "权限不足") +// c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission")) // } // if err == orm.ErrNoRows { -// c.JsonResult(404, "项目不存在") +// c.JsonResult(404, i18n.Tr(c.Lang, "message.item_not_exist")) // } // logs.Error("生成阅读令牌失败 =>", err) // c.JsonResult(6002, err.Error()) @@ -668,7 +669,7 @@ func (c *BookController) Import() { // book := models.NewBook() // // if _, err := book.Find(bookResult.BookId); err != nil { -// c.JsonResult(6001, "项目不存在") +// c.JsonResult(6001, i18n.Tr(c.Lang, "message.item_not_exist")) // } // if action == "create" { // if bookResult.PrivatelyOwned == 0 { @@ -710,7 +711,7 @@ func (c *BookController) Delete() { err = models.NewBook().ThoroughDeleteBook(bookResult.BookId) if err == orm.ErrNoRows { - c.JsonResult(6002, "项目不存在") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist")) } if err != nil { logs.Error("删除项目 => ", err) @@ -741,22 +742,22 @@ func (c *BookController) Release() { if err != nil { if err == models.ErrPermissionDenied { - c.JsonResult(6001, "权限不足") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.no_permission")) } if err == orm.ErrNoRows { - c.JsonResult(6002, "项目不存在") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist")) } logs.Error(err) - c.JsonResult(6003, "未知错误") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.unknown_exception")) } if book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder && book.RoleId != conf.BookEditor { - c.JsonResult(6003, "权限不足") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.no_permission")) } bookId = book.BookId } - go models.NewBook().ReleaseContent(bookId) + go models.NewBook().ReleaseContent(bookId, c.Lang) - c.JsonResult(0, "发布任务已推送到任务队列,稍后将在后台执行。") + c.JsonResult(0, i18n.Tr(c.Lang, "message.publish_to_queue")) } //文档排序. @@ -772,7 +773,7 @@ func (c *BookController) SaveSort() { if c.Member.IsAdministrator() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil || book == nil { - c.JsonResult(6001, "项目不存在") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.item_not_exist")) return } bookId = book.BookId @@ -784,7 +785,7 @@ func (c *BookController) SaveSort() { c.Abort("403") } if bookResult.RoleId == conf.BookObserver { - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } bookId = bookResult.BookId } @@ -808,7 +809,7 @@ func (c *BookController) SaveSort() { continue } if doc.BookId != bookId { - logs.Info("%s", "权限错误") + logs.Info("%s", i18n.Tr(c.Lang, "message.no_permission")) continue } sort, ok := item["sort"].(float64) @@ -848,15 +849,15 @@ func (c *BookController) Team() { pageIndex, _ := c.GetInt("page", 1) if key == "" { - c.ShowErrorPage(404, "项目不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist")) } book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId) if err != nil || book == nil { if err == models.ErrPermissionDenied { - c.ShowErrorPage(403, "权限不足") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) } - c.ShowErrorPage(500, "系统错误") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error")) return } //如果不是创始人也不是管理员则不能操作 @@ -927,7 +928,7 @@ func (c *BookController) TeamDelete() { teamId, _ := c.GetInt("teamId") if teamId <= 0 { - c.JsonResult(5001, "参数错误") + c.JsonResult(5001, i18n.Tr(c.Lang, "message.param_error")) } book, err := c.IsPermission() @@ -992,22 +993,22 @@ func (c *BookController) IsPermission() (*models.BookResult, error) { identify := c.GetString("identify") if identify == "" { - return nil, errors.New("参数错误") + return nil, errors.New(i18n.Tr(c.Lang, "message.param_error")) } book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { - return book, errors.New("权限不足") + return book, errors.New(i18n.Tr(c.Lang, "message.no_permission")) } if err == orm.ErrNoRows { - return book, errors.New("项目不存在") + return book, errors.New(i18n.Tr(c.Lang, "message.item_not_exist")) } return book, err } if book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder { - return book, errors.New("权限不足") + return book, errors.New(i18n.Tr(c.Lang, "message.no_permission")) } return book, nil } diff --git a/controllers/BookMemberController.go b/controllers/BookMemberController.go index 38c33f1d..df0d7020 100644 --- a/controllers/BookMemberController.go +++ b/controllers/BookMemberController.go @@ -5,6 +5,7 @@ import ( "github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/core/logs" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/models" ) @@ -20,7 +21,7 @@ func (c *BookMemberController) AddMember() { roleId, _ := c.GetInt("role_id", 3) logs.Info(account) if identify == "" || account <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } book, err := c.IsPermission() @@ -31,14 +32,14 @@ func (c *BookMemberController) AddMember() { member := models.NewMember() if _, err := member.Find(account); err != nil { - c.JsonResult(404, "用户不存在") + c.JsonResult(404, i18n.Tr(c.Lang, "message.user_not_existed")) } if member.Status == 1 { - c.JsonResult(6003, "用户已被禁用") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.user_disable")) } if _, err := models.NewRelationship().FindForRoleId(book.BookId, member.MemberId); err == nil { - c.JsonResult(6003, "用户已存在该项目中") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.user_exist_in_proj")) } relationship := models.NewRelationship() @@ -51,7 +52,7 @@ func (c *BookMemberController) AddMember() { memberRelationshipResult.RoleId = conf.BookRole(roleId) memberRelationshipResult.RelationshipId = relationship.RelationshipId memberRelationshipResult.BookId = book.BookId - memberRelationshipResult.ResolveRoleName() + memberRelationshipResult.ResolveRoleName(c.Lang) c.JsonResult(0, "ok", memberRelationshipResult) } @@ -65,33 +66,33 @@ func (c *BookMemberController) ChangeRole() { role, _ := c.GetInt("role_id", 0) if identify == "" || memberId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } if memberId == c.Member.MemberId { - c.JsonResult(6006, "不能变更自己的权限") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.cannot_change_own_priv")) } book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { - c.JsonResult(403, "权限不足") + c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission")) } if err == orm.ErrNoRows { - c.JsonResult(404, "项目不存在") + c.JsonResult(404, i18n.Tr(c.Lang, "message.item_not_exist")) } c.JsonResult(6002, err.Error()) } if book.RoleId != 0 && book.RoleId != 1 { - c.JsonResult(403, "权限不足") + c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission")) } member := models.NewMember() if _, err := member.Find(memberId); err != nil { - c.JsonResult(6003, "用户不存在") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.user_not_existed")) } if member.Status == 1 { - c.JsonResult(6004, "用户已被禁用") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.user_disable")) } relationship, err := models.NewRelationship().UpdateRoleId(book.BookId, memberId, conf.BookRole(role)) @@ -105,7 +106,7 @@ func (c *BookMemberController) ChangeRole() { memberRelationshipResult.RoleId = relationship.RoleId memberRelationshipResult.RelationshipId = relationship.RelationshipId memberRelationshipResult.BookId = book.BookId - memberRelationshipResult.ResolveRoleName() + memberRelationshipResult.ResolveRoleName(c.Lang) c.JsonResult(0, "ok", memberRelationshipResult) } @@ -116,25 +117,25 @@ func (c *BookMemberController) RemoveMember() { member_id, _ := c.GetInt("member_id", 0) if identify == "" || member_id <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } if member_id == c.Member.MemberId { - c.JsonResult(6006, "不能删除自己") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.cannot_delete_self")) } book, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { - c.JsonResult(403, "权限不足") + c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission")) } if err == orm.ErrNoRows { - c.JsonResult(404, "项目不存在") + c.JsonResult(404, i18n.Tr(c.Lang, "message.item_not_exist")) } c.JsonResult(6002, err.Error()) } //如果不是创始人也不是管理员则不能操作 if book.RoleId != conf.BookFounder && book.RoleId != conf.BookAdmin { - c.JsonResult(403, "权限不足") + c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission")) } err = models.NewRelationship().DeleteByBookIdAndMemberId(book.BookId, member_id) @@ -150,15 +151,15 @@ func (c *BookMemberController) IsPermission() (*models.BookResult, error) { if err != nil { if err == models.ErrPermissionDenied { - return book, errors.New("权限不足") + return book, errors.New(i18n.Tr(c.Lang, "message.no_permission")) } if err == orm.ErrNoRows { - return book, errors.New("项目不存在") + return book, errors.New(i18n.Tr(c.Lang, "message.item_not_exist")) } return book, err } if book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder { - return book, errors.New("权限不足") + return book, errors.New(i18n.Tr(c.Lang, "message.no_permission")) } return book, nil } diff --git a/controllers/DocumentController.go b/controllers/DocumentController.go index 9633745a..0d3eb4b0 100644 --- a/controllers/DocumentController.go +++ b/controllers/DocumentController.go @@ -18,6 +18,7 @@ import ( "github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" + "github.com/beego/i18n" "github.com/boombuler/barcode" "github.com/boombuler/barcode/qr" "github.com/mindoc-org/mindoc/conf" @@ -43,7 +44,7 @@ func (c *DocumentController) Index() { token := c.GetString("token") if identify == "" { - c.ShowErrorPage(404, "项目不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist")) } // 如果没有开启匿名访问则跳转到登录 @@ -68,7 +69,7 @@ func (c *DocumentController) Index() { c.Data["Description"] = utils.AutoSummary(doc.Release, 120) } } else { - c.Data["Title"] = "概要" + c.Data["Title"] = i18n.Tr(c.Lang, "blog.summary") c.Data["Content"] = template.HTML(blackfriday.Run([]byte(bookResult.Description))) } @@ -76,10 +77,10 @@ func (c *DocumentController) Index() { if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(404, "当前项目没有文档") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.no_doc_in_cur_proj")) } else { logs.Error("生成项目文档树时出错 -> ", err) - c.ShowErrorPage(500, "生成项目文档树时出错") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.build_doc_tree_error")) } } c.Data["Model"] = bookResult @@ -98,7 +99,7 @@ func (c *DocumentController) Read() { c.Data["DocumentId"] = id if identify == "" || id == "" { - c.ShowErrorPage(404, "项目不存或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist")) } // 如果没有开启匿名访问则跳转到登录 @@ -112,31 +113,30 @@ func (c *DocumentController) Read() { c.TplName = fmt.Sprintf("document/%s_read.tpl", bookResult.Theme) doc := models.NewDocument() - if docId, err := strconv.Atoi(id); err == nil { doc, err = doc.FromCacheById(docId) if err != nil || doc == nil { logs.Error("从缓存中读取文档时失败 ->", err) - c.ShowErrorPage(404, "文档不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.doc_not_exist")) return } } else { doc, err = doc.FromCacheByIdentify(id, bookResult.BookId) if err != nil || doc == nil { if err == orm.ErrNoRows { - c.ShowErrorPage(404, "文档不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.doc_not_exist")) } else { - logs.Error("从缓存查询文档时出错 ->", err) - c.ShowErrorPage(500, "未知异常") + logs.Error("从数据库查询文档时出错 ->", err) + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.unknown_exception")) } return } } if doc.BookId != bookResult.BookId { - c.ShowErrorPage(404, "文档不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.doc_not_exist")) } - + doc.Lang = c.Lang doc.Processor() attach, err := models.NewAttachment().FindListByDocumentId(doc.DocumentId) @@ -170,7 +170,7 @@ func (c *DocumentController) Read() { if err != nil && err != orm.ErrNoRows { logs.Error("生成项目文档树时出错 ->", err) - c.ShowErrorPage(500, "生成项目文档树时出错") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.build_doc_tree_error")) } c.Data["Description"] = utils.AutoSummary(doc.Release, 120) @@ -188,7 +188,7 @@ func (c *DocumentController) Edit() { identify := c.Ctx.Input.Param(":key") if identify == "" { - c.ShowErrorPage(404, "无法解析项目标识") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.project_id_error")) } bookResult := models.NewBookResult() @@ -198,7 +198,7 @@ func (c *DocumentController) Edit() { if c.Member.IsAdministrator() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } bookResult = models.NewBookResult().ToBookResult(*book) @@ -207,15 +207,15 @@ func (c *DocumentController) Edit() { if err != nil { if err == orm.ErrNoRows || err == models.ErrPermissionDenied { - c.ShowErrorPage(403, "项目不存在或没有权限") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } else { logs.Error("查询项目时出错 -> ", err) - c.ShowErrorPage(500, "查询项目时出错") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error")) } return } if bookResult.RoleId == conf.BookObserver { - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } } @@ -269,11 +269,11 @@ func (c *DocumentController) Create() { isOpen, _ := c.GetInt("is_open", 0) if identify == "" { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } if docName == "" { - c.JsonResult(6004, "文档名称不能为空") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.doc_name_empty")) } bookId := 0 @@ -283,7 +283,7 @@ func (c *DocumentController) Create() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { logs.Error(err) - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_existed_or_no_permit")) } bookId = book.BookId @@ -292,7 +292,7 @@ func (c *DocumentController) Create() { if err != nil || bookResult.RoleId == conf.BookObserver { logs.Error("FindByIdentify => ", err) - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_existed_or_no_permit")) } bookId = bookResult.BookId @@ -300,18 +300,18 @@ func (c *DocumentController) Create() { if docIdentify != "" { if ok, err := regexp.MatchString(`[a-z]+[a-zA-Z0-9_.\-]*$`, docIdentify); !ok || err != nil { - c.JsonResult(6003, "文档标识只能包含小写字母、数字,以及“-”、“.”和“_”符号") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.project_id_tips")) } d, _ := models.NewDocument().FindByIdentityFirst(docIdentify, bookId) if d.DocumentId > 0 && d.DocumentId != docId { - c.JsonResult(6006, "文档标识已被使用") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_id_existed")) } } if parentId > 0 { doc, err := models.NewDocument().Find(parentId) if err != nil || doc.BookId != bookId { - c.JsonResult(6003, "父分类不存在") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.parent_id_not_existed")) } } @@ -336,7 +336,7 @@ func (c *DocumentController) Create() { if err := document.InsertOrUpdate(); err != nil { logs.Error("添加或更新文档时出错 -> ", err) - c.JsonResult(6005, "保存失败") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed")) } else { c.JsonResult(0, "ok", document) } @@ -349,7 +349,7 @@ func (c *DocumentController) Upload() { isAttach := true if identify == "" { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } name := "editormd-file-file" @@ -359,7 +359,7 @@ func (c *DocumentController) Upload() { name = "editormd-image-file" file, moreFile, err = c.GetFile(name) if err == http.ErrMissingFile || moreFile == nil { - c.JsonResult(6003, "没有发现需要上传的文件") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_empty")) return } } @@ -375,17 +375,17 @@ func (c *DocumentController) Upload() { } if conf.GetUploadFileSize() > 0 && moreFile.Size > conf.GetUploadFileSize() { - c.JsonResult(6009, "文件大小超过了限定的最大值") + c.JsonResult(6009, i18n.Tr(c.Lang, "message.upload_file_size_limit")) } ext := filepath.Ext(moreFile.Filename) //文件必须带有后缀名 if ext == "" { - c.JsonResult(6003, "无法解析文件的格式") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.upload_file_type_error")) } //如果文件类型设置为 * 标识不限制文件类型 if conf.IsAllowUploadFileExt(ext) == false { - c.JsonResult(6004, "不允许的文件类型") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.upload_file_type_error")) } bookId := 0 @@ -395,7 +395,7 @@ func (c *DocumentController) Upload() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { - c.JsonResult(6006, "文档不存在或权限不足") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.doc_not_exist_or_no_permit")) } bookId = book.BookId @@ -405,7 +405,7 @@ func (c *DocumentController) Upload() { if err != nil { logs.Error("DocumentController.Edit => ", err) if err == orm.ErrNoRows { - c.JsonResult(6006, "权限不足") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.no_permission")) } c.JsonResult(6001, err.Error()) @@ -413,7 +413,7 @@ func (c *DocumentController) Upload() { // 如果没有编辑权限 if book.RoleId != conf.BookEditor && book.RoleId != conf.BookAdmin && book.RoleId != conf.BookFounder { - c.JsonResult(6006, "权限不足") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.no_permission")) } bookId = book.BookId @@ -422,11 +422,11 @@ func (c *DocumentController) Upload() { if docId > 0 { doc, err := models.NewDocument().Find(docId) if err != nil { - c.JsonResult(6007, "文档不存在") + c.JsonResult(6007, i18n.Tr(c.Lang, "message.doc_not_exist")) } if doc.BookId != bookId { - c.JsonResult(6008, "文档不属于指定的项目") + c.JsonResult(6008, i18n.Tr(c.Lang, "message.doc_not_belong_project")) } } @@ -448,7 +448,7 @@ func (c *DocumentController) Upload() { if err != nil { logs.Error("保存文件失败 -> ", err) - c.JsonResult(6005, "保存文件失败") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed")) } attachment := models.NewAttachment() @@ -481,7 +481,7 @@ func (c *DocumentController) Upload() { if err != nil { os.Remove(filePath) logs.Error("文件保存失败 ->", err) - c.JsonResult(6006, "文件保存失败") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed")) } if attachment.HttpPath == "" { @@ -489,7 +489,7 @@ func (c *DocumentController) Upload() { if err := attachment.Update(); err != nil { logs.Error("保存文件失败 ->", err) - c.JsonResult(6005, "保存文件失败") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed")) } } @@ -531,10 +531,10 @@ func (c *DocumentController) DownloadAttachment() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(404, "项目不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist")) } else { logs.Error("查找项目时出错 ->", err) - c.ShowErrorPage(500, "系统错误") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error")) } } @@ -542,7 +542,7 @@ func (c *DocumentController) DownloadAttachment() { if c.Member == nil || c.Member.Role != conf.MemberSuperRole { // 如果项目是私有的,并且 token 不正确 if (book.PrivatelyOwned == 1 && token == "") || (book.PrivatelyOwned == 1 && book.PrivateToken != token) { - c.ShowErrorPage(403, "权限不足") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) } } @@ -557,14 +557,14 @@ func (c *DocumentController) DownloadAttachment() { if err != nil { logs.Error("查找附件时出错 -> ", err) if err == orm.ErrNoRows { - c.ShowErrorPage(404, "附件不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist")) } else { - c.ShowErrorPage(500, "查找附件时出错") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error")) } } if attachment.BookId != bookId { - c.ShowErrorPage(404, "附件不存在或已删除") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.attachment_not_exist")) } c.Ctx.Output.Download(filepath.Join(conf.WorkingDirectory, attachment.FilePath), attachment.FileName) @@ -577,39 +577,39 @@ func (c *DocumentController) RemoveAttachment() { attachId, _ := c.GetInt("attach_id") if attachId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } attach, err := models.NewAttachment().Find(attachId) if err != nil { logs.Error(err) - c.JsonResult(6002, "附件不存在") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.attachment_not_exist")) } document, err := models.NewDocument().Find(attach.DocumentId) if err != nil { logs.Error(err) - c.JsonResult(6003, "文档不存在") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.doc_not_exist")) } if c.Member.Role != conf.MemberSuperRole { rel, err := models.NewRelationship().FindByBookIdAndMemberId(document.BookId, c.Member.MemberId) if err != nil { logs.Error(err) - c.JsonResult(6004, "权限不足") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.no_permission")) } if rel.RoleId == conf.BookObserver { - c.JsonResult(6004, "权限不足") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.no_permission")) } } err = attach.Delete() if err != nil { logs.Error(err) - c.JsonResult(6005, "删除失败") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed")) } os.Remove(filepath.Join(conf.WorkingDirectory, attach.FilePath)) @@ -631,7 +631,7 @@ func (c *DocumentController) Delete() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { logs.Error("FindByIdentify => ", err) - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } bookId = book.BookId @@ -640,31 +640,31 @@ func (c *DocumentController) Delete() { if err != nil || bookResult.RoleId == conf.BookObserver { logs.Error("FindByIdentify => ", err) - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } bookId = bookResult.BookId } if docId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } doc, err := models.NewDocument().Find(docId) if err != nil { logs.Error("Delete => ", err) - c.JsonResult(6003, "删除失败") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed")) } // 如果文档所属项目错误 if doc.BookId != bookId { - c.JsonResult(6004, "参数错误") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.param_error")) } // 递归删除项目下的文档以及子文档 err = doc.RecursiveDocument(doc.DocumentId) if err != nil { - c.JsonResult(6005, "删除失败") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.failed")) } // 重置文档数量统计 @@ -690,7 +690,7 @@ func (c *DocumentController) Content() { if c.Member.IsAdministrator() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil || book == nil { - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) return } @@ -701,7 +701,7 @@ func (c *DocumentController) Content() { if err != nil || bookResult.RoleId == conf.BookObserver { logs.Error("项目不存在或权限不足 -> ", err) - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } bookId = bookResult.BookId @@ -709,7 +709,7 @@ func (c *DocumentController) Content() { } if docId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } if c.Ctx.Input.IsPost() { @@ -719,19 +719,18 @@ func (c *DocumentController) Content() { isCover := c.GetString("cover") doc, err := models.NewDocument().Find(docId) - if err != nil || doc == nil { - c.JsonResult(6003, "读取文档错误") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.read_file_error")) return } if doc.BookId != bookId { - c.JsonResult(6004, "保存的文档不属于指定项目") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.dock_not_belong_project")) } if doc.Version != version && !strings.EqualFold(isCover, "yes") { logs.Info("%d|", version, doc.Version) - c.JsonResult(6005, "文档已被修改确定要覆盖吗?") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.confirm_override_doc")) } history := models.NewDocumentHistory() @@ -744,7 +743,7 @@ func (c *DocumentController) Content() { history.ParentId = doc.ParentId history.Version = time.Now().Unix() history.Action = "modify" - history.ActionName = "修改文档" + history.ActionName = i18n.Tr(c.Lang, "doc.modify_doc") if markdown == "" && content != "" { doc.Markdown = content @@ -758,7 +757,7 @@ func (c *DocumentController) Content() { if err := doc.InsertOrUpdate(); err != nil { logs.Error("InsertOrUpdate => ", err) - c.JsonResult(6006, "保存失败") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed")) } // 如果启用了文档历史,则添加历史文档 @@ -775,9 +774,10 @@ func (c *DocumentController) Content() { //如果启用了自动发布 if autoRelease { go func() { + doc.Lang = c.Lang err := doc.ReleaseContent() if err == nil { - logs.Informational("文档自动发布成功 -> document_id=%d;document_name=%s", doc.DocumentId, doc.DocumentName) + logs.Informational(i18n.Tr(c.Lang, "message.doc_auto_published")+"-> document_id=%d;document_name=%s", doc.DocumentId, doc.DocumentName) } }() } @@ -787,7 +787,7 @@ func (c *DocumentController) Content() { doc, err := models.NewDocument().Find(docId) if err != nil { - c.JsonResult(6003, "文档不存在") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.doc_not_exist")) return } @@ -805,7 +805,7 @@ func (c *DocumentController) Export() { identify := c.Ctx.Input.Param(":key") if identify == "" { - c.ShowErrorPage(500, "参数错误") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.param_error")) } output := c.GetString("output") @@ -817,7 +817,7 @@ func (c *DocumentController) Export() { return } if !conf.GetEnableExport() { - c.ShowErrorPage(500, "系统没有开启导出功能") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "export_func_disable")) } bookResult := models.NewBookResult() @@ -825,10 +825,10 @@ func (c *DocumentController) Export() { book, err := models.NewBook().FindByIdentify(identify) if err != nil { if err == orm.ErrNoRows { - c.ShowErrorPage(404, "项目不存在") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist")) } else { logs.Error("查找项目时出错 ->", err) - c.ShowErrorPage(500, "查找项目时出错") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.system_error")) } } bookResult = models.NewBookResult().ToBookResult(*book) @@ -836,7 +836,7 @@ func (c *DocumentController) Export() { bookResult = c.isReadable(identify, token) } if !bookResult.IsDownload { - c.ShowErrorPage(200, "当前项目没有开启导出功能") + c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.cur_project_export_func_disable")) } if !strings.HasPrefix(bookResult.Cover, "http:://") && !strings.HasPrefix(bookResult.Cover, "https:://") { @@ -845,12 +845,12 @@ func (c *DocumentController) Export() { if output == "markdown" { if bookResult.Editor != "markdown" { - c.ShowErrorPage(500, "当前项目不支持Markdown编辑器") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.cur_project_not_support_md")) } p, err := bookResult.ExportMarkdown(c.CruSession.SessionID(context.TODO())) if err != nil { - c.ShowErrorPage(500, "导出文档失败") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.failed")) } c.Ctx.Output.Download(p, bookResult.BookName+".zip") @@ -883,15 +883,15 @@ func (c *DocumentController) Export() { } else if output == "pdf" || output == "epub" || output == "docx" || output == "mobi" { if err := models.BackgroundConvert(c.CruSession.SessionID(context.TODO()), bookResult); err != nil && err != gopool.ErrHandlerIsExist { - c.ShowErrorPage(500, "导出失败,请查看系统日志") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.export_failed")) } - c.ShowErrorPage(200, "文档正在后台转换,请稍后再下载") + c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.file_converting")) } else { - c.ShowErrorPage(200, "不支持的文件格式") + c.ShowErrorPage(200, i18n.Tr(c.Lang, "message.unsupport_file_type")) } - c.ShowErrorPage(404, "项目没有导出文件") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.no_exportable_file")) } // 生成项目访问的二维码 @@ -902,20 +902,20 @@ func (c *DocumentController) QrCode() { book, err := models.NewBook().FindByIdentify(identify) if err != nil || book.BookId <= 0 { - c.ShowErrorPage(404, "项目不存在") + c.ShowErrorPage(404, i18n.Tr(c.Lang, "message.item_not_exist")) } uri := conf.URLFor("DocumentController.Index", ":key", identify) code, err := qr.Encode(uri, qr.L, qr.Unicode) if err != nil { logs.Error("生成二维码失败 ->", err) - c.ShowErrorPage(500, "生成二维码失败") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.gen_qrcode_failed")) } code, err = barcode.Scale(code, 150, 150) if err != nil { logs.Error("生成二维码失败 ->", err) - c.ShowErrorPage(500, "生成二维码失败") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.gen_qrcode_failed")) } c.Ctx.ResponseWriter.Header().Set("Content-Type", "image/png") @@ -925,7 +925,7 @@ func (c *DocumentController) QrCode() { err = png.Encode(c.Ctx.ResponseWriter, code) if err != nil { logs.Error("生成二维码失败 ->", err) - c.ShowErrorPage(500, "生成二维码失败") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.gen_qrcode_failed")) } } @@ -938,7 +938,7 @@ func (c *DocumentController) Search() { keyword := strings.TrimSpace(c.GetString("keyword")) if identify == "" { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } if !c.EnableAnonymous && !c.isUserLoggedIn() { @@ -951,11 +951,11 @@ func (c *DocumentController) Search() { docs, err := models.NewDocumentSearchResult().SearchDocument(keyword, bookResult.BookId) if err != nil { logs.Error(err) - c.JsonResult(6002, "搜索结果错误") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.search_result_error")) } if len(docs) < 0 { - c.JsonResult(404, "没有数据库") + c.JsonResult(404, i18n.Tr(c.Lang, "message.no_data")) } for _, doc := range docs { @@ -985,7 +985,7 @@ func (c *DocumentController) History() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { logs.Error("查找项目失败 ->", err) - c.Data["ErrorMessage"] = "项目不存在或权限不足" + c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit") return } @@ -995,7 +995,7 @@ func (c *DocumentController) History() { bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil || bookResult.RoleId == conf.BookObserver { logs.Error("查找项目失败 ->", err) - c.Data["ErrorMessage"] = "项目不存在或权限不足" + c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit") return } @@ -1004,27 +1004,27 @@ func (c *DocumentController) History() { } if docId <= 0 { - c.Data["ErrorMessage"] = "参数错误" + c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.param_error") return } doc, err := models.NewDocument().Find(docId) if err != nil { logs.Error("Delete => ", err) - c.Data["ErrorMessage"] = "获取历史失败" + c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.get_doc_his_failed") return } // 如果文档所属项目错误 if doc.BookId != bookId { - c.Data["ErrorMessage"] = "参数错误" + c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.param_error") return } histories, totalCount, err := models.NewDocumentHistory().FindToPager(docId, pageIndex, conf.PageSize) if err != nil { logs.Error("分页查找文档历史失败 ->", err) - c.Data["ErrorMessage"] = "获取历史失败" + c.Data["ErrorMessage"] = i18n.Tr(c.Lang, "message.get_doc_his_failed") return } @@ -1048,7 +1048,7 @@ func (c *DocumentController) DeleteHistory() { historyId, _ := c.GetInt("history_id", 0) if historyId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } bookId := 0 @@ -1058,7 +1058,7 @@ func (c *DocumentController) DeleteHistory() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { logs.Error("查找项目失败 ->", err) - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } bookId = book.BookId @@ -1066,31 +1066,31 @@ func (c *DocumentController) DeleteHistory() { bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil || bookResult.RoleId == conf.BookObserver { logs.Error("查找项目失败 ->", err) - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } bookId = bookResult.BookId } if docId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } doc, err := models.NewDocument().Find(docId) if err != nil { logs.Error("Delete => ", err) - c.JsonResult(6001, "获取历史失败") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.get_doc_his_failed")) } // 如果文档所属项目错误 if doc.BookId != bookId { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } err = models.NewDocumentHistory().Delete(historyId, docId) if err != nil { logs.Error(err) - c.JsonResult(6002, "删除失败") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok") @@ -1107,7 +1107,7 @@ func (c *DocumentController) RestoreHistory() { historyId, _ := c.GetInt("history_id", 0) if historyId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } bookId := 0 @@ -1116,7 +1116,7 @@ func (c *DocumentController) RestoreHistory() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { logs.Error("FindByIdentify => ", err) - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } bookId = book.BookId @@ -1124,31 +1124,31 @@ func (c *DocumentController) RestoreHistory() { bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil || bookResult.RoleId == conf.BookObserver { logs.Error("FindByIdentify => ", err) - c.JsonResult(6002, "项目不存在或权限不足") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist_or_no_permit")) } bookId = bookResult.BookId } if docId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } doc, err := models.NewDocument().Find(docId) if err != nil { logs.Error("Delete => ", err) - c.JsonResult(6001, "获取历史失败") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.get_doc_his_failed")) } // 如果文档所属项目错误 if doc.BookId != bookId { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } err = models.NewDocumentHistory().Restore(historyId, docId, c.Member.MemberId) if err != nil { logs.Error(err) - c.JsonResult(6002, "删除失败") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok", doc) @@ -1170,7 +1170,7 @@ func (c *DocumentController) Compare() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { logs.Error("DocumentController.Compare => ", err) - c.ShowErrorPage(403, "权限不足") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) return } @@ -1181,7 +1181,7 @@ func (c *DocumentController) Compare() { bookResult, err := models.NewBookResult().FindByIdentify(identify, c.Member.MemberId) if err != nil || bookResult.RoleId == conf.BookObserver { logs.Error("FindByIdentify => ", err) - c.ShowErrorPage(403, "权限不足") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) return } @@ -1191,7 +1191,7 @@ func (c *DocumentController) Compare() { } if historyId <= 0 { - c.ShowErrorPage(60002, "参数错误") + c.ShowErrorPage(60002, i18n.Tr(c.Lang, "message.param_error")) } history, err := models.NewDocumentHistory().Find(historyId) @@ -1202,7 +1202,7 @@ func (c *DocumentController) Compare() { doc, err := models.NewDocument().Find(history.DocumentId) if err != nil || doc == nil || doc.BookId != bookId { - c.ShowErrorPage(60002, "文档不存在或已删除") + c.ShowErrorPage(60002, i18n.Tr(c.Lang, "message.doc_not_exist")) return } @@ -1224,7 +1224,7 @@ func (c *DocumentController) isReadable(identify, token string) *models.BookResu if err != nil { logs.Error(err) - c.ShowErrorPage(500, "项目不存在") + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.item_not_exist")) } bookResult := models.NewBookResult().ToBookResult(*book) isOk := false @@ -1249,13 +1249,13 @@ func (c *DocumentController) isReadable(identify, token string) *models.BookResu c.SetSession(identify, token) } else if token, ok := c.GetSession(identify).(string); !ok || !strings.EqualFold(token, book.PrivateToken) { logs.Info("尝试访问文档但权限不足 ->", identify, token) - c.ShowErrorPage(403, "权限不足") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) } } else if password := c.GetString("bPassword", ""); !isOk && book.BookPassword != "" && password != "" { //如果设置了密码,则判断密码是否正确 if book.BookPassword != password { - c.JsonResult(5001, "密码错误") + c.JsonResult(5001, i18n.Tr(c.Lang, "message.wrong_password")) } else { c.SetSession(identify, password) c.JsonResult(0, "OK") @@ -1274,7 +1274,7 @@ func (c *DocumentController) isReadable(identify, token string) *models.BookResu } } else { logs.Info("尝试访问文档但权限不足 ->", identify, token) - c.ShowErrorPage(403, "权限不足") + c.ShowErrorPage(403, i18n.Tr(c.Lang, "message.no_permission")) } } } @@ -1288,7 +1288,7 @@ func promptUserToLogIn(c *DocumentController) { logs.Info(" Access will be redirected to login page(SessionId: " + c.CruSession.SessionID(context.TODO()) + ").") if c.IsAjax() { - c.JsonResult(6000, "请重新登录。") + c.JsonResult(6000, i18n.Tr(c.Lang, "message.need_relogin")) } else { c.Redirect(conf.URLFor("AccountController.Login")+"?url="+url.PathEscape(conf.BaseUrl+c.Ctx.Request.URL.RequestURI()), 302) } diff --git a/controllers/HomeController.go b/controllers/HomeController.go index 673c03d8..c4233c04 100644 --- a/controllers/HomeController.go +++ b/controllers/HomeController.go @@ -28,14 +28,11 @@ func (c *HomeController) Index() { pageIndex, _ := c.GetInt("page", 1) pageSize := 18 - memberId := 0 - if c.Member != nil { memberId = c.Member.MemberId } books, totalCount, err := models.NewBook().FindForHomeToPager(pageIndex, pageSize, memberId) - if err != nil { logs.Error(err) c.Abort("500") @@ -47,6 +44,5 @@ func (c *HomeController) Index() { c.Data["PageHtml"] = "" } c.Data["TotalPages"] = int(math.Ceil(float64(totalCount) / float64(pageSize))) - c.Data["Lists"] = books } diff --git a/controllers/ManagerController.go b/controllers/ManagerController.go index 38998a2e..8984031b 100644 --- a/controllers/ManagerController.go +++ b/controllers/ManagerController.go @@ -16,6 +16,7 @@ import ( "github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/models" "github.com/mindoc-org/mindoc/utils" @@ -40,17 +41,17 @@ func (c *ManagerController) Index() { c.TplName = "manager/index.tpl" c.Data["Model"] = models.NewDashboard().Query() + c.Data["Action"] = "index" } // 用户列表. func (c *ManagerController) Users() { c.Prepare() c.TplName = "manager/users.tpl" - + c.Data["Action"] = "users" pageIndex, _ := c.GetInt("page", 0) members, totalCount, err := models.NewMember().FindToPager(pageIndex, conf.PageSize) - if err != nil { c.Data["ErrorMessage"] = err.Error() return @@ -68,7 +69,6 @@ func (c *ManagerController) Users() { } b, err := json.Marshal(members) - if err != nil { c.Data["Result"] = template.JS("[]") } else { @@ -89,16 +89,16 @@ func (c *ManagerController) CreateMember() { status, _ := c.GetInt("status", 0) if ok, err := regexp.MatchString(conf.RegexpAccount, account); account == "" || !ok || err != nil { - c.JsonResult(6001, "账号只能由英文字母数字组成,且在3-50个字符") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.username_invalid_format")) } if l := strings.Count(password1, ""); password1 == "" || l > 50 || l < 6 { - c.JsonResult(6002, "密码必须在6-50个字符之间") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.pwd_length_tips")) } if password1 != password2 { - c.JsonResult(6003, "确认密码不正确") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.wrong_confirm_pwd")) } if ok, err := regexp.MatchString(conf.RegexpEmail, email); !ok || err != nil || email == "" { - c.JsonResult(6004, "邮箱格式不正确") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.email_invalid_format")) } if role != 0 && role != 1 && role != 2 { role = 1 @@ -110,7 +110,7 @@ func (c *ManagerController) CreateMember() { member := models.NewMember() if _, err := member.FindByAccount(account); err == nil && member.MemberId > 0 { - c.JsonResult(6005, "账号已存在") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.account_existed")) } member.Account = account @@ -139,7 +139,7 @@ func (c *ManagerController) UpdateMemberStatus() { status, _ := c.GetInt("status", 0) if member_id <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } if status != 0 && status != 1 { status = 0 @@ -147,19 +147,19 @@ func (c *ManagerController) UpdateMemberStatus() { member := models.NewMember() if _, err := member.Find(member_id); err != nil { - c.JsonResult(6002, "用户不存在") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.user_not_existed")) } if member.MemberId == c.Member.MemberId { - c.JsonResult(6004, "不能变更自己的状态") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.cannot_change_own_status")) } if member.Role == conf.MemberSuperRole { - c.JsonResult(6005, "不能变更超级管理员的状态") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.cannot_change_super_status")) } member.Status = status if err := member.Update(); err != nil { logs.Error("", err) - c.JsonResult(6003, "用户状态设置失败") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok", member) } @@ -171,27 +171,28 @@ func (c *ManagerController) ChangeMemberRole() { memberId, _ := c.GetInt("member_id", 0) role, _ := c.GetInt("role", 0) if memberId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } if role != int(conf.MemberAdminRole) && role != int(conf.MemberGeneralRole) { - c.JsonResult(6001, "用户权限不正确") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.no_permission")) } member := models.NewMember() if _, err := member.Find(memberId); err != nil { - c.JsonResult(6002, "用户不存在") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.user_not_existed")) } if member.MemberId == c.Member.MemberId { - c.JsonResult(6004, "不能变更自己的权限") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.cannot_change_own_priv")) } if member.Role == conf.MemberSuperRole { - c.JsonResult(6005, "不能变更超级管理员的权限") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.cannot_change_super_priv")) } member.Role = conf.SystemRole(role) if err := member.Update(); err != nil { - c.JsonResult(6003, "用户权限设置失败") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed")) } + member.Lang = c.Lang member.ResolveRoleName() c.JsonResult(0, "ok", member) } @@ -200,7 +201,7 @@ func (c *ManagerController) ChangeMemberRole() { func (c *ManagerController) EditMember() { c.Prepare() c.TplName = "manager/edit_users.tpl" - + c.Data["Action"] = "users" member_id, _ := c.GetInt(":id", 0) if member_id <= 0 { @@ -208,7 +209,6 @@ func (c *ManagerController) EditMember() { } member, err := models.NewMember().Find(member_id) - if err != nil { logs.Error(err) c.Abort("404") @@ -224,7 +224,7 @@ func (c *ManagerController) EditMember() { member.Description = description member.RealName = c.GetString("real_name") if password1 != "" && password2 != password1 { - c.JsonResult(6001, "确认密码不正确") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.wrong_confirm_pwd")) } if password1 != "" && member.AuthMethod != conf.AuthMethodLDAP { member.Password = password1 @@ -236,7 +236,7 @@ func (c *ManagerController) EditMember() { password, err := utils.PasswordHash(password1) if err != nil { logs.Error(err) - c.JsonResult(6003, "对用户密码加密时出错") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.pwd_encrypt_failed")) } member.Password = password } @@ -255,30 +255,28 @@ func (c *ManagerController) DeleteMember() { member_id, _ := c.GetInt("id", 0) if member_id <= 0 { - c.JsonResult(404, "参数错误") + c.JsonResult(404, i18n.Tr(c.Lang, "message.param_error")) } member, err := models.NewMember().Find(member_id) - if err != nil { logs.Error(err) - c.JsonResult(500, "用户不存在") + c.JsonResult(500, i18n.Tr(c.Lang, "message.user_not_existed")) } if member.Role == conf.MemberSuperRole { c.JsonResult(500, "不能删除超级管理员") } - superMember, err := models.NewMember().FindByFieldFirst("role", 0) + superMember, err := models.NewMember().FindByFieldFirst("role", 0) if err != nil { logs.Error(err) c.JsonResult(5001, "未能找到超级管理员") } err = models.NewMember().Delete(member_id, superMember.MemberId) - if err != nil { logs.Error(err) - c.JsonResult(5002, "删除失败") + c.JsonResult(5002, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok") } @@ -287,7 +285,7 @@ func (c *ManagerController) DeleteMember() { func (c *ManagerController) Books() { c.Prepare() c.TplName = "manager/books.tpl" - + c.Data["Action"] = "books" pageIndex, _ := c.GetInt("page", 1) books, totalCount, err := models.NewBookResult().FindToPager(pageIndex, conf.PageSize) @@ -318,7 +316,7 @@ func (c *ManagerController) EditBook() { c.Prepare() c.TplName = "manager/edit_book.tpl" - + c.Data["Action"] = "books" identify := c.GetString(":key") if identify == "" { @@ -328,8 +326,8 @@ func (c *ManagerController) EditBook() { if err != nil { c.Abort("500") } - if c.Ctx.Input.IsPost() { + if c.Ctx.Input.IsPost() { bookName := strings.TrimSpace(c.GetString("book_name")) description := strings.TrimSpace(c.GetString("description", "")) commentStatus := c.GetString("comment_status") @@ -344,7 +342,7 @@ func (c *ManagerController) EditBook() { itemId, _ := c.GetInt("itemId") if strings.Count(description, "") > 500 { - c.JsonResult(6004, "项目描述不能大于500字") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.project_desc_tips")) } if commentStatus != "open" && commentStatus != "closed" && commentStatus != "group_only" && commentStatus != "registered_only" { commentStatus = "closed" @@ -356,7 +354,7 @@ func (c *ManagerController) EditBook() { } } if !models.NewItemsets().Exist(itemId) { - c.JsonResult(6006, "项目空间不存在") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.project_space_not_exist")) } book.Publisher = publisher book.HistoryCount = historyCount @@ -390,7 +388,7 @@ func (c *ManagerController) EditBook() { } if err := book.Update(); err != nil { - c.JsonResult(6006, "保存失败") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok") } @@ -410,18 +408,18 @@ func (c *ManagerController) DeleteBook() { bookId, _ := c.GetInt("book_id", 0) if bookId <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } book := models.NewBook() err := book.ThoroughDeleteBook(bookId) if err == orm.ErrNoRows { - c.JsonResult(6002, "项目不存在") + c.JsonResult(6002, i18n.Tr(c.Lang, "message.item_not_exist")) } if err != nil { logs.Error("删除失败 -> ", err) - c.JsonResult(6003, "删除失败") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok") } @@ -436,7 +434,7 @@ func (c *ManagerController) CreateToken() { book, err := models.NewBook().FindByFieldFirst("identify", identify) if err != nil { - c.JsonResult(6001, "项目不存在") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.item_not_exist")) } if action == "create" { @@ -447,14 +445,14 @@ func (c *ManagerController) CreateToken() { book.PrivateToken = string(utils.Krand(conf.GetTokenSize(), utils.KC_RAND_KIND_ALL)) if err := book.Update(); err != nil { logs.Error("生成阅读令牌失败 => ", err) - c.JsonResult(6003, "生成阅读令牌失败") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok", conf.URLFor("DocumentController.Index", ":key", book.Identify, "token", book.PrivateToken)) } else { book.PrivateToken = "" if err := book.Update(); err != nil { logs.Error("CreateToken => ", err) - c.JsonResult(6004, "删除令牌失败") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok", "") } @@ -464,7 +462,7 @@ func (c *ManagerController) CreateToken() { func (c *ManagerController) Setting() { c.Prepare() c.TplName = "manager/setting.tpl" - + c.Data["Action"] = "setting" options, err := models.NewOption().All() if c.Ctx.Input.IsPost() { @@ -483,7 +481,6 @@ func (c *ManagerController) Setting() { for _, item := range options { c.Data[item.OptionName] = item.OptionValue } - } // Transfer 转让项目. @@ -492,16 +489,16 @@ func (c *ManagerController) Transfer() { account := c.GetString("account") if account == "" { - c.JsonResult(6004, "接受者账号不能为空") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.receive_account_empty")) } member, err := models.NewMember().FindByAccount(account) if err != nil { logs.Error("FindByAccount => ", err) - c.JsonResult(6005, "接受用户不存在") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.receive_account_not_exist")) } if member.Status != 0 { - c.JsonResult(6006, "接受用户已被禁用") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.receive_account_disabled")) } if !c.Member.IsAdministrator() { @@ -549,7 +546,7 @@ func (c *ManagerController) DeleteComment() { comment_id, _ := c.GetInt("comment_id", 0) if comment_id <= 0 { - c.JsonResult(6001, "参数错误") + c.JsonResult(6001, i18n.Tr(c.Lang, "message.param_error")) } comment := models.NewComment() @@ -573,7 +570,7 @@ func (c *ManagerController) PrivatelyOwned() { identify := c.GetString("identify") if status != "open" && status != "close" { - c.JsonResult(6003, "参数错误") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.param_error")) } state := 0 if status == "open" { @@ -599,7 +596,7 @@ func (c *ManagerController) PrivatelyOwned() { if err != nil { logs.Error("PrivatelyOwned => ", err) - c.JsonResult(6004, "保存失败") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok") } @@ -608,6 +605,7 @@ func (c *ManagerController) PrivatelyOwned() { func (c *ManagerController) AttachList() { c.Prepare() c.TplName = "manager/attach_list.tpl" + c.Data["Action"] = "attach" pageIndex, _ := c.GetInt("page", 1) @@ -638,14 +636,14 @@ func (c *ManagerController) AttachList() { func (c *ManagerController) AttachDetailed() { c.Prepare() c.TplName = "manager/attach_detailed.tpl" - attach_id, _ := strconv.Atoi(c.Ctx.Input.Param(":id")) + c.Data["Action"] = "attach" + attach_id, _ := strconv.Atoi(c.Ctx.Input.Param(":id")) if attach_id <= 0 { c.Abort("404") } attach, err := models.NewAttachmentResult().Find(attach_id) - if err != nil { logs.Error("AttachDetailed => ", err) if err == orm.ErrNoRows { @@ -690,11 +688,10 @@ func (c *ManagerController) AttachDelete() { func (c *ManagerController) LabelList() { c.Prepare() c.TplName = "manager/label_list.tpl" - + c.Data["Action"] = "label" pageIndex, _ := c.GetInt("page", 1) labels, totalCount, err := models.NewLabel().FindToPager(pageIndex, conf.PageSize) - if err != nil { c.ShowErrorPage(50001, err.Error()) } @@ -712,13 +709,12 @@ func (c *ManagerController) LabelList() { //删除标签 func (c *ManagerController) LabelDelete() { labelId, err := strconv.Atoi(c.Ctx.Input.Param(":id")) - if err != nil { logs.Error("获取删除标签参数时出错:", err) - c.JsonResult(50001, "参数错误") + c.JsonResult(50001, i18n.Tr(c.Lang, "message.param_error")) } if labelId <= 0 { - c.JsonResult(50001, "参数错误") + c.JsonResult(50001, i18n.Tr(c.Lang, "message.param_error")) } label, err := models.NewLabel().FindFirst("label_id", labelId) @@ -736,6 +732,7 @@ func (c *ManagerController) LabelDelete() { func (c *ManagerController) Config() { c.Prepare() c.TplName = "manager/config.tpl" + c.Data["Action"] = "config" if c.Ctx.Input.IsPost() { content := strings.TrimSpace(c.GetString("configFileTextArea")) if content == "" { @@ -773,11 +770,10 @@ func (c *ManagerController) Config() { func (c *ManagerController) Team() { c.Prepare() c.TplName = "manager/team.tpl" - + c.Data["Action"] = "team" pageIndex, _ := c.GetInt("page", 0) teams, totalCount, err := models.NewTeam().FindToPager(pageIndex, conf.PageSize) - if err != nil && err != orm.ErrNoRows { c.ShowErrorPage(500, err.Error()) } @@ -795,7 +791,6 @@ func (c *ManagerController) Team() { } b, err := json.Marshal(teams) - if err != nil { c.Data["Result"] = template.JS("[]") } else { @@ -809,7 +804,7 @@ func (c *ManagerController) TeamCreate() { teamName := c.GetString("teamName") if teamName == "" { - c.JsonResult(5001, "团队名称不能为空") + c.JsonResult(5001, i18n.Tr(c.Lang, "message.team_name_empty")) } team := models.NewTeam() @@ -830,10 +825,10 @@ func (c *ManagerController) TeamEdit() { teamId, _ := c.GetInt("teamId") if teamName == "" { - c.JsonResult(5001, "团队名称不能为空") + c.JsonResult(5001, i18n.Tr(c.Lang, "message.team_name_empty")) } if teamId <= 0 { - c.JsonResult(5002, "团队标识不能为空") + c.JsonResult(5002, i18n.Tr(c.Lang, "message.team_id_empty")) } team, err := models.NewTeam().First(teamId) @@ -846,19 +841,16 @@ func (c *ManagerController) TeamEdit() { c.CheckJsonError(5004, err) c.JsonResult(0, "OK", team) - } func (c *ManagerController) TeamDelete() { c.Prepare() teamId, _ := c.GetInt("teamId") - if teamId <= 0 { - c.JsonResult(5002, "团队标识不能为空") + c.JsonResult(5002, i18n.Tr(c.Lang, "message.team_id_empty")) } err := models.NewTeam().Delete(teamId) - c.CheckJsonError(5001, err) c.JsonResult(0, "OK") @@ -867,23 +859,21 @@ func (c *ManagerController) TeamDelete() { func (c *ManagerController) TeamMemberList() { c.Prepare() c.TplName = "manager/team_member_list.tpl" + c.Data["Action"] = "team" teamId, _ := strconv.Atoi(c.Ctx.Input.Param(":id")) + if teamId <= 0 { + c.ShowErrorPage(500, i18n.Tr(c.Lang, "message.param_error")) + } pageIndex, _ := c.GetInt("page", 0) - if teamId <= 0 { - c.ShowErrorPage(500, "参数错误") - } - team, err := models.NewTeam().First(teamId) - if err == orm.ErrNoRows { c.ShowErrorPage(404, "团队不存在") } c.CheckErrorResult(500, err) c.Data["Model"] = team - teams, totalCount, err := models.NewTeamMember().FindToPager(teamId, pageIndex, conf.PageSize) - + teams, totalCount, err := models.NewTeamMember().SetLang(c.Lang).FindToPager(teamId, pageIndex, conf.PageSize) if err != nil && err != orm.ErrNoRows { c.ShowErrorPage(500, err.Error()) } @@ -901,7 +891,6 @@ func (c *ManagerController) TeamMemberList() { } b, err := json.Marshal(teams) - if err != nil { logs.Error("编码 JSON 结果失败 ->", err) c.Data["Result"] = template.JS("[]") @@ -918,7 +907,7 @@ func (c *ManagerController) TeamSearchMember() { keyword := strings.TrimSpace(c.GetString("q")) if teamId <= 0 { - c.JsonResult(500, "参数错误") + c.JsonResult(500, i18n.Tr(c.Lang, "message.param_error")) } searchResult, err := models.NewTeamMember().FindNotJoinMemberByAccount(teamId, keyword, 10) @@ -936,7 +925,7 @@ func (c *ManagerController) TeamMemberAdd() { roleId, _ := c.GetInt("roleId") if teamId <= 0 || memberId <= 0 || roleId <= 0 || roleId > int(conf.BookObserver) { - c.JsonResult(5001, "参数不正确") + c.JsonResult(5001, i18n.Tr(c.Lang, "message.system_error")) } teamMember := models.NewTeamMember() @@ -965,7 +954,7 @@ func (c *ManagerController) TeamMemberDelete() { } err = teamMember.Delete(teamMember.TeamMemberId) if err != nil { - c.JsonResult(5002, "删除失败") + c.JsonResult(5002, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "ok") } @@ -976,7 +965,7 @@ func (c *ManagerController) TeamChangeMemberRole() { roleId, _ := c.GetInt("roleId") teamId, _ := c.GetInt("teamId") if memberId <= 0 || roleId <= 0 || teamId <= 0 || roleId > int(conf.BookObserver) { - c.JsonResult(5001, "参数错误") + c.JsonResult(5001, i18n.Tr(c.Lang, "message.param_error")) } teamMember, err := models.NewTeamMember().ChangeRoleId(teamId, memberId, conf.BookRole(roleId)) @@ -993,12 +982,12 @@ func (c *ManagerController) TeamChangeMemberRole() { func (c *ManagerController) TeamBookList() { c.Prepare() c.TplName = "manager/team_book_list.tpl" - + c.Data["Action"] = "team" teamId, _ := strconv.Atoi(c.Ctx.Input.Param(":id")) pageIndex, _ := c.GetInt("page", 0) if teamId <= 0 { - c.JsonResult(5002, "团队标识不能为空") + c.JsonResult(5002, i18n.Tr(c.Lang, "message.team_id_empty")) } team, err := models.NewTeam().First(teamId) @@ -1028,7 +1017,6 @@ func (c *ManagerController) TeamBookList() { } b, err := json.Marshal(teams) - if err != nil { logs.Error("编码 JSON 结果失败 ->", err) c.Data["Result"] = template.JS("[]") @@ -1045,7 +1033,7 @@ func (c *ManagerController) TeamBookAdd() { bookId, _ := c.GetInt("bookId") if teamId <= 0 || bookId <= 0 { - c.JsonResult(500, "参数错误") + c.JsonResult(500, i18n.Tr(c.Lang, "message.param_error")) } teamRel := models.NewTeamRelationship() teamRel.BookId = bookId @@ -1069,7 +1057,7 @@ func (c *ManagerController) TeamSearchBook() { keyword := strings.TrimSpace(c.GetString("q")) if teamId <= 0 { - c.JsonResult(500, "参数错误") + c.JsonResult(500, i18n.Tr(c.Lang, "message.param_error")) } searchResult, err := models.NewTeamRelationship().FindNotJoinBookByName(teamId, keyword, 10) @@ -1087,13 +1075,13 @@ func (c *ManagerController) TeamBookDelete() { teamRelationshipId, _ := c.GetInt("teamRelId") if teamRelationshipId <= 0 { - c.JsonResult(500, "参数错误") + c.JsonResult(500, i18n.Tr(c.Lang, "message.param_error")) } err := models.NewTeamRelationship().Delete(teamRelationshipId) if err != nil { - c.JsonResult(5001, "删除失败") + c.JsonResult(5001, i18n.Tr(c.Lang, "message.failed")) } c.JsonResult(0, "OK") } @@ -1102,6 +1090,7 @@ func (c *ManagerController) TeamBookDelete() { func (c *ManagerController) Itemsets() { c.Prepare() c.TplName = "manager/itemsets.tpl" + c.Data["Action"] = "itemsets" pageIndex, _ := c.GetInt("page", 0) items, totalCount, err := models.NewItemsets().FindToPager(pageIndex, conf.PageSize) @@ -1123,7 +1112,6 @@ func (c *ManagerController) Itemsets() { } c.Data["Lists"] = items - } //编辑或添加项目空间. @@ -1133,14 +1121,14 @@ func (c *ManagerController) ItemsetsEdit() { itemName := strings.TrimSpace(c.GetString("itemName")) itemKey := strings.TrimSpace(c.GetString("itemKey")) if itemName == "" || itemKey == "" { - c.JsonResult(5001, "参数错误") + c.JsonResult(5001, i18n.Tr(c.Lang, "message.param_error")) } var item *models.Itemsets var err error if itemId > 0 { if item, err = models.NewItemsets().First(itemId); err != nil { if err == orm.ErrNoRows { - c.JsonResult(5002, "项目空间不存在") + c.JsonResult(5002, i18n.Tr(c.Lang, "message.project_space_not_exist")) } else { c.JsonResult(5003, "查询项目空间出错") } diff --git a/controllers/SearchController.go b/controllers/SearchController.go index ff734817..5cb041e1 100644 --- a/controllers/SearchController.go +++ b/controllers/SearchController.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/beego/beego/v2/core/logs" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/models" "github.com/mindoc-org/mindoc/utils" @@ -87,16 +88,16 @@ func (c *SearchController) User() { key := c.Ctx.Input.Param(":key") keyword := strings.TrimSpace(c.GetString("q")) if key == "" || keyword == "" { - c.JsonResult(404, "参数错误") + c.JsonResult(404, i18n.Tr(c.Lang, "message.param_error")) } keyword = sqltil.EscapeLike(keyword) book, err := models.NewBookResult().FindByIdentify(key, c.Member.MemberId) if err != nil { if err == models.ErrPermissionDenied { - c.JsonResult(403, "没有权限") + c.JsonResult(403, i18n.Tr(c.Lang, "message.no_permission")) } - c.JsonResult(500, "项目不存在") + c.JsonResult(500, i18n.Tr(c.Lang, "message.item_not_exist")) } //members, err := models.NewMemberRelationshipResult().FindNotJoinUsersByAccount(book.BookId, 10, "%"+keyword+"%") diff --git a/controllers/SettingController.go b/controllers/SettingController.go index 1ad090c0..762af330 100644 --- a/controllers/SettingController.go +++ b/controllers/SettingController.go @@ -9,6 +9,7 @@ import ( "time" "github.com/beego/beego/v2/core/logs" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/graphics" "github.com/mindoc-org/mindoc/models" @@ -28,7 +29,7 @@ func (c *SettingController) Index() { description := strings.TrimSpace(c.GetString("description")) if email == "" { - c.JsonResult(601, "邮箱不能为空") + c.JsonResult(601, i18n.Tr(c.Lang, "message.email_empty")) } member := c.Member member.Email = email @@ -48,34 +49,34 @@ func (c *SettingController) Password() { if c.Ctx.Input.IsPost() { if c.Member.AuthMethod == conf.AuthMethodLDAP { - c.JsonResult(6009, "当前用户不支持修改密码") + c.JsonResult(6009, i18n.Tr(c.Lang, "message.cur_user_cannot_change_pwd")) } password1 := c.GetString("password1") password2 := c.GetString("password2") password3 := c.GetString("password3") if password1 == "" { - c.JsonResult(6003, "原密码不能为空") + c.JsonResult(6003, i18n.Tr(c.Lang, "message.origin_pwd_empty")) } if password2 == "" { - c.JsonResult(6004, "新密码不能为空") + c.JsonResult(6004, i18n.Tr(c.Lang, "message.new_pwd_empty")) } if count := strings.Count(password2, ""); count < 6 || count > 18 { - c.JsonResult(6009, "密码必须在6-18字之间") + c.JsonResult(6009, i18n.Tr(c.Lang, "message.pwd_length")) } if password2 != password3 { c.JsonResult(6003, "确认密码不正确") } if ok, _ := utils.PasswordVerify(c.Member.Password, password1); !ok { - c.JsonResult(6005, "原始密码不正确") + c.JsonResult(6005, i18n.Tr(c.Lang, "message.wrong_origin_pwd")) } if password1 == password2 { - c.JsonResult(6006, "新密码不能和原始密码相同") + c.JsonResult(6006, i18n.Tr(c.Lang, "message.same_pwd")) } pwd, err := utils.PasswordHash(password2) if err != nil { - c.JsonResult(6007, "密码加密失败") + c.JsonResult(6007, i18n.Tr(c.Lang, "message.pwd_encrypt_failed")) } c.Member.Password = pwd if err := c.Member.Update(); err != nil { diff --git a/controllers/TemplateController.go b/controllers/TemplateController.go index 4348a1c0..bc903eb7 100644 --- a/controllers/TemplateController.go +++ b/controllers/TemplateController.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/beego/beego/v2/client/orm" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/models" ) @@ -20,7 +21,7 @@ func (c *TemplateController) isPermission() error { bookIdentify := c.GetString("identify", "") if bookIdentify == "" { - return errors.New("参数错误") + return errors.New(i18n.Tr(c.Lang, "message.param_error")) } if !c.Member.IsAdministrator() { diff --git a/go.mod b/go.mod index 57f2a3c3..ad9a1f1b 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,10 @@ go 1.13 require ( github.com/PuerkitoBio/goquery v1.4.1 + github.com/Unknwon/goconfig v0.0.0-20200908083735-df7de6a44db8 // indirect github.com/andybalholm/cascadia v1.2.0 // indirect github.com/beego/beego/v2 v2.0.2-0.20210322114547-10ea897525a5 + github.com/beego/i18n v0.0.0-20161101132742-e9308947f407 github.com/boombuler/barcode v1.0.0 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b // indirect github.com/howeyc/fsnotify v0.9.0 @@ -15,6 +17,7 @@ require ( github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/russross/blackfriday/v2 v2.1.0 + github.com/smartystreets/goconvey v1.6.4 // indirect gopkg.in/asn1-ber.v1 v1.0.0-00010101000000-000000000000 // indirect gopkg.in/ldap.v2 v2.5.1 gopkg.in/yaml.v2 v2.3.0 // indirect diff --git a/go.sum b/go.sum index ad9e0b76..e74efd15 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/PuerkitoBio/goquery v1.4.1 h1:smcIRGdYm/w7JSbcdeLHEMzxmsBQvl8lhf0dSw2nzMI= github.com/PuerkitoBio/goquery v1.4.1/go.mod h1:T9ezsOHcCrDCgA8aF1Cqr3sSYbO/xgdy8/R/XiIMAhA= +github.com/Unknwon/goconfig v0.0.0-20200908083735-df7de6a44db8 h1:1TrMV1HmBApBbM+Hy7RCKZD6UlYWYIPPfoeXomG7+zE= +github.com/Unknwon/goconfig v0.0.0-20200908083735-df7de6a44db8/go.mod h1:wngxua9XCNjvHjDiTiV26DaKDT+0c63QR6H5hjVUUxw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -14,6 +16,8 @@ github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxB github.com/beego/beego/v2 v2.0.2-0.20210322114547-10ea897525a5 h1:i0swsv6hmoF6pkeG2S/dvOWwOKFPGDKhrmTlWH6I1nM= github.com/beego/beego/v2 v2.0.2-0.20210322114547-10ea897525a5/go.mod h1:JlRUJ/NVNygorqjyt7/lQ8R++KSE0qXvxeIfbnIUd7Q= github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= +github.com/beego/i18n v0.0.0-20161101132742-e9308947f407 h1:WtJfx5HqASTQp7HfiZldnin8KQV2futplF3duGp5PGc= +github.com/beego/i18n v0.0.0-20161101132742-e9308947f407/go.mod h1:KLeFCpAMq2+50NkXC8iiJxLLiiTfTqrGtKEVm+2fk7s= github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -92,6 +96,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -101,6 +107,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kardianos/service v1.1.0 h1:QV2SiEeWK42P0aEmGcsAgjApw/lRxkwopvT+Gu6t1/0= github.com/kardianos/service v1.1.0/go.mod h1:RrJI2xn5vve/r32U5suTbeaSGoMU6GbNPoj36CVYcHc= @@ -176,6 +184,10 @@ github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKz github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -254,6 +266,7 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/models/BookModel.go b/models/BookModel.go index 78676a33..d78f6ca2 100644 --- a/models/BookModel.go +++ b/models/BookModel.go @@ -19,6 +19,7 @@ import ( "github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/core/logs" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/utils" "github.com/mindoc-org/mindoc/utils/cryptil" @@ -115,7 +116,7 @@ func NewBook() *Book { } //添加一个项目 -func (book *Book) Insert() error { +func (book *Book) Insert(lang string) error { o := orm.NewOrm() // o.Begin() book.BookName = utils.StripTags(book.BookName) @@ -141,7 +142,7 @@ func (book *Book) Insert() error { } document := NewDocument() document.BookId = book.BookId - document.DocumentName = "空白文档" + document.DocumentName = i18n.Tr(lang, "init.blank_doc") //"空白文档" document.MemberId = book.MemberId err = document.InsertOrUpdate() if err != nil { @@ -362,7 +363,7 @@ func (book *Book) FindByIdentify(identify string, cols ...string) (*Book, error) } //分页查询指定用户的项目 -func (book *Book) FindToPager(pageIndex, pageSize, memberId int) (books []*BookResult, totalCount int, err error) { +func (book *Book) FindToPager(pageIndex, pageSize, memberId int, lang string) (books []*BookResult, totalCount int, err error) { o := orm.NewOrm() @@ -430,13 +431,13 @@ ORDER BY book.order_index, book.book_id DESC limit ?,?` books[index].LastModifyText = text.Account + " 于 " + text.ModifyTime.Format("2006-01-02 15:04:05") } if book.RoleId == 0 { - book.RoleName = "创始人" + book.RoleName = i18n.Tr(lang, "common.creator") } else if book.RoleId == 1 { - book.RoleName = "管理员" + book.RoleName = i18n.Tr(lang, "common.administrator") } else if book.RoleId == 2 { - book.RoleName = "编辑者" + book.RoleName = i18n.Tr(lang, "common.editor") } else if book.RoleId == 3 { - book.RoleName = "观察者" + book.RoleName = i18n.Tr(lang, "common.observer") } } } @@ -631,7 +632,7 @@ WHERE (relationship_id > 0 OR book.privately_owned = 0 or team.team_member_id > } // ReleaseContent 批量发布文档 -func (book *Book) ReleaseContent(bookId int) { +func (book *Book) ReleaseContent(bookId int, lang string) { releaseQueue <- bookId once.Do(func() { go func() { @@ -652,6 +653,7 @@ func (book *Book) ReleaseContent(bookId int) { } for _, item := range docs { item.BookId = bookId + item.Lang = lang _ = item.ReleaseContent() } @@ -679,7 +681,7 @@ func (book *Book) ResetDocumentNumber(bookId int) { } //导入项目 -func (book *Book) ImportBook(zipPath string) error { +func (book *Book) ImportBook(zipPath string, lang string) error { if !filetil.FileExists(zipPath) { return errors.New("文件不存在 => " + zipPath) } @@ -972,7 +974,7 @@ func (book *Book) ImportBook(zipPath string) error { book.Description = "【项目导入存在错误:" + err.Error() + "】" } logs.Info("项目导入完毕 => ", book.BookName) - book.ReleaseContent(book.BookId) + book.ReleaseContent(book.BookId, lang) return err } diff --git a/models/BookResult.go b/models/BookResult.go index 6d466db8..a5c987ea 100644 --- a/models/BookResult.go +++ b/models/BookResult.go @@ -17,6 +17,7 @@ import ( "github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/server/web" + "github.com/beego/i18n" "github.com/mindoc-org/mindoc/conf" "github.com/mindoc-org/mindoc/converter" "github.com/mindoc-org/mindoc/utils/cryptil" @@ -70,6 +71,7 @@ type BookResult struct { IsDisplayComment bool `json:"is_display_comment"` IsDownload bool `json:"is_download"` AutoSave bool `json:"auto_save"` + Lang string } func NewBookResult() *BookResult { @@ -85,6 +87,11 @@ func (m *BookResult) String() string { return string(ret) } +func (m *BookResult) SetLang(lang string) *BookResult { + m.Lang = lang + return m +} + // 根据项目标识查询项目以及指定用户权限的信息. func (m *BookResult) FindByIdentify(identify string, memberId int) (*BookResult, error) { if identify == "" || memberId <= 0 { @@ -131,13 +138,13 @@ func (m *BookResult) FindByIdentify(identify string, memberId int) (*BookResult, } if m.RoleId == conf.BookFounder { - m.RoleName = "创始人" + m.RoleName = i18n.Tr(m.Lang, "common.creator") } else if m.RoleId == conf.BookAdmin { - m.RoleName = "管理员" + m.RoleName = i18n.Tr(m.Lang, "common.administrator") } else if m.RoleId == conf.BookEditor { - m.RoleName = "编辑者" + m.RoleName = i18n.Tr(m.Lang, "common.editor") } else if m.RoleId == conf.BookObserver { - m.RoleName = "观察者" + m.RoleName = i18n.Tr(m.Lang, "common.observer") } doc := NewDocument() diff --git a/models/DocumentModel.go b/models/DocumentModel.go index d05e15c8..f0ed549c 100644 --- a/models/DocumentModel.go +++ b/models/DocumentModel.go @@ -3,6 +3,8 @@ package models import ( "time" + "github.com/beego/i18n" + "fmt" "strconv" @@ -44,6 +46,8 @@ type Document struct { IsOpen int `orm:"column(is_open);type(int);default(0)" json:"is_open"` ViewCount int `orm:"column(view_count);type(int)" json:"view_count"` AttachList []*Attachment `orm:"-" json:"attach"` + //i18n + Lang string `orm:"-"` } // 多字段唯一键 @@ -276,7 +280,7 @@ func (item *Document) Processor() *Document { //处理附件 attachList, err := NewAttachment().FindListByDocumentId(item.DocumentId) if err == nil && len(attachList) > 0 { - content := bytes.NewBufferString("