Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Chinese docs for help, contribution and development (#24925) #25011

Merged
merged 5 commits into from
May 31, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions docs/content/doc/contributing/guidelines-backend.zh-cn.md
Original file line number Diff line number Diff line change
@@ -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 changes: 138 additions & 0 deletions docs/content/doc/contributing/guidelines-frontend.zh-cn.md
Original file line number Diff line number Diff line change
@@ -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 代码分离。
53 changes: 53 additions & 0 deletions docs/content/doc/contributing/guidelines-refactoring.zh-cn.md
Original file line number Diff line number Diff line change
@@ -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 changes: 17 additions & 0 deletions docs/content/doc/contributing/translation.zh-cn.md
Original file line number Diff line number Diff line change
@@ -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/)
46 changes: 46 additions & 0 deletions docs/content/doc/development/integrations.zh-cn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
date: "2023-05-25T17:29:00+08:00"
title: "集成"
slug: "integrations"
weight: 65
toc: false
draft: false
aliases:
- /zh-cn/integrations
menu:
sidebar:
parent: "development"
name: "集成"
weight: 65
identifier: "integrations"
---

# 集成

Gitea拥有一个出色的第三方集成社区,以及在其他各种项目中的一流支持。

我们正在[awesome-gitea](https://gitea.com/gitea/awesome-gitea)上整理一个列表来跟踪这些集成!

如果你正在寻找[CI/CD](https://gitea.com/gitea/awesome-gitea#user-content-devops),
一个[SDK](https://gitea.com/gitea/awesome-gitea#user-content-sdk),
甚至一些额外的[主题](https://gitea.com/gitea/awesome-gitea#user-content-themes),
你可以在[awesome-gitea](https://gitea.com/gitea/awesome-gitea)中找到它们的列表!

## 预填新文件名和内容

如果你想打开一个具有给定名称和内容的新文件,
你可以使用查询参数来实现:

```txt
GET /{{org}}/{{repo}}/_new/{{filepath}}
?filename={{filename}}
&value={{content}}
```

例如:

```txt
GET https://git.example.com/johndoe/bliss/_new/articles/
?filename=hello-world.md
&value=Hello%2C%20World!
```
Loading