diff --git a/docs/zh-Hans/Index.md b/docs/zh-Hans/Index.md
index 71e5a520da..ce4fcfa3b4 100644
--- a/docs/zh-Hans/Index.md
+++ b/docs/zh-Hans/Index.md
@@ -10,7 +10,8 @@ ABP是一个**开源应用程序框架**,专注于基于ASP.NET Core的Web应用
使用ABP开发新项目的最简单方法是使用启动模板:
-* [ASP.NET Core MVC 模板](Getting-Started-AspNetCore-MVC-Template.md)
+* [ASP.NET Core MVC (Razor Pages) UI 启动模板](Getting-Started?UI=MVC&DB=EF&Tiered=No)
+* [Angular UI 启动模板](Getting-Started?UI=NG&DB=EF&Tiered=No)
如果你想从头开始(使用空项目),请手动安装ABP框架并使用以下教程:
diff --git a/docs/zh-Hans/Road-Map.md b/docs/zh-Hans/Road-Map.md
new file mode 100644
index 0000000000..b764ce2e2e
--- /dev/null
+++ b/docs/zh-Hans/Road-Map.md
@@ -0,0 +1,11 @@
+# ABP Framework 路线图
+
+您可以随时在[GitHub仓库](https://github.com/abpframework/abp/milestones)上查看里程碑计划和优先的积压问题,获取详细的路线图.
+
+虽然我们将**继续添加其他令人兴奋的功能**,但我们将在`中期`中处理以下主要项目:
+
+* **gRPC 集成**和为所有预构建模块实现它.
+* 为所有预构建模块实现 **Blazor UI**.
+* **.NET 5.0**! Microsoft宣布.NET 5.0将在2020年11月发布,我们将为此更改做准备并在Microsoft发布它之后立即迁移到.NET 5.0. 我们希望顺利过渡.
+
+请在[GitHub仓库](https://github.com/abpframework/abpork/abp/milestones)为你的功能请求创建issue,但在创建前请先搜索是否已存在类似的issues.
\ No newline at end of file
diff --git a/docs/zh-Hans/Text-Templating.md b/docs/zh-Hans/Text-Templating.md
index 3d3941c607..0785dbba29 100644
--- a/docs/zh-Hans/Text-Templating.md
+++ b/docs/zh-Hans/Text-Templating.md
@@ -204,13 +204,14 @@ PascalCase 属性名(如 `UserName`) 在模板中用做小驼峰(如 `userName`)
假设你需要向用户发送电子邮件重置密码. 模板内容:
````
-{%{{{L "ResetMyPassword"}}}%}
+{%{{{L "ResetMyPassword" model.name}}}%}
````
`L` 函数用于根据当前用户的文化来定位给定的Key,你需要在本地化文件中定义 `ResetMyPassword` 键:
````json
-"ResetMyPassword": "Click here to reset your password"
+"ResetMyPasswordTitle": "Reset my password",
+"ResetMyPassword": "Hi {0}, Click here to reset your password"
````
你还需要在模板定义提供程序类中声明要与此模板一起使用的本地化资源:
@@ -234,6 +235,7 @@ var result = await _templateRenderer.RenderAsync(
"PasswordReset", //the template name
new PasswordResetModel
{
+ Name = "john",
Link = "https://abp.io/example-link?userId=123&token=ABC"
}
);
@@ -242,7 +244,7 @@ var result = await _templateRenderer.RenderAsync(
你可以看到以下本地化结果:
````csharp
-Click here to reset your password
+Hi john, Click here to reset your password
````
> 如果你为应用程序定义了 [默认本地化资源](Localization.md), 则无需声明模板定义的资源类型.
diff --git a/docs/zh-Hans/UI/Angular/List-Service.md b/docs/zh-Hans/UI/Angular/List-Service.md
new file mode 100644
index 0000000000..6d5bc6f1ef
--- /dev/null
+++ b/docs/zh-Hans/UI/Angular/List-Service.md
@@ -0,0 +1,163 @@
+# 使用ListService轻松查询列表
+
+`ListService` 是一种实用程序服务,提供简单的分页,排序和搜索实现.
+
+## 入门
+
+`ListService` **没有在根提供**. 原因是通过这种方式它会清除组件上的所有订阅. 你可以使用可选的 `LIST_QUERY_DEBOUNCE_TIME` 令牌调整debounce行为.
+
+```js
+import { ListService } from '@abp/ng.core';
+import { BookDto } from '../models';
+import { BookService } from '../services';
+
+@Component({
+ /* class metadata here */
+ providers: [
+ // [Required]
+ ListService,
+
+ // [Optional]
+ // Provide this token if you want a different debounce time.
+ // Default is 300. Cannot be 0. Any value below 100 is not recommended.
+ { provide: LIST_QUERY_DEBOUNCE_TIME, useValue: 500 },
+ ],
+ template: `
+
+ `,
+})
+class BookComponent {
+ items: BookDto[] = [];
+ count = 0;
+
+ constructor(
+ public readonly list: ListService,
+ private bookService: BookService,
+ ) {}
+
+ ngOnInit() {
+ // A function that gets query and returns an observable
+ const bookStreamCreator = query => this.bookService.getList(query);
+
+ this.list.hookToQuery(bookStreamCreator).subscribe(
+ response => {
+ this.items = response.items;
+ this.count = response.count;
+ // If you use OnPush change detection strategy,
+ // call detectChanges method of ChangeDetectorRef here.
+ }
+ ); // Subscription is auto-cleared on destroy.
+ }
+}
+```
+
+> 注意 `list` 是 `public` 并且 `readonly`. 因为我们将直接在组件的模板中使用 `ListService` 属性. 可以视为反模式,但是实现起来要快得多. 你可以改为使用公共组件属性.
+
+将 `ListService` 属性放入模板中,如下所示:
+
+```html
+
+
+
+
+
+ |
+ {%{{{ '::Name' | abpLocalization }}}%}
+
+ |
+
+
+
+
+
+ | {%{{{ data.name }}}%} |
+
+
+```
+
+## 与Observables一起使用
+
+你可以将Observables与Angular的[AsyncPipe](https://angular.io/guide/observables-in-angular#async-pipe)结合使用:
+
+```ts
+ book$ = this.list.hookToQuery(query => this.bookService.getListByInput(query));
+```
+
+```html
+
+
+
+
+
+
+```
+
+...or...
+
+
+```ts
+ @Select(BookState.getBooks)
+ books$: Observable;
+
+ @Select(BookState.getBookCount)
+ bookCount$: Observable;
+
+ ngOnInit() {
+ this.list.hookToQuery((query) => this.store.dispatch(new GetBooks(query))).subscribe();
+ }
+```
+
+```html
+
+
+
+
+```
+
+## 如何在创建/更新/删除时刷新表
+
+`ListService` 公开了一个 `get` 方法来触发当前查询的请求. 因此基本上每当创建,更新或删除操作解析时,你可以调用 `this.list.get();` 它会调用钩子流创建者.
+
+```ts
+this.store.dispatch(new DeleteBook(id)).subscribe(this.list.get);
+```
+
+...or...
+
+```ts
+this.bookService.createByInput(form.value)
+ .subscribe(() => {
+ this.list.get();
+
+ // Other subscription logic here
+ })
+```
+
+## 如何在表中实现服务器端搜索
+
+`ListService` 公开一个 `filter` 属性,该属性将使用当前查询和给定的搜索字符串触发一个请求. 你需要做的就是通过双向绑定将其绑定到输入元素.
+
+```html
+
+
+
+```
diff --git a/docs/zh-Hans/docs-nav.json b/docs/zh-Hans/docs-nav.json
index a3becc073b..0111eabc31 100644
--- a/docs/zh-Hans/docs-nav.json
+++ b/docs/zh-Hans/docs-nav.json
@@ -372,6 +372,10 @@
{
"text": "TrackByService",
"path": "UI/Angular/Track-By-Service.md"
+ },
+ {
+ "text": "ListService",
+ "path": "UI/Angular/List-Service.md"
}
]
},