forked from forgejo/forgejo
Backport #24925, partially backport #24934 (`docs/content/doc/help/faq.zh-cn.md` file) Part of backport has already done by #24942 Also backport #24881 to avoid "deadlock" --------- Co-authored-by: Zettat123 <zettat123@gmail.com>
This commit is contained in:
parent
d2c9fb02dd
commit
37b73b3337
18 changed files with 2705 additions and 0 deletions
123
docs/content/doc/contributing/guidelines-backend.zh-cn.md
Normal file
123
docs/content/doc/contributing/guidelines-backend.zh-cn.md
Normal file
|
@ -0,0 +1,123 @@
|
|||
---
|
||||
date: "2023-05-25T23:41:00+08:00"
|
||||
title: "后端开发指南"
|
||||
slug: "guidelines-backend"
|
||||
weight: 20
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/guidelines-backend
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "contributing"
|
||||
name: "后端开发指南"
|
||||
weight: 20
|
||||
identifier: "guidelines-backend"
|
||||
---
|
||||
|
||||
# 后端开发指南
|
||||
|
||||
**目录**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## 背景
|
||||
|
||||
Gitea使用Golang作为后端编程语言。它使用了许多第三方包,并且自己也编写了一些包。
|
||||
例如,Gitea使用[Chi](https://github.com/go-chi/chi)作为基本的Web框架。[Xorm](https://xorm.io)是一个用于与数据库交互的ORM框架。
|
||||
因此,管理这些包非常重要。在开始编写后端代码之前,请参考以下准则。
|
||||
|
||||
## 包设计准则
|
||||
|
||||
### 包列表
|
||||
|
||||
为了保持易于理解的代码并避免循环依赖,拥有良好的代码结构是很重要的。Gitea后端分为以下几个部分:
|
||||
|
||||
- `build`:帮助构建Gitea的脚本。
|
||||
- `cmd`:包含所有Gitea的实际子命令,包括web、doctor、serv、hooks、admin等。`web`将启动Web服务。`serv`和`hooks`将被Git或OpenSSH调用。其他子命令可以帮助维护Gitea。
|
||||
- `tests`:常用的测试函数
|
||||
- `tests/integration`:集成测试,用于测试后端回归。
|
||||
- `tests/e2e`:端到端测试,用于测试前端和后端的兼容性和视觉回归。
|
||||
- `models`:包含由xorm用于构建数据库表的数据结构。它还包含查询和更新数据库的函数。应避免与其他Gitea代码的依赖关系。在某些情况下,比如日志记录时可以例外。
|
||||
- `models/db`:基本的数据库操作。所有其他`models/xxx`包都应依赖于此包。`GetEngine`函数只能从models/中调用。
|
||||
- `models/fixtures`:单元测试和集成测试中使用的示例数据。一个`yml`文件表示一个将在测试开始时加载到数据库中的表。
|
||||
- `models/migrations`:存储不同版本之间的数据库迁移。修改数据库结构的PR**必须**包含一个迁移步骤。
|
||||
- `modules`:在Gitea中处理特定功能的不同模块。工作正在进行中:其中一些模块应该移到`services`中,特别是那些依赖于models的模块,因为它们依赖于数据库。
|
||||
- `modules/setting`:存储从ini文件中读取的所有系统配置,并在各处引用。但是在可能的情况下,应将其作为函数参数使用。
|
||||
- `modules/git`:用于与`Git`命令行或Gogit包交互的包。
|
||||
- `public`:编译后的前端文件(JavaScript、图像、CSS等)
|
||||
- `routers`:处理服务器请求。由于它使用其他Gitea包来处理请求,因此其他包(models、modules或services)不能依赖于routers。
|
||||
- `routers/api`:包含`/api/v1`相关路由,用于处理RESTful API请求。
|
||||
- `routers/install`:只能在系统处于安装模式(INSTALL_LOCK=false)时响应。
|
||||
- `routers/private`:仅由内部子命令调用,特别是`serv`和`hooks`。
|
||||
- `routers/web`:处理来自Web浏览器或Git SMART HTTP协议的HTTP请求。
|
||||
- `services`:用于常见路由操作或命令执行的支持函数。使用`models`和`modules`来处理请求。
|
||||
- `templates`:用于生成HTML输出的Golang模板。
|
||||
|
||||
### 包依赖关系
|
||||
|
||||
由于Golang不支持导入循环,我们必须仔细决定包之间的依赖关系。这些包之间有一些级别。以下是理想的包依赖关系方向。
|
||||
|
||||
`cmd` -> `routers` -> `services` -> `models` -> `modules`
|
||||
|
||||
从左到右,左侧的包可以依赖于右侧的包,但右侧的包不能依赖于左侧的包。在同一级别的子包中,可以根据该级别的规则进行依赖。
|
||||
|
||||
**注意事项**
|
||||
|
||||
为什么我们需要在`models`之外使用数据库事务?以及如何使用?
|
||||
某些操作在数据库记录插入/更新/删除失败时应该允许回滚。
|
||||
因此,服务必须能够创建数据库事务。以下是一些示例:
|
||||
|
||||
```go
|
||||
// services/repository/repository.go
|
||||
func CreateXXXX() error {
|
||||
return db.WithTx(func(ctx context.Context) error {
|
||||
// do something, if err is returned, it will rollback automatically
|
||||
if err := issues.UpdateIssue(ctx, repoID); err != nil {
|
||||
// ...
|
||||
return err
|
||||
}
|
||||
// ...
|
||||
return nil
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
在`services`中**不应该**直接使用`db.GetEngine(ctx)`,而是应该在`models/`下编写一个函数。
|
||||
如果该函数将在事务中使用,请将`context.Context`作为函数的第一个参数。
|
||||
|
||||
```go
|
||||
// models/issues/issue.go
|
||||
func UpdateIssue(ctx context.Context, repoID int64) error {
|
||||
e := db.GetEngine(ctx)
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 包名称
|
||||
|
||||
对于顶层包,请使用复数作为包名,例如`services`、`models`,对于子包,请使用单数,例如`services/user`、`models/repository`。
|
||||
|
||||
### 导入别名
|
||||
|
||||
由于有一些使用相同包名的包,例如`modules/user`、`models/user`和`services/user`,当这些包在一个Go文件中被导入时,很难知道我们使用的是哪个包以及它是变量名还是导入名。因此,我们始终建议使用导入别名。为了与常见的驼峰命名法的包变量区分开,建议使用**snake_case**作为导入别名的命名规则。
|
||||
例如:`import user_service "code.gitea.io/gitea/services/user"`
|
||||
|
||||
### 重要注意事项
|
||||
|
||||
- 永远不要写成`x.Update(exemplar)`,而没有明确的`WHERE`子句:
|
||||
- 这将导致表中的所有行都被使用exemplar的非零值进行更新,包括ID。
|
||||
- 通常应该写成`x.ID(id).Update(exemplar)`。
|
||||
- 如果在迁移过程中使用`x.Insert(exemplar)`向表中插入记录,而ID是预设的:
|
||||
- 对于MSSQL变体,你将需要执行``SET IDENTITY_INSERT `table` ON``(否则迁移将失败)
|
||||
- 对于PostgreSQL,你还需要更新ID序列,否则迁移将悄无声息地通过,但后续的插入将失败:
|
||||
``SELECT setval('table_name_id_seq', COALESCE((SELECT MAX(id)+1 FROM `table_name`), 1), false)``
|
||||
|
||||
### 未来的任务
|
||||
|
||||
目前,我们正在进行一些重构,以完成以下任务:
|
||||
|
||||
- 纠正不符合规则的代码。
|
||||
- `models`中的文件太多了,所以我们正在将其中的一些移动到子包`models/xxx`中。
|
||||
- 由于它们依赖于`models`,因此应将某些`modules`子包移动到`services`中。
|
138
docs/content/doc/contributing/guidelines-frontend.zh-cn.md
Normal file
138
docs/content/doc/contributing/guidelines-frontend.zh-cn.md
Normal file
|
@ -0,0 +1,138 @@
|
|||
---
|
||||
date: "2023-05-25T16:00:00+02:00"
|
||||
title: "前端开发指南"
|
||||
slug: "guidelines-frontend"
|
||||
weight: 20
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/guidelines-frontend
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "contributing"
|
||||
name: "前端开发指南"
|
||||
weight: 20
|
||||
identifier: "guidelines-frontend"
|
||||
---
|
||||
|
||||
# 前端开发指南
|
||||
|
||||
**目录**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## 背景
|
||||
|
||||
Gitea 在其前端中使用[Fomantic-UI](https://fomantic-ui.com/introduction/getting-started.html)(基于[jQuery](https://api.jquery.com))和 [Vue3](https://vuejs.org/)。
|
||||
|
||||
HTML 页面由[Go HTML Template](https://pkg.go.dev/html/template)渲染。
|
||||
|
||||
源文件可以在以下目录中找到:
|
||||
|
||||
* **CSS 样式**: `web_src/css/`
|
||||
* **JavaScript 文件**: `web_src/js/`
|
||||
* **Vue 组件**: `web_src/js/components/`
|
||||
* **Go HTML 模板**: `templates/`
|
||||
|
||||
## 通用准则
|
||||
|
||||
我们推荐使用[Google HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.html)和[Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)。
|
||||
|
||||
## Gitea 特定准则:
|
||||
|
||||
1. 每个功能(Fomantic-UI/jQuery 模块)应放在单独的文件/目录中。
|
||||
2. HTML 的 id 和 class 应使用 kebab-case,最好包含2-3个与功能相关的关键词。
|
||||
3. 在 JavaScript 中使用的 HTML 的 id 和 class 应在整个项目中是唯一的,并且应包含2-3个与功能相关的关键词。建议在仅在 JavaScript 中使用的 class 中使用 `js-` 前缀。
|
||||
4. 不应覆盖框架提供的 class 的 CSS 样式。始终使用具有2-3个与功能相关的关键词的新 class 名称来覆盖框架样式。Gitea 中的帮助 CSS 类在 `helpers.less` 中。
|
||||
5. 后端可以通过使用`ctx.PageData["myModuleData"] = map[]{}`将复杂数据传递给前端,但不要将整个模型暴露给前端,以避免泄露敏感数据。
|
||||
6. 简单页面和与 SEO 相关的页面使用 Go HTML 模板渲染生成静态的 Fomantic-UI HTML 输出。复杂页面可以使用 Vue3。
|
||||
7. 明确变量类型,优先使用`elem.disabled = true`而不是`elem.setAttribute('disabled', 'anything')`,优先使用`$el.prop('checked', var === 'yes')`而不是`$el.prop('checked', var)`。
|
||||
8. 使用语义化元素,优先使用`<button class="ui button">`而不是`<div class="ui button">`。
|
||||
9. 避免在 CSS 中使用不必要的`!important`,如果无法避免,添加注释解释为什么需要它。
|
||||
10. 避免在一个事件监听器中混合不同的事件,优先为每个事件使用独立的事件监听器。
|
||||
11. 推荐使用自定义事件名称前缀`ce-`。
|
||||
12. Gitea 的 tailwind-style CSS 类使用`gt-`前缀(`gt-relative`),而 Gitea 自身的私有框架级 CSS 类使用`g-`前缀(`g-modal-confirm`)。
|
||||
|
||||
### 可访问性 / ARIA
|
||||
|
||||
在历史上,Gitea大量使用了可访问性不友好的框架 Fomantic UI。
|
||||
Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`aria.md`),
|
||||
但仍然存在许多问题需要大量的工作和时间来修复。
|
||||
|
||||
### 框架使用
|
||||
|
||||
不建议混合使用不同的框架,这会使代码难以维护。
|
||||
一个 JavaScript 模块应遵循一个主要框架,并遵循该框架的最佳实践。
|
||||
|
||||
推荐的实现方式:
|
||||
|
||||
* Vue + Vanilla JS
|
||||
* Fomantic-UI(jQuery)
|
||||
* Vanilla JS
|
||||
|
||||
不推荐的实现方式:
|
||||
|
||||
* Vue + Fomantic-UI(jQuery)
|
||||
* jQuery + Vanilla JS
|
||||
|
||||
为了保持界面一致,Vue 组件可以使用 Fomantic-UI 的 CSS 类。
|
||||
尽管不建议混合使用不同的框架,
|
||||
但如果混合使用是必要的,并且代码设计良好且易于维护,也可以工作。
|
||||
|
||||
### async 函数
|
||||
|
||||
只有当函数内部存在`await`调用或返回`Promise`时,才将函数标记为`async`。
|
||||
|
||||
不建议使用`async`事件监听器,这可能会导致问题。
|
||||
原因是`await`后的代码在事件分发之外执行。
|
||||
参考:https://github.com/github/eslint-plugin-github/blob/main/docs/rules/async-preventdefault.md
|
||||
|
||||
如果一个事件监听器必须是`async`,应在任何`await`之前使用`e.preventDefault()`,
|
||||
建议将其放在函数的开头。
|
||||
|
||||
如果我们想在非异步上下文中调用`async`函数,
|
||||
建议使用`const _promise = asyncFoo()`来告诉读者
|
||||
这是有意为之的,我们想调用异步函数并忽略Promise。
|
||||
一些 lint 规则和 IDE 也会在未处理返回的 Promise 时发出警告。
|
||||
|
||||
### HTML 属性和 dataset
|
||||
|
||||
禁止使用`dataset`,它的驼峰命名行为使得搜索属性变得困难。
|
||||
然而,仍然存在一些特殊情况,因此当前的准则是:
|
||||
|
||||
* 对于旧代码:
|
||||
* 应将`$.data()`重构为`$.attr()`。
|
||||
* 在极少数情况下,可以使用`$.data()`将一些非字符串数据绑定到元素上,但强烈不推荐使用。
|
||||
|
||||
* 对于新代码:
|
||||
* 不应使用`node.dataset`,而应使用`node.getAttribute`。
|
||||
* 不要将任何用户数据绑定到 DOM 节点上,使用合适的设计模式描述节点和数据之间的关系。
|
||||
|
||||
### 显示/隐藏元素
|
||||
|
||||
* 推荐在Vue组件中使用`v-if`和`v-show`来显示/隐藏元素。
|
||||
* Go 模板代码应使用 Gitea 的 `.gt-hidden` 和 `showElem()/hideElem()/toggleElem()` 来显示/隐藏元素,请参阅`.gt-hidden`的注释以获取更多详细信息。
|
||||
|
||||
### Go HTML 模板中的样式和属性
|
||||
|
||||
建议使用以下方式:
|
||||
|
||||
```html
|
||||
<div class="gt-name1 gt-name2 {{if .IsFoo}}gt-foo{{end}}" {{if .IsFoo}}data-foo{{end}}></div>
|
||||
```
|
||||
|
||||
而不是:
|
||||
|
||||
```html
|
||||
<div class="gt-name1 gt-name2{{if .IsFoo}} gt-foo{{end}}"{{if .IsFoo}} data-foo{{end}}></div>
|
||||
```
|
||||
|
||||
以使代码更易读。
|
||||
|
||||
### 旧代码
|
||||
|
||||
许多旧代码已经存在于本文撰写之前。建议重构旧代码以遵循指南。
|
||||
|
||||
### Vue3 和 JSX
|
||||
|
||||
Gitea 现在正在使用 Vue3。我们决定不引入 JSX,以保持 HTML 代码和 JavaScript 代码分离。
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
date: "2023-05-25T00:00:00+00:00"
|
||||
title: "重构指南"
|
||||
slug: "guidelines-refactoring"
|
||||
weight: 20
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/guidelines-refactoring
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "contributing"
|
||||
name: "重构指南"
|
||||
weight: 20
|
||||
identifier: "guidelines-refactoring"
|
||||
---
|
||||
|
||||
# 重构指南
|
||||
|
||||
**目录**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## 背景
|
||||
|
||||
自2014年2月12日编写了第一行代码以来,Gitea已经发展成为一个庞大的项目。
|
||||
因此,代码库变得越来越大。代码库越大,维护就越困难。
|
||||
存在许多过时的机制,许多框架混合在一起,一些遗留代码可能会导致错误并阻碍新功能的开发。
|
||||
为了使代码库更易于维护,使Gitea变得更好,开发人员应牢记使用现代机制来重构旧代码。
|
||||
|
||||
本文档是关于重构代码库的指南集合。
|
||||
|
||||
## 重构建议
|
||||
|
||||
* 设计更多关于未来的内容,而不仅仅解决当前问题。
|
||||
* 减少模糊性,减少冲突,提高可维护性。
|
||||
* 描述重构,例如:
|
||||
* 为什么需要重构。
|
||||
* 如何解决旧问题。
|
||||
* 重构的优点/缺点是什么。
|
||||
* 只做必要的更改,尽量保留旧逻辑。
|
||||
* 引入一些中间步骤,使重构更容易审查,完整的重构计划可以在几个PR中完成。
|
||||
* 如果存在分歧,应该请TOC(技术监督委员会)参与决策。
|
||||
* 添加必要的测试以确保重构的正确性。
|
||||
* 非错误重构优先在里程碑的开始时进行,这样可以更容易地在发布之前发现问题。
|
||||
|
||||
## 审查和合并建议
|
||||
|
||||
* 重构的PR不应该长时间保持打开状态(通常为7天),应尽快进行审查。
|
||||
* 重构的PR应尽快合并,不应被其他PR阻塞。
|
||||
* 如果TOC没有异议,重构的PR可以在7天后由一名核心成员(非作者)批准后合并。
|
||||
* 如果最终结果良好,容忍一些不完美/临时的步骤。
|
||||
* 如果重构是必要的,容忍一些回归错误,并尽快修复错误。
|
17
docs/content/doc/contributing/translation.zh-cn.md
Normal file
17
docs/content/doc/contributing/translation.zh-cn.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
date: "2023-05-25T00:00:00+02:00"
|
||||
title: "翻译指南"
|
||||
weight: 70
|
||||
toc: true
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "contributing"
|
||||
name: "翻译指南"
|
||||
weight: 70
|
||||
identifier: "translation-guidelines"
|
||||
---
|
||||
|
||||
本页面用于提供一套通用规则,以确保翻译的一致性。
|
||||
|
||||
* [German](/de-de/übersetzungs-richtlinien/)
|
Loading…
Add table
Add a link
Reference in a new issue