diff --git a/TODO/a-primer-on-android-navigation.md b/TODO/a-primer-on-android-navigation.md
index 2411e4946c3..cfcf4555cce 100644
--- a/TODO/a-primer-on-android-navigation.md
+++ b/TODO/a-primer-on-android-navigation.md
@@ -3,89 +3,88 @@
> * 原文作者:[Liam Spradlin](https://medium.com/@LiamSpradlin)
> * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
> * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO/a-primer-on-android-navigation.md](https://github.com/xitu/gold-miner/blob/master/TODO/a-primer-on-android-navigation.md)
-> * 译者:
-> * 校对者:
+> * 译者:[horizon13th](https://github.com/horizon13th)
+> * 校对者:[SumiMakito](https://github.com/sumimakito), [laiyun90](https://github.com/laiyun90)
-# A Primer on Android navigation
+# 安卓界面导航初识
-> Any vehicle someone uses to move between scenes in your interface — that’s navigation
+> 界面中任何引领用户跳转于页面之间的媒介 —— 这便是导航
-As soon as you link two screens together in an app, you have navigation. That link—whatever it may be—is the vehicle that carries users between those screens. And although creating navigation is relatively simple, creating the *right* navigation for your users isn’t always straightforward. In this post we’ll take a look at some of the most common navigation patterns used on Android, how they impact system-level navigation, and how to mix and match patterns to suit your interface and your users.
+当你的应用中的两个不同页面产生联系时,导航便由此而生。跳转链接(不论从哪跳到哪)便是页面间传递用户的媒介。创建导航相对容易,但想要把导航**做好**并不总是那么简单。这篇博文里,我们探讨一下安卓系统下最常见的导航模式,看看它们是怎样影响系统布局,以及如何为你的应用界面,用户量身打造导航栏。
---
-### ✏️ Defining navigation
+### ✏️ 定义导航
-Before digging into common navigation patterns, it’s worth stepping back and finding a starting point for thinking about navigation in your app.
+在深入探索导航模式前,让我们先退后一步回到起点,做一个小练习,回想一下你的应用中的导航。
-The Material Design spec has some [great guidance](https://material.io/guidelines/patterns/navigation.html#navigation-defining-your-navigation) on how to approach defining navigation structures, but for the purposes of this post we can boil everything down to two simple points:
+在 Material Design 网站中有许多 [优秀设计规范](https://material.io/guidelines/patterns/navigation.html#navigation-defining-your-navigation) 介绍了如何着手定义导航结构。但本文中我们把所有的理论归结为简单的两点:
-- Build navigation *based on* tasks and content
-- Build navigation *for* people
+- 基于**任务和内容**构建导航
+- 基于**用户**构建导航
-Building navigation based on tasks and content means breaking down what tasks people will be performing, and what they’ll see along the way, and mapping out relationships between the two. Determine how tasks relate to one another — which tasks are more or less important, which tasks are siblings, which ones nest inside one another, and which tasks will be performed more or less often.
+基于**任务和内容**构建导航意味着,将任务分步骤拆分。设想用户在完成任务的过程中应该做什么看到什么,怎样处理步骤之间的关系,决定哪一步更重要,哪些步骤是并列关系,哪些步骤是包含关系,哪些步骤常见或不常见。
-That’s where building navigation for people comes in — the people using your interface can tell you whether it’s working for them or not, and your navigation should be built around helping them succeed in your app.
+至于基于**用户**构建导航,只有真正使用过你设计的界面的用户才能告诉你这适不适合他们。你所设计的导航最好能帮助他们更好地使用应用,带给他们最大化的便利。
-Once you know how the tasks in your app work together, you can decide what content users need to see along the way and when and how to present it—this exercise should provide a good foundation for deciding which patterns best serve your app’s experience.
+当你搞清楚在你的应用中,多个任务怎样协同工作的,便可以着手设计。用户在完成任务的过程中可以看到什么内容,在什么时候,以什么方式来呈现。这个小练习能够让你从根本上思考什么样的设计模式能更好地服务于你的 app 体验。
-*📚 Find more detailed guidance on breaking down tasks and behaviors for navigation *[*in the Material spec*](https://material.io/guidelines/patterns/navigation.html)*.*
+📚 分解任务行为以设计导航更多内容,详见 [Material Design](https://material.io/guidelines/patterns/navigation.html)。
---
-### 🗂 Tabs
+### 🗂 标签页(Tabs)
![](https://cdn-images-1.medium.com/max/2000/1*7VP4nwgLIOSLg2W13Iz6Dg.png)
-#### Definition
+#### 定义
-Tabs provide quick navigation between sibling views inside the same parent screen. They’re coplanar, meaning they can be swiped around, and they live in an extensible, identifiable tab bar.
+标签页提供了在相同父页面场景下,同级页面间的快速导航。所有的选项卡是位于同一平面的,这意味着,他们可以放置在同一可扩展的状态栏上,也可以相互改变位置。
-Tabs are great for filtering, segmenting, or providing depth to related pieces of content. Unrelated pieces of content, or content with its own deep hierarchy may be better served by using other navigation patterns.
+标签页是很好的页面内容过滤、分段、分级工具。但是对于毫无关联的内容,或是层级化结构内容,也许其它的导航模式会更合适。
-*📚 Find all the details on designing tabs *[*here*](https://material.io/guidelines/components/tabs.html#)*, and on implementing tabs *[*here*](https://developer.android.com/training/implementing-navigation/lateral.html)*.*
-
-#### Tabs in action
+📚 设计标签页的更多细节 [参考此处](https://material.io/guidelines/components/tabs.html#),更多实现 [参考此处](https://developer.android.com/training/implementing-navigation/lateral.html)。
+#### 标签页实例
![](https://cdn-images-1.medium.com/max/800/1*tgbpHME812InaPR0FW6qaw.png)
![](https://cdn-images-1.medium.com/max/800/1*BrOW6gtAXsqg4xymoOq9pQ.png)
![](https://cdn-images-1.medium.com/max/800/1*PJTRuuAemKls6g1l9YJkqQ.png)
-Play Music, Google+, Play Newsstand
+Play Music 应用,Google+ 应用,Play Newsstand 应用
-Play Music *(above, left)* uses tabs to add depth to the music library, organizing the same general content in different ways to accommodate different means of exploration.
+Play Music 应用(左)使用标签页增加音乐库的探索深度,以不同的方式组织大致相同的内容,为用户定制不同的探索方法。
-Google+ *(above, center)* uses tabs to segment Collections, a single content type that leads to very heterogeneous content deeper in the app.
+Google+ 应用(中)使用标签页将收藏列表分块,每个类别下都是深层异构的内容。
-Play Newsstand *(above, right)* uses tabs on the Library screen to present different sets of the same information — one tab presents a holistic, multi-layered collection, while the other shows a condensed set of headlines.
+Play Newsstand 应用(右)在媒体库页面使用标签页来呈现相同信息的不同集合 - 其中一个选项卡呈现一个整体的多层次的集合,另一个选项卡显示浓缩集合的大标题。
-#### History
+#### 访问记录
-Tabs exist on one level together, inside the same parent screen. So navigating between tabs should not create history either for the system back button or for the app’s up button.
+标签页一般为同一级别,因此它们的布局在相同的父级页面下。两个标签页间的切换不需要为系统后退键或应用的返回键新建历史记录。
---
-### 🍔 Nav drawers
+### 🍔 侧边栏/抽屉式导航栏(Nav drawers)
![](https://cdn-images-1.medium.com/max/2000/1*OlvxTeFymVd35TFE1d4QcA.png)
-#### Definition
+#### 定义
-The navigation drawer is generally a vertical pane attached to the left edge of the canvas. Drawers can manifest off-screen or on, persistent or not, but they always share some common characteristics.
+侧边栏(抽屉式导航栏)可以理解为附于页面左部边缘的垂直面板。设计者可以将侧边栏设计在屏幕外或屏幕内可见,持续存在或者不用时隐藏,但这些不同的设计往往有相同的特点。
-Typically, the nav drawer lists parent destinations that are peers or siblings with one another. A nav drawer can be used in apps with several primary destinations, and some unique supporting destinations like settings or help.
+通常侧边栏会列出一些同级的父级页面们,尤其用于放置较重要的页面,又例如一些“设置”,“帮助”这类特殊页面。
-If you combine the drawer with another primary navigation component — bottom nav, for example — the drawer can contain secondary destinations, or important destinations that don’t directly follow in the hierarchy from the bottom nav.
+如果你将侧边栏和另一个导航控件相组合——底部导航栏,那么侧边栏可以放置一些二级链接,或者底部导航不能直接到达的重要链接。
-When using the nav drawer, be aware of what *kinds* of destinations you’re presenting — adding too many destinations or destinations that represent different levels in the app’s hierarchy can get confusing.
+当使用侧边栏时,要注意链接**类别**——放过多的链接,或展示过多不同级别的链接,都会让应用的层次结构显得混乱。
-Also be aware of visibility — the drawer can be good for reducing visibility or compacting navigation away from the main content area, but that can also be a drawback depending on how the destinations in your app need to be presented and accessed.
+还有需要注意的一点是界面的可视性。侧边栏可以很好的帮助应用减少可视性,压缩与主要内容无关的导航区。但是,这也可能成为应用的不足,取决于导航栏的目标链接在具体场景中如何呈现和被访问。
-*📚 Get detailed guidance on nav drawer design *[*here*](https://material.io/guidelines/patterns/navigation-drawer.html)*, and implementation *[*here*](https://developer.android.com/training/implementing-navigation/nav-drawer.html)*.*
+📚 设计侧边栏的更多细节[参考此处](https://material.io/guidelines/patterns/navigation-drawer.html),更多实现[参考此处](https://developer.android.com/training/implementing-navigation/nav-drawer.html)。
-#### Nav drawers in action
+#### 侧边栏实例
![](https://cdn-images-1.medium.com/max/800/1*dFyqnTkAgdbLlFf5unYuTg.png)
@@ -93,21 +92,19 @@ Also be aware of visibility — the drawer can be good for reducing visibili
![](https://cdn-images-1.medium.com/max/800/1*t4KPT6fq_zgLH04hEuDsag.png)
-Play Store, Google Camera, Inbox
-
-The Play Store *(above, left)* uses the nav drawer to point to different sections of the store, each dedicated to a different type of content.
+Play Store 应用,Google Camera 应用,Inbox 应用
-Google Camera *(above, center)* uses the drawer for supporting destinations — these are mostly destinations that augment the capture experience, plus a path to settings.
+Play Store 应用(左上)使用侧边栏展示应用商店的不同区域,每一栏都链接到不同区域的内容。
-Inbox *(above, right)* has an extensible nav drawer that can get quite long. At the top are primary destinations that present different segments of your email, and below those are supporting segments called bundles.
+Google Camera(中上)使用侧边栏列出其它支持功能——大部分是提升照相体验的其他应用外链,当然了还有相机设置。
-Because the nav drawer in Inbox can get so long, the “settings” and “help & feedback” items are presented in a persistent sheet, accessible from anywhere in the drawer.
+Inbox(右上)邮箱应用使用了伸长版的侧边栏。顶端是电子邮箱的主要功能链接,用于展示不同类别的邮件,侧边栏的下方则为一些支持工具和扩展包。由于电子邮箱的侧边栏非常的长,“设置”和“帮助反馈”按钮固定在侧边栏底端,方便用户随时访问。
-#### History
+#### 访问记录
-Nav drawers should generally create history for the system back button when the app has a distinct “Home” destination. In the Play Store, the home destination is the Apps & Games entry, which actually presents the user with tab navigation to see highlighted content of all types. So the Play Store creates history to get back to that destination from other areas of the app.
+当应用程序有明显的“返回首页”功能时,侧边栏应当为系统创建“返回首页”的功能。例如,在 Play Store 应用商店中,点击“返回首页”按钮回到页面“应用程序及游戏”,展示给用户的是所有类别的精选应用。因而 Play Store 应用创建了从其它页面到主页面的返回功能。
-Google Camera likewise takes users back to the default, primary capture mode minus any augmentation.
+同样的,在使用 Google Camera 相机应用时,当用户点击返回键时,返回到相机的默认拍摄界面。
![](https://cdn-images-1.medium.com/max/800/1*lVkPA6HXWIXX83XwkLZFuA.png)
@@ -115,9 +112,9 @@ Google Camera likewise takes users back to the default, primary capture mode min
![](https://cdn-images-1.medium.com/max/800/1*IsXPcy3A3NB0DcuypPqG9A.png)
-The “start driving” entry augments the primary map view
+“开始导航” 圆形按钮增强主地图功能。
-The same goes for Google Maps *(above)* — any destination in the drawer is presented as either a layer on top of or an augmentation to the primary map screen, so the back button brings us back to a clean slate.
+谷歌地图(如上)也用了相同的方案,侧边栏的选项要么是在地图上加层,要么增强主地图提供辅助功能。所以当用户点击“返回”按钮时回到的也是默认地图界面。
![](https://cdn-images-1.medium.com/max/800/1*cZMuV29jlk2r-SKVWOTCTw.png)
@@ -125,27 +122,27 @@ The same goes for Google Maps *(above)* — any destination in the drawer is
![](https://cdn-images-1.medium.com/max/800/1*nq4Zb0Oc_6_pDfpCIUufGw.png)
-You may notice the Play Store *(above)* doesn’t change the nav drawer indicator in the toolbar to an “up” button once you navigate to a destination. This is because the primary destinations in the drawer are on an equal level in the app’s navigation hierarchy. Since you aren’t moving deeper into the app by selecting “Movies & TV” from the drawer, you can’t go further up. You’re still at the top level, just on a parallel screen.
+你可能会注意到,随着你进入其他页面,Play Store 谷歌商店(上图)工具栏中的侧边栏图标并未改变。这是因为侧边栏的按钮在应用的层级结构中为同一级别。由于用户并没有深入到子级页面(例如,点击“音乐与视频”),因而侧边栏的图标并不会改变成返回上一级的样式。用户始终在最顶级的页面,只不过是在同级页面中切换而已。
---
-### 🚨 Bottom nav
+### 🚨 底部导航(Bottom nav)
![](https://cdn-images-1.medium.com/max/2000/1*ucVh0hZm7BLSQiI-yzet3Q.png)
-#### Definition
+#### 定义
-On Android, the bottom nav component is comprised of between three and five primary destinations. Importantly, “more” is not a destination. Neither are menus nor dialogs.
+在安卓系统中,底部导航控件通常由三到五个目的地按钮构成。重要的一点是,“更多”按钮并不能看作一个目的地,更不是菜单或对话框。
-Bottom navigation works best when your app has a limited number of disparate top-level destinations (bottom nav should never scroll) that need to be instantly accessible. One of the main benefits of a “bottom bar” is being able to jump from a child screen to an unrelated parent screen instantly, without navigating back up to the current parent first.
+当你的应用只有有限个数的顶级页面需要被访问时,使用底部导航栏最合适(底部导航千万不能滚动)。底栏最主要的优点在于,可以从子页面迅速跳入毫无关联的顶级页面,而无需先导航到当前页面的父页面。
-It’s important to note that while destinations in the bottom bar should all be equal in the app’s navigation hierarchy, items in the bottom bar are not coplanar the way tabs are, and shouldn’t be presented as such.
+值得注意的是,尽管底部导航的链接应当在应用中有相同的层级结构,但是他们和标签页截然不同,也绝不能以标签页的形式展现。
-Swiping between destinations in the bottom bar suggests a relationship between destinations that doesn’t exist. Each destination should be a discrete parent, not a sibling of the other destinations. If the destinations in your app are similar or present similar content, they may be better suited for tabs.
+切换底部栏,暗示着两个面板是毫无关系的。每个面板是孤立的父节点,而不是其它面板的兄弟节点。如果你的应用中,两个面板有相同内容或者相同的父节点,也许用标签页是更好的选择。
-*📚 Find more detailed design guidance for bottom nav *[*here*](https://material.io/guidelines/components/bottom-navigation.html#)*, and implementation details *[*here*](https://developer.android.com/reference/android/support/design/widget/BottomNavigationView.html)*.*
+📚 设计底部导航的更多细节[参考此处](https://material.io/guidelines/components/bottom-navigation.html#),更多实现[参考此处](https://developer.android.com/reference/android/support/design/widget/BottomNavigationView.html)。
-#### Bottom nav in action
+#### 底部导航实例
![](https://cdn-images-1.medium.com/max/800/1*FCTrc2tb_5VLXSLmCGd0Qw.png)
@@ -153,41 +150,41 @@ Swiping between destinations in the bottom bar suggests a relationship between d
![](https://cdn-images-1.medium.com/max/800/1*3_WrkSIhD7Y7jG9h4nCM6Q.png)
-Google Photos
+Google Photos 相册应用
-Bottom nav has some interesting considerations beyond its basic definition. Probably most complex is the notion of just *how* persistent the bottom bar should be. The answer, as with so many design decisions, is “it depends.”
+除了底部导航的基本定义,还有一些有意思的点值得考虑。也许最复杂的问题就是:底部导航栏是否要持续存在?答案和许多设计决策一样,那就是:“看情况”。
-Typically the bottom bar persists across the entire app, but there are some cases that could justify hiding the bottom bar. If the user enters a very shallow hierarchy — on single-purpose screens like message composition — or if the app wants to present a more immersive experience a step or two deep into the hierarchy, the bottom bar may be hidden.
+通常底部导航在整个应用中是持续存在的,但在某些情况下,导航栏是隐藏的状态。例如用户使用的应用只有很浅的层次结构,像收发短信这类单一功能的页面,又或者应用想给用户更深刻的用户体验,那底部导航或许隐藏起来更好。
-In Google Photos *(above)*, the bottom nav disappears inside albums. Albums are presented as a secondary layer in the hierarchy, and the only further navigational action is opening a photo, which itself opens on top of the album UI. This implementation satisfies the “single-purpose” rule for hiding the bottom nav while serving the goal of creating a more immersive experience once the user gets beyond the top level.
+在 Google Photos 相册应用中(上图),底部导航在相册中是隐藏的。相册在整个层级结构中处于第二层,比相册更深一层只有查看相片,打开它时从相册页面顶部展现。这种实现方式满足了隐藏底边导航以达到“唯一目的”的规则。当用户进入程序最顶层时,为其创造沉浸式体验。
-#### Additional considerations
+#### 其它考虑
-If the bar is persistent across the entire app, the next logical consideration would be behavior when jumping between destinations using the bar. If the user is several layers deep in a hierarchy stemming from one destination and they switch to another destination and then switch back to the first, what should they see? The parent screen, or the child screen on which they left off?
+如果底部导航在整个应用中持续存在,那么下一个需要考虑的问题便是底部导航的跳转逻辑。假设一个用户在深层层级结构中进行跳转,从一个子页面切换到另一个子页面,再点击返回跳转到前一个子页面,那他到底应该看到哪一个页面呢?父级页面?还是他停留过的子级页面?
-This decision should be informed by those using your app. In general, tapping an item in the bottom bar should go directly to the associated screen, not to a deeper layer of the hierarchy, but as with any guideline — *deviate with purpose.*
+这个功能应该取决于应用的使用者。一般来说,点击底部按钮应该直接跳转到关联页面,而不是更深层的页面。不过话说回来还是老问题,**看情况**。
-#### History
+#### 访问记录
-Bottom nav shouldn’t create history for the system back button. Going deeper into hierarchies stemming from bottom nav destinations can create history for the system back button *and* the app’s up button, but the bottom bar can serve as its own sort of historical navigation as well.
+底部导航栏的点按不应该为系统“返回键”创建历史记录。不过层级结构中进入深层级可以为系统“返回键”创造系统历史记录,为应用创建“返回上级”访问记录,但是底部栏其本身便是一种具有记录历史特性的导航结构。
-Tapping an item in bottom nav should take you straight to the associated destination, and tapping it again should navigate back to the parent level, or refresh the parent level if the user’s already there.
+点按底部导航按钮,应当直接跳转到关联页面。用户再次点击按钮应当跳转到该栏的父页面,或者当用户以及在父级页面时刷新页面。
---
-### 🕹 In-context navigation
+### 🕹 上下文导航(In-context navigation)
![](https://cdn-images-1.medium.com/max/2000/1*urOlDr3ceb6JiqdQsS4GmQ.png)
-#### Definition
+#### 定义
-In-context navigation is comprised of any navigational interaction outside of the components described above. This includes things like buttons, tiles, cards, and anything else that takes the user elsewhere in an app.
+上下文导航由所有非上述导航控件间的交互组成。这些控件包括像按钮、方块、卡片,还有其它应用内跳转的内容。
-In-context navigation is typically less linear than explicit navigation — interactions may transport the user through a hierarchy, between different steps in discrete hierarchies, or out of the app entirely.
+通常,上下文导航和常用导航形式相比,更多是非线性操作 —— 交互行为使用户在层级结构,离散型结构之间任意跳转,甚至跳转到应用之外。
-*📚 Look for more guidance on in-context navigation *[*here*](https://material.io/guidelines/patterns/navigation.html#navigation-combined-patterns)*.*
+📚 设计上下文导航的更多细节[参考此处](https://material.io/guidelines/patterns/navigation.html#navigation-combined-patterns)。
-#### In-context navigation in action
+#### 上下文导航实例
![](https://cdn-images-1.medium.com/max/800/1*kAS321rLOPopo2wj5Pt1rQ.png)
@@ -195,9 +192,9 @@ In-context navigation is typically less linear than explicit navigation —
![](https://cdn-images-1.medium.com/max/800/1*Ks9Fvut3daB1khAkoB7aaQ.png)
-Clock, Google, and Google Calendar
+时钟应用,Google 搜索应用,Google 日历应用
-In the Clock app *(above, left)* there’s a FAB; the Google app *(above, middle) *relies primarily on information arranged inside cards; and Google Calendar *(above, right)* creates tiles for events.
+时钟应用(左上)设计的很巧妙,有一个浮动操作按钮;Google 搜索应用(中上)主要靠下部卡片维护信息;Google 日历(右上)给每一个日历时间创建块状条目。
![](https://cdn-images-1.medium.com/max/800/1*Ns0RzUEA6qmbQpILjMJMwA.png)
@@ -205,25 +202,28 @@ In the Clock app *(above, left)* there’s a FAB; the Google app *(above, middle
![](https://cdn-images-1.medium.com/max/800/1*ZWjwDWr61A5r8TprQiHCVw.png)
-Activating the FAB in Clock *(above, left)* brings you to a world clock selection screen, tapping the weather card in the Google app *(above, center)* brings you to a search results page for “weather,” and tapping an event tile in Calendar *(above, right)* takes you to that event’s details.
+在时钟应用里(左上)通过点击浮动按钮,即刻查看世界时钟;在 Google 搜索应用(中上)里点击天气卡片,搜索引擎立马为你展示“天气”的搜索结果;Google 日历(右上)点击块状条目进入事件详情页。
-We also see in these screenshots the different ways in-context navigation can transport the user. In the Clock app we’re down one level from the clock itself, in the Google app we’ve ended up at essentially an augmentation of the main screen, and in Calendar we’ve opened [a full-screen dialog](https://material.io/guidelines/components/dialogs.html#dialogs-full-screen-dialogs).
+我们也能看出来,这些截图展现了上下文导航给用户带来不一样的跳转体验。时钟应用里,用户进入应用的子级页面;Google 搜索应用使用卡片以增强主屏幕,而 Google 日历是点击打开[全屏窗口](https://material.io/guidelines/components/dialogs.html#dialogs-full-screen-dialogs)。
-#### History
+#### 访问记录
-There’s no hard rule for creating history via in-context navigation. Whether history is created relies entirely on what kind of in-context navigation the app uses and where the user is taken. In cases where it’s not clear exactly what kind of history should be created, it’s good to know what the up and back buttons do in general.
+对于上下文导航,并没有对访问记录的硬性规定。访问记录的创建与否完全取决于使用什么形式的上下文导航,还有用户通过导航要去哪里。为了以防万一,在某些情况里应用创建什么类型的历史记录并不明确,设计者最好了解下,在通常情况点击返回键和向上键设置会产生什么操作。
---
-### ↖️ Up, back, and close buttons
+### ↖️ 向上键、返回键、关闭键(Up, back, and close buttons)
![](https://cdn-images-1.medium.com/max/2000/1*VBBwhx66_hRZApzdLzVrJA.png)
-The back, up, and close buttons are all important to navigating an Android UI, but are often misunderstood. The three buttons actually have pretty simple behavior from a UX perspective, so remembering the following rules should help get you out of any perplexing situation.
+返回键,向上键,关闭键这三个按键在安卓用户界面里都非常重要,但却常常被理解错误。实际上,从用户体验的角度,三个按钮都很简单,只要熟记下面的几条规则,保证再也不会陷入困惑。
+
-- **Up **isfound in the app’s toolbar when the user has descended the app’s hierarchy. It navigates back up the hierarchy in chronological order until the user reaches a parent screen. Since the up button doesn’t appear on parent screens, it should never lead out of an app.
-- **Back** is always present in the system nav bar. It navigates backward chronologically, irrespective of app hierarchy, even if the previous chronological screen was inside another app. It also dismisses temporary elements like dialogs, bottom sheets, and overlays.
-- **Close **is typically used to dismiss transient layers of the interface or discard changes in a [full-screen dialog](https://material.io/guidelines/components/dialogs.html#dialogs-full-screen-dialogs). Consider the event detail screen in Google Calendar *(shown below)*. The temporary nature of the detail screen becomes even more clear on larger screens. In Inbox *(below)*, the transition from inbox to message suggests the message is a layer on top of the inbox, so the close button is appropriate. Gmail *(below) *positions the message as a distinct level of the app and uses the up button.
+- **向上键**往往是当用户沿着应用层级结构返回上级菜单时使用到,常出现于应用工具栏。点击向上键,窗口延时间先后顺序后退直到用户到达最顶级父页面。由于顶级父页面无法再往上跳出应用,向上键不应该出现在顶极父页面中。
+
+- **返回键**存在于系统底部导航栏。它的导航作用是沿时间顺序后退,而非应用页面的层级关系,哪怕前一个时间节点是在其它应用中。它还用于关闭临时页面元素,比如对话框,底部表单等层叠面板。
+
+- **关闭键**通常用于关闭界面临时层,或者放弃修改[全屏对话框](https://material.io/guidelines/components/dialogs.html#dialogs-full-screen-dialogs)。例如 Google 日历事件详情页(下图)。全屏日历事件详情页面属于很明显是临时页,设计时使用关闭键。Google 邮箱应用(下图)中,从收件箱到邮件正文的渐进效果显示,邮件正文是收件箱页面的叠加层,因此使用关闭键较合适。 而 Gmail 应用中(下图)邮件正文是作为一个独立层存在于应用中的,因此返回键更合适。
![](https://cdn-images-1.medium.com/max/800/1*zgH-Iq78hKbjiy-WaGl2uQ.png)
@@ -231,13 +231,13 @@ The back, up, and close buttons are all important to navigating an Android UI, b
![](https://cdn-images-1.medium.com/max/800/1*4NyzX3EnqcytgxgfDRuzLg.png)
-Calendar, Inbox, and Gmail
+日历应用,邮箱应用,Gmail 应用
-*📚 Refer specifically to back vs up behavior in the Material Spec *[*here*](https://material.io/guidelines/patterns/navigation.html#navigation-up-back-buttons)*.*
+📚更多关于 后退键 vs 返回键 用户行为探讨,尽在 [Material Design](https://material.io/guidelines/patterns/navigation.html#navigation-up-back-buttons)。
-### 🔄 Combining patterns
+### 🔄 混合模式(Combining patterns)
-Throughout this primer we’ve seen examples of apps that successfully implement each of the various explicit navigation components. Many of these examples also succeed in combining navigation patterns to form a structure that makes sense for users. To wrap up, let’s review a couple of those examples with an eye toward mixing and matching.
+尽管在这份初学者指南中,我们主要分析了使用单个导航组件的成功案例。实际上,这些应用在组合运用多类导航时仍然表现出色,构建了合理的用户行为框架。在文章结尾,我们来看看几个混搭实例。
![](https://cdn-images-1.medium.com/max/800/1*N_M792Hp2LBETAXjYgC3sw.png)
@@ -247,9 +247,9 @@ Throughout this primer we’ve seen examples of apps that successfully implement
Google+
-Maybe the most obvious example is Google+ *(above)*, which mixes all of the patterns we’ve discussed — tabs, a nav drawer, bottom nav, and in-context navigation.
+可能最显而易见的实例便是 Google+(上图),混合上述所有元素 —— 标签页、底部导航、上下文导航。
-To break it down, the bottom nav is the focus in G+. It provides access to four top-level destinations. Tabs augment two of those destinations by segmenting their content into sensible categories. The nav drawer contains other destinations, both primary and secondary, that might be accessed less frequently.
+分离来看,底部导航是 Google+ 的焦点,可以访问四个顶级页面。而标签页将页面结构化增强,通过不同类别拆分内容。而侧边栏囊括了剩余其它按钮,以访问频率区分主次。
![](https://cdn-images-1.medium.com/max/800/1*cZMuV29jlk2r-SKVWOTCTw.png)
@@ -257,11 +257,11 @@ To break it down, the bottom nav is the focus in G+. It provides access to four
![](https://cdn-images-1.medium.com/max/800/1*GcX2vbkwoA8iGm3RwTsJVQ.png)
-Play Store
+Google Play 应用商店
-The Play Store *(above)* primarily uses a nav drawer, frequently uses in-context navigation, and occasionally uses tabs.
+Google Play 应用商店(上图)使用侧边栏当作主要导航,大量使用上下文导航,局部使用标签页导航。
-In the shots above, we see destinations reached through the nav drawer. The drawer is still accessible on these screens because they’re all primary destinations. Just below the toolbar we see chips to navigate to filtered content selections, an example of in-context navigation. In app charts, tabs are used to sort the entire charted library into specific segments.
+上图中,我们看到所有从侧边栏进入的页面中,打开侧边栏的图标始终是可点按的,因为这些页面都是最顶级父页面。在顶端工具栏下方,小椭圆片帮助细分页面内容,是典型的上下文导航。在应用下载统计页面,标签页将排列好的应用分门别类。
![](https://cdn-images-1.medium.com/max/800/1*c2rK-Zvz7W7aFThPSFqrJg.png)
@@ -269,17 +269,15 @@ In the shots above, we see destinations reached through the nav drawer. The draw
![](https://cdn-images-1.medium.com/max/800/1*ZWjwDWr61A5r8TprQiHCVw.png)
-Google Calendar
-
-Google Calendar *(above)* uses a nav drawer and in-context navigation, and uses both in really interesting ways.
+Google 日历应用
-The drawer in Calendar is non-standard, used mostly to augment the calendar. The calendar itself is controlled by an expanding toolbar panel, and colorful tiles lead users to event details.
+Google 日历应用(上图)巧妙得使用了侧边栏导航和上下文导航。此处侧边栏是一个非标准的日历增强面板。日历本身由可扩展的工具栏控制,不同颜色的色块表示用户的日历事项,点击进入详情即可查看详细日程。
-📚 *Read more about combining navigation patterns *[*here*](https://material.io/guidelines/patterns/navigation.html#navigation-patterns)*.*
+📚 更多混合导航实例[参考此处](https://material.io/guidelines/patterns/navigation.html#navigation-patterns)。
-### 🤔 Have more questions?
+### 🤔 更多问题?
-Navigation is a complex topic. Hopefully this primer provides a good foundation for understanding common navigation principles on Android. If you still have questions, leave a response or catch up on our first [#AskMaterial](https://twitter.com/search?q=%23AskMaterial) session with the [Material Design](http://Material.io) & Design Relations teams on Twitter [here](https://twitter.com/i/moments/884845596145836032)!
+导航本身是一个很复杂的话题,希望这篇导航初识能帮助到读者,对安卓导航的设计原理有一个较好的理解。如果你还有其它问题,欢迎留言或在推特 [#AskMaterial](https://twitter.com/search?q=%23AskMaterial) 话题下与 [Material Design](http://Material.io) 进行互动,当然还有我们团队账号,[猛戳这里](https://twitter.com/i/moments/884845596145836032)关注!
---
diff --git a/TODO/artificial-intelligence-in-ux-design.md b/TODO/artificial-intelligence-in-ux-design.md
index 22f5cf426cf..8b2ce608b77 100644
--- a/TODO/artificial-intelligence-in-ux-design.md
+++ b/TODO/artificial-intelligence-in-ux-design.md
@@ -3,109 +3,107 @@
> * 原文作者:[Mukund Krishna](https://www.sitepoint.com/author/mukund-krishna/)
> * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
> * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO/artificial-intelligence-in-ux-design.md](https://github.com/xitu/gold-miner/blob/master/TODO/artificial-intelligence-in-ux-design.md)
- > * 译者:
- > * 校对者:
+ > * 译者:[Changkun Ou](https://github.com/changkun/)
+ > * 校对者:[Tina92](https://github.com/Tina92)、[shawnchenxmu](https://github.com/shawnchenxmu)
- # Can AI Solve Your UX Design Problems?
+# AI 能解决你的 UX 设计问题吗?
![AI Powered UX](https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2017/07/1501567920icDqSo2.jpg)
-One of Mark Zuckerberg’s key New Year resolutions for 2016 was to build his own “[simple AI bot](http://www.vanityfair.com/news/2016/12/mark-zuckerberg-spent-100-hours-building-his-own-robot-butler)” that could help him with the household tasks. Remember the image of the butler, Jarvis from Iron Man? That’s a classic Hollywood example of how AI works.
+马克·扎克伯格在 2016 年的重要新年决定之一就是建立属于自己的「[简单 AI 机器人](http://www.vanityfair.com/news/2016/12/mark-zuckerberg-spent-100-hours-building-his-own-robot-butler)」,来帮助他解决家务。还记得钢铁侠的管家 Jarvis 吗?这就是一个关于AI如何发挥作用的好莱坞经典范例。
-But, what precisely is Artificial Intelligence and how can it solve the most common UX problems today?
+那么,人工智能(artificial intelligence, AI)究竟是什么?它又如何能解决当今最常见的UX问题呢
![Tony Stark using Jarvis](https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2017/07/150156788652646.jpg)
-Tony Stark using Jarvis.
+Tony Stark 在使用 Jarvis。
-Artificial Intelligence (or AI) is an advanced human-like computerized system that has the ability to intelligently manage the activities and systems which humans usually do manually. While bots like Apple’s Siri and Amazon’s Echo are programmed to take on our most mundane tasks, bots like Google’s *Deep Dream* are inherently creative, helping users in problem-solving, thereby improving their experience.
+人工智能(或者说 AI)是一种先进的类人计算机系统,能够聪明的管理通常需要人类手动执行的活动和系统。当苹果的 Siri 和亚马逊的 Echo 这样的机器人还在处理我们最平凡的任务时,像 Google 的 **Deep Dream** 这样的机器人天生就具有创造性,并能帮助用户解决问题,从而改善他们的体验。
-AI is finding its application across multiple real-time scenarios:
+AI 正在多个实时场景中得到应用:
-- **Handle data explosion** – With the advent of smartphones and mobile devices, comes the explosion of data. As the amount of data grows, it is pertinent to have an AI system to analyze, process, organize, and interpret the data.
-- **The ability to decipher our intent** – Netflix can predict from your behavior what kind of TV show or movie will keep you glued to your sofa. Imagine if your AI system can adjust your car’s temperature and turn off the lights when you take your car out of the garage.
-- **Improving the customer experience** – AI can dig deep into details which human eye could probably miss and help you focus on the right data. For instance, [RightClick.io](https://rightclick.io/#/) is a chatbot that helps you create websites by involving you in a conversation. Even if you try to divert it with unrelated questions, this AI device will put you back to the actual job of website creation.
+- **处理数据爆炸**:随着智能手机和移动设备的出现,数据正爆炸式增长。随着数据量的增长,有一个 AI 系统来分析、处理、组织和解释数据。
+- **辨别我们的意图**:Netflix 可以从你的行为中预测什么样的电视节目或电影将让你待在沙发上。想象一下,你的 AI 系统可以调整汽车的温度,在你从车库出来时自动把灯关掉。
+- **改善客户体验**:AI 可深入挖掘人眼可能错过的细节,从而帮助你专注于正确的数据。 比如,[RightClick.io](https://rightclick.io/#/) 是一个聊天机器人,可以让你通过与其对话来创建网站。即使你试着对其用不相关的问题转移话题,这个 AI 设备还是会引导你返回网站创建的实际工作中去。
![RightClick.io](https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2017/07/15015679069ApLLkv.jpg)
RightClick.io
-Artificial Intelligence is transforming the way we create user experiences. While movies like *Terminator* have given us a dystopian idea of AI, the reality is totally distinct. AI is a powerful technology that positively influences consumer behavior and enables businesses to provide a great user experience.
+人工智能正在改变我们创造用户体验的方式。 虽然**终结者**的电影给了我们一个 AI 的反乌托邦的想法,但现实是完全不同的。AI 是一种强大的技术,可以积极地影响消费者行为,并使企业能够提供出色的用户体验。
-## Understanding the role of AI in UX
+## 理解 AI 在 UX 中的作用
-To begin with, let us look at a few real-life scenarios of how AI is impacting UX today. Context-intelligent chatbots can delight your customer with prompt and timely advice or workarounds. Navigational apps could direct you to your destination effortlessly. With a few taps/clicks, you will receive your favorite meal at your doorstep.
+首先,让我们来看看如今现实生活中一些 AI 如何影响 UX 的场景。 能够感知上下文的聊天机器人可以通过提供一些及时的建议或解决方法从而取悦你的客户。导航应用程序可以毫不费力地将你引导到目的地。简单点几下,你就可以在家门口收到你最喜爱的餐点。
-### How does this work?
+### 这是怎么工作的?
-The very thought of developing AI came from the idea of science fictions, that described of machines that could talk, think or feel. AI is a combination of several nascent technologies- machine learning, deep learning, chat bots, augmented reality, virtual reality, robots- to name a few.
+开发 AI 的想法来自科幻小说,这些小说描述了可以说话、思考或感受的机器。AI 是多种新兴技术的组合,比如:机器学习、深度学习、聊天机器人、增强现实、虚拟现实和机器人等等。
-AI covers anything to do with infusing intelligence into machines/ devices so that they emulate the unique reasoning power of human beings. All of these can be accomplished by using algorithms that are capable of discovering human behavior patterns and generate insights from the data received and stored by the devices. Artificial Intelligence enabled devices or machines are programmed carefully so that they support in future decision-making.
+AI 涵盖了将智能注入到机器或设备的任何事情,使它们能模仿人类独特的推理能力。 所有这些,都可以通过使用能够发现人类行为模式、并从设备接收和存储的数据产生见解的算法来实现。应该细心的编写启用人工智能的设备或者机器,以便它们能在将来的决策中起到帮助。
-All this might sound simple, but these are interactions powered by the fast growing AI technology. In fact, when it comes to humanizing customer experience, AI will become an indispensable tool in a UX designer’s kit. However, besides architecting human-like conversations and actions, there is a lot more AI can do in the digital realm for generating outstanding UX.
+这一切可能听起来很简单,但这些交互都是由快速增长的 AI 技术提供的。事实上,当涉及人性化客户体验时,AI 将成为 UX 设计师套件中不可或缺的工具。然而,除了构建类似人类的对话和行动之外,AI 还能在数字领域中大显身手,创造出优秀的 UX。
-## 1. A platform to collaborate
+## 1. 一个面向协助的平台
-AI is going mainstream with bots and robots fostering human-like interactions with the power of cognitive intelligence. However, robots cannot replace humans completely. Instead, AI nurtures fruitful collaboration in the domain of UX.
+AI 正在伴随着机器人走向主流,而机器人则通过认知智能的力量培育出了像人一样的互动。然而,机器人不能完全取代人类。相反,AI 在 UX 的领域起到了卓有成效的协助作用。
-For example, [TheGrid.io](https://thegrid.io/) is an algorithm-driven design platform that lets you build highly impressive and optimized websites. The platform is built from the ground up around the concept of continuous A/B testing and refinement layouts. Designers can sift through the multiple options provided by such AI-driven tools and select what works for them.
+例如,[TheGrid.io](https://thegrid.io/) 是一个算法驱动的设计平台,可让您构建高度令人印象深刻和优化的网站。该平台是围绕连续 A/B 测试和细化布局的概念构建的。设计师可以筛选由这些 AI 驱动的工具提供的多个选项,并选择适合它们的功能。
![TheGrid.io](https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2017/07/1501567868cAk9mgD-e1501568470475.jpg)
-Like any good assistant, it usually does best when offering fresh options rather than making critical decisions. When designers have an intelligent platform to help them choose a template and verify the same by applying algorithms, it helps them to make more creative decisions.
+像任何好的助手一样,它通常在提供的新选项中做出最好的决定,而不是作出关键的决定。当设计师有一个智能平台帮助他们选择一个模板并通过应用算法来验证模板时,它可以帮助他们做出更多的创造性决策。
-## 2. Journey mapping with AI
+## 2. 用 AI 制定旅程
-Companies like [ReFUEL4](https://www.refuel4.com/) use the power of predictive analytics to understand the online journey of users and map them into segments based on their behavior. The most powerful UX is the one that understands and even predicts user interests and actions.
+像 [ReFUEL4](https://www.refuel4.com/) 这样的公司利用预测分析的力量来了解用户的线上行为,并根据他们的行为对其进行进一步的细化。最强大的 UX 是一个了解甚至能预测用户兴趣和行动的 UX。
![Refuel4](https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2017/07/1501567882ezgif.com-optimize-34.gif)
-Once the designer is able to map a user’s journey, he can understand the paths a user is expected to travel in course of their digital interactions. AI-powered journey mapping allows you to create simple, engaging, and profitable UI.
+一旦设计师能够制定用户的行程,那么他就可以理解用户在交互过程中所期望路径。AI 驱动的行程制定可让你创建简单、有吸引力和有利可图的用户界面。
-## 3. Taking over repetitive, lower-value creative tasks
+## 3. 接管重复、低价值的创造性任务
-In a multi-device world, designers often have to come up with many graphics and variations of content to cater to multiple forms of a campaign. This can be quite mind-numbing and demands a lot of time.
+在多设备世界里,设计师经常必须提出许多图形和各种各样的内容,以满足各种形式的活动。 这可能很麻烦,要花很多时间。
![Netflix layout generation.](https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2017/07/150156789352650.jpg)
-Netflix layout generation.
+Netflix 的布局生成。
-That’s why platforms like Netflix hand over these tedious tasks to algorithms. Human designers can map out the ‘rules’ for how a layout should work and then provide the system with a library of raw graphic elements to work with. Netflix’s system is then capable of combining the rules with the image assets to create original movie poster and banner units.
+这就是像 Netflix 这样的平台将这些繁琐的任务交给算法的原因。人类设计师可以绘制布局应如何工作的「规则」,然后为系统提供一个原始图形元素库来处理它们。Netflix 的系统能够将规则与图像素材相结合,以创建原始电影海报和横幅单元。
-When AI handles such tasks, designers can focus more on understanding the user journey and refining these rules. It’s not unlike a scenario where a senior designer is directing a team of junior designers. Each benefits from the other.
+当 AI 处理这些任务时,设计人员可以更多地关注理解用户之旅并完善这些规则。 这与高级设计师正在指导一支初级设计师团队没什么不同的,双赢。
-AI technologies like machine learning empowers digital marketers for granular targeting. For example, IBM’s Watson facilitates psychological user segmentation so that marketers can provide the right content to the right audience at the right time.
+像机器学习这样的 AI 技术可以使数字营销人员进行细粒度定位。例如,IBM 的 Watson 促进心理用户细分,使营销人员能够在正确的时间向正确的受众提供正确的内容。
-### Here is how Watson AI works:
+### Watson AI 的工作原理:
-Watson breaks down questions into different keywords or ‘sentences fragments’ in order to discover statistically related phrases. It not only creates a new algorithm for this operation but executes hundreds of analysis algorithms simultaneously.
+为了发现统计学上相关的短语,Watson 将问题分解成不同的关键字或「句子片段」。它不仅为此操作创建了一种新算法,而且同时执行了数百种分析算法。
-If more algorithms come up with the same answer independently, then Watson is more likely to be correct. Once Watson gets multiple solutions in hand, it verifies the potential workarounds against the database to ascertain if any of them makes sense.
+如果越多的算法独立出现相同的答案,那么 Watson 就越有可能是正确的。一旦 Watson 获得了多个解决方案,它将验证数据库的潜在解决方法,从而确定其中的任何一个是否有意义。
-## How do you mold AI for a better UX?
+## 你会怎样塑造 AI 来获得更好的 UX ?
-AI systems have the ability to analyze large amounts of data quickly and also learn and adjust their behavior in real-time. AI systems can infer from the context and you need to supply them with additional information in the form of business rules, questions, metadata and similar other conditions.
+AI 系统能够快速分析大量数据,并实时学习和调整其行为。 AI 系统可以从上下文中推断,你则需要给它们提供额外的关于业务规则、问题、元数据和类似的类似的其他条件的信息。
-As you work through each design phase to build a great user experience, you can constantly refine the questions that you ask your AI system. This will change the way it analyzes data.
+当你通过每个设计阶段建立良好的用户体验时,你可以不断完善您询问 AI 系统的问题。这将改变分析数据的方式。
-For example, if you are managing a health insurance website, ask plain questions like:
+例如,如果您正在管理健康保险网站,可以问如下问题:
-- How many people between the age 40-60 use your application?
-- How many expecting moms access the system?
+- 40 至 60岁之间有多少人使用你的应用程序?
+- 有多少准妈妈访问系统?
-The system takes your questions, analyzes the data and learns to throw up the best possible answers. Each time you feed a new data or criterion, the system conditions itself using AI technology to enhance your user experience.
+系统会收到你的问题,分析数据并学习给出最佳答案。每当你提供新的数据或标准时,系统会使用人工智能来改善自身的用户体验。
-## The beauty of molding AI is:
+## 塑造 AI 的艺术:
-- You can ask general to specific questions to your AI system. The system attends your questions, takes the data, and self-learns.
-- AI can analyze all the queries made on your search engine, collect more user analytics, identify trends, and generate richer findings.
-- Refine the quality of search results with data – AI can come up with better predictive search terms, provide recommendations, cross-topic referrals (similar to what Amazon offers), and bring more relevant content on top.
-- Above all, AI learns from everyone who has visited your application till now and serves your users with needed content. This makes way for a richer user experience.
-- Information Architecture with AI-AI analyzes both your internal and external data and helps you build information structure for your content management system and a navigation structure for your end users.
+- 你可以向你的 AI 系统询问从一般到特殊问题。系统则处理问题、拿到数据再自我学习。
+- AI 可以分析搜索引擎上的所有查询,收集更多的用户分析结果、识别趋势,并生成更丰富的结果。
+- 使用数据优化搜索结果的质量:AI 可以预测搜索条件、提供建议、跨主题推荐(类似于 Amazon 提供的),从而给出更多相关的内容。
+- 最重要的是,AI 能学习到目前为止所有访问过你应用的用户,并为你的用户提供了所需的内容。这产生了更丰富的用户体验。
+- 具有 AI 的信息架构:AI 分析你的内部和外部数据,并帮助你构建内容管理系统的信息结构和最终用户的导航结构。
-User experience is not necessarily about leveraging data insights, it’s about intelligence too. Artificial intelligence connects the dots by infusing intelligence into the disparate sources of data.
+用户体验不一定是利用对数据的见解,它也是关于智能的。人工智能通过向不同数据源注入智能,从而连接了各类独立的节点。
-Though AI technologies like machine learning, chatbots, VR, robots, AR and other systems are gaining momentum, the growth seems to be gradual. AI, when combined with UX becomes the icon of the future technology. Merging AI with UX is a formula that should lead us to enhanced content findability and reachability.
+虽然像机器学习、聊天机器人、VR、机器人、AR 等系统的 AI 技术正呈增长势头,但增长似乎是渐进的。 AI 与 UX 结合成为未来技术的标志。将 AI 与 UX 合并是一个公式,一个将引领我们增强内容的可查找性和可获取性的公式。
-
- ---
+---
> [掘金翻译计划](https://github.com/xitu/gold-miner) 是一个翻译优质互联网技术文章的社区,文章来源为 [掘金](https://juejin.im) 上的英文分享文章。内容覆盖 [Android](https://github.com/xitu/gold-miner#android)、[iOS](https://github.com/xitu/gold-miner#ios)、[React](https://github.com/xitu/gold-miner#react)、[前端](https://github.com/xitu/gold-miner#前端)、[后端](https://github.com/xitu/gold-miner#后端)、[产品](https://github.com/xitu/gold-miner#产品)、[设计](https://github.com/xitu/gold-miner#设计) 等领域,想要查看更多优质译文请持续关注 [掘金翻译计划](https://github.com/xitu/gold-miner)、[官方微博](http://weibo.com/juejinfanyi)、[知乎专栏](https://zhuanlan.zhihu.com/juejinfanyi)。
-
\ No newline at end of file
diff --git a/TODO/building-an-api-gateway-using-nodejs.md b/TODO/building-an-api-gateway-using-nodejs.md
index b4f04eb3e07..c5225c6b79d 100644
--- a/TODO/building-an-api-gateway-using-nodejs.md
+++ b/TODO/building-an-api-gateway-using-nodejs.md
@@ -3,157 +3,167 @@
> * 原文作者:[Péter Márton](https://twitter.com/slashdotpeter)
> * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
> * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO/building-an-api-gateway-using-nodejs.md](https://github.com/xitu/gold-miner/blob/master/TODO/building-an-api-gateway-using-nodejs.md)
- > * 译者:
- > * 校对者:
+ > * 译者:[MuYunyun](https://github.com/MuYunyun)
+ > * 校对者:[jasonxia23](https://github.com/jasonxia23)、[CACppuccino](https://github.com/CACppuccino)
- # Building an API Gateway using Node.js
+ # 使用 Node.js 搭建一个 API 网关
- Services in a microservices architecture share some common requirements regarding authentication and transportation when they need to be accessible by external clients. API Gateway s provide a **shared layer** to handle differences between service protocols and fulfills the requirements of specific clients like desktop browsers, mobile devices, and legacy systems.
+ 外部客户端访问微服务架构中的服务时,服务端会对认证和传输有一些常见的要求。API 网关提供**共享层**来处理服务协议之间的差异,并满足特定客户端(如桌面浏览器、移动设备和老系统)的要求。
-# Microservices and consumers
+# 微服务和消费者
-Microservices are a service oriented architecture where teams can design, develop and ship their applications independently. It allows **technology diversity** on various levels of the system, where teams can benefit from using the best language, database, protocol, and transportation layer for the given technical challenge. For example, one team can use JSON over HTTP REST while the other team can use gRPC over HTTP/2 or a messaging broker like RabbitMQ.
+微服务是面向服务的架构,团队可以独立设计、开发和发布应用程序。它允许在系统各个层面上的**技术多样性**,团队可以在给定的技术难题中使用最佳语言、数据库、协议和传输层,从而受益。例如,一个团队可以使用 HTTP REST 上的 JSON,而另一个团队可以使用 HTTP/2 上的 gRPC 或 RabbitMQ 等消息代理。
-Using different data serialization and protocols can be powerful in certain situations, but **clients** that want to consume our product may **have different requirements**. The problem can also occur in systems with homogeneous technology stack as consumers can vary from a desktop browser through mobile devices and gaming consoles to legacy systems. One client may expect XML format while the other one wants JSON. In many cases, you need to support both.
+在某些情况下使用不同的数据序列化和协议可能是强大的,但要使用我们的产品的**客户**可能**有不同的需求**。该问题也可能发生在具有同质技术栈的系统中,因为客户可以从桌面浏览器通过移动设备和游戏机到遗留系统。一个客户可能期望 XML 格式,而另一个客户可能希望 JSON 。在许多情况下,您需要同时支持它们。
-Another challenge that you can face when clients want to consume your microservices comes from generic **shared logic** like authentication, as you don't want to re-implement the same thing in all of your services.
+当客户想要使用您的微服务时,您可以面对的另一个挑战来自于通用的**共享逻辑**(如身份验证),因为您不想在所有服务中重新实现相同的事情。
-To summarize: we don't want to implement our internal services in our microservices architecture in a way to support multiple clients and re-implement the same logic all over. This is where the **API Gateway** comes into the picture and provides a **shared layer** to handle differences between service protocols and fulfills the requirements of specific clients.
+总结:我们不想在我们的微服务架构中实现我们的内部服务,以支持多个客户端并可以重复使用相同的逻辑。这就是 **API 网关**出现的原因,其作为**共享层**来处理服务协议之间的差异并满足特定客户端的要求。
-# What is an API Gateway?
+# 什么是 API 网关?
-API Gateway is a type of service in a microservices architecture which provides a shared layer and API for clients to communicate with internal services. The API Gateway can **route requests**, transform protocols, **aggregate data** and **implement shared logic** like authentication and rate-limiters.
+API 网关是微服务架构中的一种服务,它为客户端提供共享层和 API,以便与内部服务进行通信。API 网关可以进行**路由请求**、转换协议、**聚合数据**以及**实现共享逻辑**,如认证和速率限制器。
-You can think about API Gateway as the **entry point** to our microservices world.
+您可以将 API 网关视为我们的微服务世界的**入口点**。
-Our system can have one or multiple API Gateways, depending on the clients' requirements. For example, we can have a separate gateway for desktop browsers, mobile applications and public API(s) as well.
+我们的系统可以有一个或多个 API 网关,具体取决于客户的需求。例如,我们可以为桌面浏览器、移动应用程序和公共 API 提供单独的网关。
-![API Gateway](https://blog-assets.risingstack.com/2017/07/api-gateway-1.png)*API Gateway as an entry point to microservices*
+![API Gateway](https://blog-assets.risingstack.com/2017/07/api-gateway-1.png)
-## Node.js API Gateway for frontend teams
+**API 网关作为微服务的切入点**
-As API Gateway provides functionality for client applications like browsers - it can be implemented and managed by the team who is responsible for the frontend application.
+## Node.js 用于前端团队的 API 网关
-It also means that language the API Gateway is implemented in language should be chosen by the team who is responsible for the particular client. As JavaScript is the primary language to develop applications for the browser, Node.js can be an excellent choice to implement an API Gateway even if your microservices architecture is developed in a different language.
+由于 API 网关为客户端应用程序(如浏览器)提供了功能,它可以由负责开发前端应用程序的团队实施和管理。
-Netflix successfully uses Node.js API Gateways with their Java backend to support a broad range of clients - to learn more about their approach read [The "Paved Road" PaaS for Microservices at Netflix](https://www.infoq.com/news/2017/06/paved-paas-netflix) article.
+这也意味着用哪种语言实现 API Gateway 应由负责特定客户的团队选择。由于 JavaScript 是开发浏览器应用程序的主要语言,即使您的微服务架构以不同的语言开发,Node.js 也可以成为实现 API 网关的绝佳选择。
-![](https://image.slidesharecdn.com/qconpaved-170718200756/95/paved-paas-to-microservices-7-638.jpg?cb=1500408507)*Netflix's approach to handle different clients, [source](https://www.slideshare.net/yunongx/paved-paas-to-microservices)*
+Netflix 成功地使用 Node.js API 网关及其 Java 后端来支持广泛的客户端 - 了解更多关于它们的方法阅读 [The "Paved Road" PaaS for Microservices at Netflix](https://www.infoq.com/news/2017/06/paved-paas-netflix) 这篇文章
+![](https://image.slidesharecdn.com/qconpaved-170718200756/95/paved-paas-to-microservices-7-638.jpg?cb=1500408507)
-# API Gateway functionalities
+**Netflix 处理不同客户端的方法, [资源](https://www.slideshare.net/yunongx/paved-paas-to-microservices)**
-We discussed earlier that you can put generic shared logic into your API Gateway, this section will introduce the most common gateway responsibilities.
+# API 网关功能
-## Routing and versioning
+我们之前讨论过,可以将通用共享逻辑放入您的 API 网关,本节将介绍最常见的网关职责。
-We defined the API Gateway as the entry point to your microservices. In your gateway service, you can **route requests** from a client to specific services. You can even **handle versioning** during routing or change the backend interface while the publicly exposed interface can remain the same. You can also define new endpoints in your API gateway that cooperates with multiple services.
+## 路由和版本控制
-![API Gateway - Entry point](https://blog-assets.risingstack.com/2017/07/api-gateway-entrypoint-1.png)*API Gateway as microservices entry point*
+我们将 API 网关定义为您的微服务的入口点。在您的网关服务中,您可以指定从客户端路由到特定服务的**路由请求**。您甚至可以通过路由**处理版本**或更改后端接口,而公开的接口可以保持不变。您还可以在您的 API 网关中定义与多个服务配合的新端点。
-### Evolutionary design
+![API Gateway - Entry point](https://blog-assets.risingstack.com/2017/07/api-gateway-entrypoint-1.png)
-The API Gateway approach can also help you to **break down your monolith** application. In most of the cases rewriting your system from scratch as a microservices is not a good idea and also not possible as we need to ship features for the business during the transition.
+**API 网关作为微服务入口点**
-In this case, we can put a proxy or an API Gateway in front of our monolith application and implement **new functionalities as microservices** and route new endpoints to the new services while we can serve old endpoints via monolith. Later we can also break down the monolith with moving existing functionalities into new services.
+### 网关设计的升级
-With evolutionary design, we can have a **smooth transition** from monolith architecture to microservices.
+API 网关方法也可以帮助您**分解您的整体**应用程序。在大多数情况下,在微服务端重构一个系统不是一个好主意也是不可能的,因为我们需要在重构期间为业务发送新的以及原有的功能。
-![API Gateway - Evolutionary design](https://blog-assets.risingstack.com/2017/07/api-gateway-evolutinary-design.png)*Evolutionary design with API Gateway*
+在这种情况下,我们可以将代理或 API 网关置于我们的整体应用程序之前,将**新功能作为微服务**实现,并将新端点路由到新服务,同时通过原有的路由服务旧端点。这样以后,我们也可以通过将原有功能转变为新服务来分解整体。
-## Authentication
+随着网关设计的升级,我们可以实现整体架构到微型服务的**平滑过渡**
-Most of the microservices infrastructure need to handle authentication. Putting **shared logic** like authentication to the API Gateway can help you to **keep your services small** and **domain focused**.
+![API Gateway - Evolutionary design](https://blog-assets.risingstack.com/2017/07/api-gateway-evolutinary-design.png)
-In a microservices architecture, you can keep your services protected in a DMZ *(demilitarized zone)* via network configurations and **expose** them to clients **via the API Gateway**. This gateway can also handle more than one authentication method. For example, you can support both *cookie* and *token* based authentication.
+**API 网关设计的升级**
-![API Gateway - Authentication](https://blog-assets.risingstack.com/2017/07/api-gateway-auth-1.png)*API Gateway with Authentication*
+## 认证
-## Data aggregation
+大多数微服务基础设施需要进行身份验证。将**共享逻辑**(如身份验证)添加到 API 网关可以帮助您**保持您的服务的体积变小**以及**可以集中管理域**。
-In a microservices architecture, it can happen that the client needs data in a different aggregation level, like **denormalizing data** entities that take place in various microservices. In this case, we can use our API Gateway to **resolve** these **dependencies** and collect data from multiple services.
+在微服务架构中,您可以通过网络配置将您的服务保护在 DMZ **(保护区)**中,并通过 API 网关向客户**公开**。该网关还可以处理多个身份验证方法。例如,您可以同时支持基于 **cookie** 和 **token** 的身份验证。
-In the following image you can see how the API Gateway merges and returns user and credit information as one piece of data to the client. Note, that these are owned and managed by different microservices.
+![API Gateway - Authentication](https://blog-assets.risingstack.com/2017/07/api-gateway-auth-1.png)
+
+**具有认证功能的 API 网关**
+
+## 数据汇总
+
+在微服务架构中,可能客户端所需要的数据的聚合级别不同,比如对在各种微服务中产生的**非规范化数据**实体。在这种情况下,我们可以使用我们的 API 网关来**解决**这些**依赖关系**并从多个服务收集数据。
+
+在下图中,您可以看到 API 网关如何将用户和信用信息作为一个数据返回给客户端。请注意,这些数据由不同的微服务所拥有和管理。
![API Gateway - Data aggregation](https://blog-assets.risingstack.com/2017/07/api-gateway-aggregation-1.png)
-## Serialization format transformation
+## 序列化格式转换
-It can happen that we need to support clients with **different data serialization format** requirements.
+我们需要支持客户端**不同的数据序列化格式**这样子的需求可能会发生。
-Imagine a situation where our microservices uses JSON, but one of our customers can only consume XML APIs. In this case, we can put the JSON to XML conversion into the API Gateway instead of implementing it in all of the microservices.
+想象一下我们的微服务使用 JSON 的情况,但我们的客户只能使用 XML APIs。在这种情况下,我们可以在 API 网关中把 JSON 转换为 XML,而不是在所有的微服务器中分别进行实现。
![API Gateway - Data serialization format transformation](https://blog-assets.risingstack.com/2017/07/api-gateway-format-2.png)
-## Protocol transformation
+## 协议转换
-Microservices architecture allows **polyglot protocol transportation** to gain the benefit of different technologies. However most of the client support only one protocol. In this case, we need to transform service protocols for the clients.
+微服务架构允许**多通道协议传输**从而获取多种技术的优势。然而,大多数客户端只支持一个协议。在这种情况下,我们需要转换客户端的服务协议。
-An API Gateway can also handle protocol transformation between client and microservices.
+API 网关还可以处理客户端和微服务器之间的协议转换。
-In the next image, you can see how the client expects all of the communication through HTTP REST while our internal microservices uses gRPC and GraphQL.
+在下一张图片中,您可以看到客户端希望通过 HTTP REST 进行的所有通信,而内部的微服务使用 gRPC 和 GraphQL 。
![API Gateway - Protocol transformation](https://blog-assets.risingstack.com/2017/07/api-gateway-protocol.png)
-## Rate-limiting and caching
+## 速率限制和缓存
-In the previous examples, you could see that we can put generic shared logic like authentication into the API Gateway. Other than authentication you can also implement rate-limiting, caching and various reliability features in you API Gateway.
+在前面的例子中,您可以看到我们可以把通用的共享逻辑(如身份验证)放在 API 网关中。除了身份验证之外,您还可以在 API 网关中实现速率限制,缓存以及各种可靠性功能。
-## Overambitious API gateways
+## 超负荷的 API 网关
-While implementing your API Gateway, you should avoid putting non-generic logic - like domain specific data transformation - to your gateway.
+在实现您的 API 网关时,您应避免将非通用逻辑(如特定数据转换)放入您的网关。
-Services should always have **full ownership over** their **data domain**. Building an overambitious API Gateway **takes the control from service teams** that goes against the philosophy of microservices.
+服务应该始终拥有他们的**数据域**的**全部所有权**。构建一个超负荷的 API 网关,让**微服务团队**来控制,这违背了微服务的理念。
-This is why you should be careful with data aggregations in your API Gateway - it can be powerful but can also lead to domain specific data transformation or rule processing logic that you should avoid.
+这就是为什么你应该关注你的 API 网关中的数据聚合 - 你应该避免它有大量逻辑甚至可以包含特定的数据转换或规则处理逻辑。
-Always define **clear responsibilities** for your API Gateway and only include generic shared logic in it.
+始终为您的 API 网关定义**明确的责任**,并且只包括其中的通用共享逻辑。
-# Node.js API Gateways
+# Node.js API 网关
-While you want to do simple things in your API Gateway like routing requests to specific services you can **use a reverse proxy** like nginx. But at some point, you may need to implement logic that's not supported in general proxies. In this case, you can **implement your own** API Gateway in Node.js.
+当您希望在 API 网关中执行简单的操作,比如将请求路由到特定服务,您可以使用像 nginx 这样的**反向代理**。但在某些时候,您可能需要实现一般代理不支持的逻辑。在这种情况下,您可以在 Node.js 中**实现自己的** API 网关。
-In Node.js you can use the [http-proxy](https://www.npmjs.com/package/http-proxy) package to simply proxy requests to a particular service or you can use the more feature rich [express-gateway](http://www.express-gateway.io/) to create API gateways.
+在 Node.js 中,您可以使用 [http-proxy](https://www.npmjs.com/package/http-proxy) 软件包简单地代理对特定服务的请求,也可以使用更多丰富功能的 [express-gateway](http://www.express-gateway.io/) 来创建 API 网关。
-In our first API Gateway example, we authenticate the request before we proxy it to the *user* service.
+在我们的第一个 API 网关示例中,我们在将代码委托给 **user** 服务之前验证请求。
+```js
const express = require('express')
const httpProxy = require('express-http-proxy')
const app = express()
const userServiceProxy = httpProxy('https://user-service')
- // Authentication
+ // 身份认证
app.use((req, res, next) => {
- // TODO: my authentication logic
+ // TODO: 身份认证逻辑
next()
})
- // Proxy request
+ // 代理请求
app.get('/users/:userId', (req, res, next) => {
userServiceProxy(req, res, next)
})
+```
+另一种示例可能是在您的 API 网关中发出新的请求,并将响应返回给客户端:
-Another approach can be when you make a new request in your API Gateway, and you return the response to the client:
-
+```js
const express = require('express')
const request = require('request-promise-native')
const app = express()
- // Resolve: GET /users/me
+ // 解决: GET /users/me
app.get('/users/me', async (req, res) => {
const userId = req.session.userId
- const uri = `https://user-service/users/${userId}`const user = await request(uri)
+ const uri = `https://user-service/users/${userId}`
+ const user = await request(uri)
res.json(user)
})
+```
+## Node.js API 网关总结
-## Node.js API Gateways Summarized
-
-API Gateway provides a shared layer to serve client requirements with microservices architecture. It helps to keep your services small and domain focused. You can put different generic logic to your API Gateway, but you should avoid overambitious API Gateways as these take the control from service teams.
-
+API 网关提供了一个共享层,以通过微服务架构来满足客户需求。它有助于保持您的服务小而专注。您可以将不同的通用逻辑放入您的 API 网关,但是您应该避免 API 网关的过度使用,因为很多逻辑可以从服务团队中获得控制。
---
> [掘金翻译计划](https://github.com/xitu/gold-miner) 是一个翻译优质互联网技术文章的社区,文章来源为 [掘金](https://juejin.im) 上的英文分享文章。内容覆盖 [Android](https://github.com/xitu/gold-miner#android)、[iOS](https://github.com/xitu/gold-miner#ios)、[React](https://github.com/xitu/gold-miner#react)、[前端](https://github.com/xitu/gold-miner#前端)、[后端](https://github.com/xitu/gold-miner#后端)、[产品](https://github.com/xitu/gold-miner#产品)、[设计](https://github.com/xitu/gold-miner#设计) 等领域,想要查看更多优质译文请持续关注 [掘金翻译计划](https://github.com/xitu/gold-miner)、[官方微博](http://weibo.com/juejinfanyi)、[知乎专栏](https://zhuanlan.zhihu.com/juejinfanyi)。
-
\ No newline at end of file
diff --git a/TODO/contextual-chat-bots-with-tensorflow.md b/TODO/contextual-chat-bots-with-tensorflow.md
index a24c5e3ea95..c87786082c0 100644
--- a/TODO/contextual-chat-bots-with-tensorflow.md
+++ b/TODO/contextual-chat-bots-with-tensorflow.md
@@ -3,99 +3,98 @@
> * 原文作者:[gk_](https://chatbotsmagazine.com/@gk_)
> * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
> * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO/contextual-chat-bots-with-tensorflow.md](https://github.com/xitu/gold-miner/blob/master/TODO/contextual-chat-bots-with-tensorflow.md)
-> * 译者:
-> * 校对者:
+> * 译者:[edvardhua](https://github.com/edvardHua)
+> * 校对者:[lileizhenshuai](https://github.com/lileizhenshuai), [jasonxia23](https://github.com/jasonxia23)
-# Contextual Chatbots with Tensorflow
+# 基于 TensorFlow 的上下文机器人
-In conversations, **context is king!** We’ll build a chatbot framework using Tensorflow and add some context handling to show how this can be approached.
+在对话中, **语境决定了一切!** ,在这篇文章中我们将使用 TensorFlow 构建一个能够处理上下文的聊天机器人框架。
-![](https://cdn-images-1.medium.com/max/800/1*UuPrIVA-TutyZ0MXvkGOvg.jpeg)
+有没有想过为什么大多数聊天机器人都不能够理解语境的上下文?
-“Whole World in your Hand” — Betty Newman-Maguire ([http://www.bettynewmanmaguire.ie/](http://www.bettynewmanmaguire.ie/))
-Ever wonder why most chat-bots lack conversational context?
+怎么可能在所有的对话中考虑到上下文的重要性?
-How is this possible given the importance of context in nearly all conversations?
+我们将创建一个“聊天机器人”框架,并为一个岛上的汽车出租店建立一个会话模型,这个小型的聊天机器人需要能够处理关于时间计算,预订选择等简单的功能。我们还希望他能够响应一些上下文的操作,譬如询问当天的租金。这样的话,我们的工作就可以减轻不少。
-We’re going to create a chat-bot framework and build a conversational model for an **island moped rental shop**. The chatbot for this small business needs to handle simple questions about hours of operation, reservation options and so on. We also want it to handle contextual responses such as inquiries about same-day rentals. Getting this right [could save a vacation](https://medium.com/p/how-a-messaging-app-saved-my-vacation-192b031a96f5)!
+我们将通过下面三步来实现这个功能:
-We’ll be working through 3 steps:
+- 首先,把对话意图的定义转换成 TensoFlow 模型
+- 接下来,我们构建一个聊天机器人框架来处理响应
+- 最后,我们将展示如何将基本的上下文合并到我们的相应处理模块中
-- We’ll transform conversational intent definitions to a Tensorflow model
-- Next, we will build a chat-bot framework to process responses
-- Lastly, we’ll show how basic context can be incorporated into our response processor
+我们将使用在 TensorFlow 上构建的高层次 API,也即 [**tflearn**](http://tflearn.org/) ,当然还有 [**Python**](https://www.python.org/) ,同时还使用 [**iPython notebook**](https://ipython.org/notebook.html) 来更好的完成我们的工作
-We’ll be using [**tflearn**](http://tflearn.org/), a layer above [**tensorflow**](https://www.tensorflow.org/), and of course [**Python**](https://www.python.org/). As always we’ll use [**iPython notebook**](https://ipython.org/notebook.html) as a tool to facilitate our work.
---
-#### Transform conversational intent definitions to a Tensorflow model
+#### 将会话意图的定义转换为 TensorFlow 模型
-The complete notebook for our first step is [here](https://github.com/ugik/notebooks/blob/master/Tensorflow%20chat-bot%20model.ipynb).
+这一部分的完整笔记在[这里](https://github.com/ugik/notebooks/blob/master/Tensorflow%20chat-bot%20model.ipynb)
-A chat-bot framework needs a structure in which conversational intents are defined. One clean way to do this is with a JSON file, like [this](https://github.com/ugik/notebooks/blob/master/intents.json).
+一个聊天机器人框架需要一个结构,而其中就定义了会话的意图,在这里我们使用了 json 文件来定义他,如这个[文件](https://github.com/ugik/notebooks/blob/master/intents.json)中所示
![](https://cdn-images-1.medium.com/max/800/1*pcbw_Y4acT750-lL98iw2Q.png)
-chat-bot intents
-Each conversational intent contains:
+聊天机器人的意图
+每个对话的意图都包含:
-- a **tag** (a unique name)
-- **patterns** (sentence patterns for our neural network text classifier)
-- **responses** (one will be used as a response)
+- 一个 **标签**(tag,唯一标识的名字)
+- **模式**(神经网络文本分类器的句子模式)
+- **响应**(用作响应)
-And later on we’ll add *some basic contextual elements*.
+晚些我们将 **添加一些基本的上下文元素**
-First we take care of our imports:
+首先 import 需要的库
-```
-# things we need for NLP
+```Python
+# NLP 相关的处理库
import nltk
from nltk.stem.lancaster import LancasterStemmer
stemmer = LancasterStemmer()
-# things we need for Tensorflow
+# TensorFlow 相关的库
import numpy as np
import tflearn
import tensorflow as tf
import random
```
-Have a look at “[Deep Learning in 7 lines of code](https://chatbotslife.com/deep-learning-in-7-lines-of-code-7879a8ef8cfb)” for a primer or [here](https://chatbotslife.com/tensorflow-demystified-80987184faf7) if you need to demystify Tensorflow.
+如果你想入门 TensorFlow ,可以看[这篇文章](https://chatbotslife.com/deep-learning-in-7-lines-of-code-7879a8ef8cfb),若要进一步的了解的话可以看[这篇文章](https://chatbotslife.com/tensorflow-demystified-80987184faf7)。
-```
+```Python
# import our chat-bot intents file
import json
with open('intents.json') as json_data:
intents = json.load(json_data)
```
-With our intents JSON [file](https://github.com/ugik/notebooks/blob/master/intents.json) loaded, we can now begin to organize our documents, words and classification classes.
+意图的 JSON 文件被加载后,我们现在可以开始组织我们的文档、文字和分类器对应的类别。
-```
+
+```Python
words = []
classes = []
documents = []
ignore_words = ['?']
-# loop through each sentence in our intents patterns
+# 根据意图遍历所有的句子
for intent in intents['intents']:
for pattern in intent['patterns']:
- # tokenize each word in the sentence
+ # 分词
w = nltk.word_tokenize(pattern)
- # add to our words list
+ # 将词添加到列表中
words.extend(w)
- # add to documents in our corpus
+ # 将文档添加到词料库
documents.append((w, intent['tag']))
- # add to our classes list
+ # 将 Tag 添加到类别中
if intent['tag'] not in classes:
classes.append(intent['tag'])
-# stem and lower each word and remove duplicates
+# 将词小写然后去掉忽略的词
words = [stemmer.stem(w.lower()) for w in words if w not in ignore_words]
words = sorted(list(set(words)))
-# remove duplicates
+# 使用 set 去掉重复的词
classes = sorted(list(set(classes)))
print (len(documents), "documents")
@@ -103,109 +102,110 @@ print (len(classes), "classes", classes)
print (len(words), "unique stemmed words", words)
```
-We create a list of documents (sentences), each sentence is a list of *stemmed**words* and each document is associated with an intent (a class).
+我们创建了一个文档(句子)列表,每个句子都是一个词干的列表,每个文档都与一个意图(一个类)相关。
-```
+```Python
27 documents
9 classes ['goodbye', 'greeting', 'hours', 'mopeds', 'opentoday', 'payments', 'rental', 'thanks', 'today']
44 unique stemmed words ["'d", 'a', 'ar', 'bye', 'can', 'card', 'cash', 'credit', 'day', 'do', 'doe', 'good', 'goodby', 'hav', 'hello', 'help', 'hi', 'hour', 'how', 'i', 'is', 'kind', 'lat', 'lik', 'mastercard', 'mop', 'of', 'on', 'op', 'rent', 'see', 'tak', 'thank', 'that', 'ther', 'thi', 'to', 'today', 'we', 'what', 'when', 'which', 'work', 'you']
```
-The stem ‘tak’ will match ‘take’, ‘taking’, ‘takers’, etc. We could clean the words list and remove useless entries but this will suffice for now.
+词干 "tak" 将会和 "take", "taking","takers" 等词匹配。我们可以清理单词列表并删除无用的条目,但这就足够了。
-Unfortunately this data structure won’t work with Tensorflow, we need to transform it further: *from documents of words *into* tensors of numbers*.
+但是目前的数据结构不能够被 TensorFlow 利用,我们需要进一步的转换它: **也即将文档中的词转换成数字的张量。**
-```
-# create our training data
+
+```Python
+# 创建训练数据
training = []
output = []
-# create an empty array for our output
+# 创建一个空数组来储存输出
output_empty = [0] * len(classes)
-# training set, bag of words for each sentence
+# 每个句子的训练集和词袋
for doc in documents:
- # initialize our bag of words
+ # 初始化词袋
bag = []
- # list of tokenized words for the pattern
+ # 列出文档中所有的词
pattern_words = doc[0]
- # stem each word
+ # 让词成为词干
pattern_words = [stemmer.stem(word.lower()) for word in pattern_words]
- # create our bag of words array
+ # 创建我们的词袋数组
for w in words:
bag.append(1) if w in pattern_words else bag.append(0)
- # output is a '0' for each tag and '1' for current tag
+ # 如果是当前的标记输出 1 ,否的话输出 0
output_row = list(output_empty)
output_row[classes.index(doc[1])] = 1
training.append([bag, output_row])
-# shuffle our features and turn into np.array
+# 打乱训练集并且转换成 np.array 类型
random.shuffle(training)
training = np.array(training)
-# create train and test lists
+# 创建训练集
train_x = list(training[:,0])
train_y = list(training[:,1])
```
-Notice that our data is shuffled. Tensorflow will take some of this and use it as test data *to gauge accuracy for a newly fitted model*.
+注意,我们的数据被打乱了。TensorFlow 会使用其中一部分数据用作测试, **以评估训练模型的准确性。**
-If we look at a single x and y list element, we see ‘[bag of words](https://en.wikipedia.org/wiki/Bag-of-words_model)’ arrays, one for the intent pattern, the other for the intent class.
+下面是一个 x 和 y 的列表元素,也即[词袋](https://en.wikipedia.org/wiki/Bag-of-words_model)数组,一个是意图的模式,另一个是意图所对应的类。
-```
+```Python
train_x example: [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1]
train_y example: [0, 0, 1, 0, 0, 0, 0, 0, 0]
```
-We’re ready to build our model.
+我们已经准备好了,可以创建我们的模型了。
-```
-# reset underlying graph data
+```Python
+# 重置底层图数据
tf.reset_default_graph()
-# Build neural network
+# 创建神经网络
net = tflearn.input_data(shape=[None, len(train_x[0])])
net = tflearn.fully_connected(net, 8)
net = tflearn.fully_connected(net, 8)
net = tflearn.fully_connected(net, len(train_y[0]), activation='softmax')
net = tflearn.regression(net)
-# Define model and setup tensorboard
+# 定义模型并创建 tensorboard
model = tflearn.DNN(net, tensorboard_dir='tflearn_logs')
-# Start training (apply gradient descent algorithm)
+# 使用梯度下降方法训练模型
model.fit(train_x, train_y, n_epoch=1000, batch_size=8, show_metric=True)
model.save('model.tflearn')
```
-This is the same tensor structure as we used in our 2-layer neural network in [our ‘toy’ example](https://chatbotslife.com/deep-learning-in-7-lines-of-code-7879a8ef8cfb). Watching the model fit our training data never gets old…
+这个张量的结构与我们[之前在一篇文章](https://chatbotslife.com/deep-learning-in-7-lines-of-code-7879a8ef8cfb)中使用的 2 层神经网络是相同的,训练模型的方式是不会过时的。
+
![](https://cdn-images-1.medium.com/max/800/1*5UIqnedBzsYTXJ81wEU-vg.gif)
-interactive build of a model in tflearn
-To complete this section of work, we’ll save (‘pickle’) our model and documents so the next notebook can use them.
+使用 tflearn 交互式构建模型
+为了完成这部分的工作,我们将序列化保存(pickle)模型和文档以便我们在以后的 Jupyter Notebook 中可以使用他们。
-```
-# save all of our data structures
+```Python
+# 保存我们所有的数据结构
import pickle
pickle.dump( {'words':words, 'classes':classes, 'train_x':train_x, 'train_y':train_y}, open( "training_data", "wb" ) )
```
---
-![](https://cdn-images-1.medium.com/max/800/1*f9Sq7I_pauPQ9u4PbtPt4w.jpeg)
-#### Building our chat-bot framework
+#### 创建我们的聊天机器人框架
-The complete notebook for our second step is [here](https://github.com/ugik/notebooks/blob/master/Tensorflow%20chat-bot%20response.ipynb).
+这部分的完整 notebook 在[这里](https://github.com/ugik/notebooks/blob/master/Tensorflow%20chat-bot%20response.ipynb)可以下载。
-We’ll build a simple state-machine to handle responses, using our intents model (from the previous step) as our classifier. That’s [how chat-bot’s work](https://medium.freecodecamp.com/how-chat-bots-work-dfff656a35e2).
+我们创建了一个简单的状态机来处理响应,用我们的意图模型(上一步训练的结果)作为分类器。 [聊天机器人是如何工作的](https://medium.freecodecamp.com/how-chat-bots-work-dfff656a35e2)
-> A contextual chat-bot framework is a classifier within a *state-machine*.
+> 上下文的聊天机器人框架是 **状态机** 内的一个分类器。
-After loading the same imports, we’ll *un-pickle* our model and documents as well as reload our intents file. Remember our chat-bot framework is separate from our model build — you don’t need to rebuild your model unless the intent patterns change. With several hundred intents and thousands of patterns the model could take several minutes to build.
+加载相同的导入模块后,我们将 **反序列化** 我们的模型和文档并且重新加载我们的意图文件。记住我们的 chat-bot 框架是和我们的模型分开来构建的—你不需要重新构建你的模型除非意图模式发生改变。因为有几百个意图和数千个模式,所以这个模型可能需要几分钟的时间来构建。
-```
-# restore all of our data structures
+```Python
+# 重置变量
import pickle
data = pickle.load( open( "training_data", "rb" ) )
words = data['words']
@@ -213,34 +213,34 @@ classes = data['classes']
train_x = data['train_x']
train_y = data['train_y']
-# import our chat-bot intents file
+# 导入聊天机器人的意图文件
import json
with open('intents.json') as json_data:
intents = json.load(json_data)
```
-Next we will load our saved Tensorflow (tflearn framework) model. Notice you first need to define the Tensorflow model structure just as we did in the previous section.
+接下来将加载我们保存在 TensorFlow (tflearn framework) 上的模型。首先我们需要和前面章节所述的一样来定义 TensorFlow 模型的结构。
-```
-# load our saved model
+```Python
+# 加载保存的模型
model.load('./model.tflearn')
```
-Before we can begin processing intents, we need a way to produce a bag-of-words *from user input*. This is the same technique as we used earlier to create our training documents.
+在开始处理意图之前,我们需要 **从用户的输入** 中生成词袋(bag-of-words),这和我们之前创建训练文档时使用的技术是一样的。
-```
+```Python
def clean_up_sentence(sentence):
- # tokenize the pattern
+ # 分词
sentence_words = nltk.word_tokenize(sentence)
- # stem each word
+ # 转换句子为词干
sentence_words = [stemmer.stem(word.lower()) for word in sentence_words]
return sentence_words
-# return bag of words array: 0 or 1 for each word in the bag that exists in the sentence
+# 返回词袋数组,每个数组的下标表示词的序号,如果句子包含该词,则该数组词为 1,否为 0
def bow(sentence, words, show_details=False):
- # tokenize the pattern
+ # pattern 分词
sentence_words = clean_up_sentence(sentence)
- # bag of words
+ # 词袋
bag = [0]*len(words)
for s in sentence_words:
for i,w in enumerate(words):
@@ -258,61 +258,60 @@ print (p)
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0]
```
-We are now ready to build our response processor.
+我们现在可以构建我们的响应处理器了。
-```
+```Python
ERROR_THRESHOLD = 0.25
def classify(sentence):
- # generate probabilities from the model
+ # 得出预测的概率
results = model.predict([bow(sentence, words)])[0]
- # filter out predictions below a threshold
+ # 根据概率值过滤结果
results = [[i,r] for i,r in enumerate(results) if r>ERROR_THRESHOLD]
- # sort by strength of probability
+ # 根据返回值长度降序排序
results.sort(key=lambda x: x[1], reverse=True)
return_list = []
for r in results:
return_list.append((classes[r[0]], r[1]))
- # return tuple of intent and probability
+ # 返回包含意图和概率的元组
return return_list
def response(sentence, userID='123', show_details=False):
results = classify(sentence)
- # if we have a classification then find the matching intent tag
+ # results 不为空则循环找到匹配的 tag
if results:
- # loop as long as there are matches to process
+ # 循环找到匹配的 tag
while results:
for i in intents['intents']:
- # find a tag matching the first result
+ # 是否匹配
if i['tag'] == results[0][0]:
- # a random response from the intent
+ # 随机输出一个响应??
return print(random.choice(i['responses']))
-
results.pop(0)
```
-Each sentence passed to response() is classified. Our classifier uses **model.predict()** and is lighting fast. The probabilities returned by the model are lined-up with our intents definitions to produce a list of potential responses.
+句子传递到 response() 方法后会被分类。我们分类器使用 **model.predict()** 方法是响应很快的。模型返回的响应结果的概率列表是和我们的意图定义一起处理的。
-If one or more classifications are above a threshold, we see if a tag matches an intent and then process that. We’ll treat our classification list as a stack and pop off the stack looking for a suitable match until we find one, or it’s empty.
+如果一个或多个分类器超过一个阈值,那么我们就会看到一个标记是否匹配一个意图然后再处理它。分类器列表将会当成栈,然后不断的从栈中弹出一个元素来进行匹配是否符合,直到空栈为止。
-Let’s look at a classification example, the most likely tag and its probability are returned.
+让我们来看一个分类器的例子,我们看到最可能的标记和它所对应的概率值被返回了。
-```
+```Python
classify('is your shop open today?')
[('opentoday', 0.9264171123504639)]
```
-Notice that ‘is your shop open today?’ is not one of the patterns for this intent: *“patterns”: [“Are you open today?”, “When do you open today?”, “What are your hours today?”] *however the terms ‘open’ and ‘today’ proved irresistible to our model (they are prominent in the chosen intent).
+注意到“你的商店今天营业吗”并不是这种意图的模式之一: **模式:["你今天开着吗?","你今天什么时候开?","你今天营业几小时?"]** ,然而词“开”和“今天”对我们的模式来说是很重要的(也就是说他们决定了模型会选择什么意图)。
-We can now generate a chat-bot response from user-input:
+所以我们就可以根据用户的输入生成一个 chat-bot 的回应
-```
+```Python
response('is your shop open today?')
Our hours are 9am-9pm every day
```
-And other context-free responses…
+下面是另外一个上下文无关的响应。
-```
+```Python
response('do you take cash?')
We accept VISA, Mastercard and AMEX
response('what kind of mopeds do you rent?')
@@ -323,87 +322,83 @@ Bye! Come back again soon.
---
-![](https://cdn-images-1.medium.com/max/800/1*RrQH1Mt6R73nq6lO6vTZ2w.jpeg)
-Let’s work in some basic context into our moped rental chat-bot conversation.
+让我们给出租汽车的聊天机器人加入一些基本的上下文吧。
-#### Contextualization
+#### 情景化
-We want to handle a question about renting a moped and ask if the rental is for today. That clarification question is a simple contextual response. If the user responds ‘today’ *and the context is the rental timeframe* then it’s best they call the rental company’s 1–800 #. No time to waste.
+我们想要让聊天机器人处理关于出租汽车的对话,比如询问客户是否要今天租赁。这个问题是一个简单的上下文响应,如果用户回复“今天”,那么上下文就是租赁时间,这个时候就赶紧给租赁公司打电话吧,他不想错过这个订单的。
-To achieve this we will add the notion of ‘state’ to our framework. This is comprised of a data-structure to maintain state and specific code to manipulate it while processing intents.
+为了实现这一目的,我们在框架中添加了状态这个概念。这由一个保存状态的数据结构和操作状态的特定代码组成,以便处理意图。
-Because the state of our state-machine needs to be easily persisted, restored, copied, etc. it’s important to keep it all in a data structure such as a dictionary.
+因为状态机(state-machine)需要很容易地持久化、恢复、复制等等,所以把它保存在像字典这样的数据结构中是很重要的。
-Here’s our response process with basic contextualization:
+以下是我们对基本情景化的反应过程:
-```
-# create a data structure to hold user context
-context = {}
+```Python
+# 字典储存上下文
+context = {}
ERROR_THRESHOLD = 0.25
def classify(sentence):
- # generate probabilities from the model
+ # 得到的预测的结果(概率)列表
results = model.predict([bow(sentence, words)])[0]
- # filter out predictions below a threshold
+ # 根据错误阈值筛选预测的结果
results = [[i,r] for i,r in enumerate(results) if r>ERROR_THRESHOLD]
- # sort by strength of probability
+ # 根据概率值倒序排序
results.sort(key=lambda x: x[1], reverse=True)
return_list = []
for r in results:
return_list.append((classes[r[0]], r[1]))
- # return tuple of intent and probability
+ # 返回意图和概率的元组
return return_list
def response(sentence, userID='123', show_details=False):
results = classify(sentence)
- # if we have a classification then find the matching intent tag
+ # 根据分类结果匹配意图标签
if results:
- # loop as long as there are matches to process
+ # 循环匹配
while results:
for i in intents['intents']:
- # find a tag matching the first result
+ # 寻找与第一个结果匹配的标签
if i['tag'] == results[0][0]:
- # set context for this intent if necessary
+ # 在必要时为这个意图设置上下文
if 'context_set' in i:
if show_details: print ('context:', i['context_set'])
context[userID] = i['context_set']
-
- # check if this intent is contextual and applies to this user's conversation
+ # 检查这个意图是否与上下文相关然后与当前用户关联
if not 'context_filter' in i or \
(userID in context and 'context_filter' in i and i['context_filter'] == context[userID]):
if show_details: print ('tag:', i['tag'])
- # a random response from the intent
+ # 返回响应
return print(random.choice(i['responses']))
-
results.pop(0)
```
-Our context state is a dictionary, it will contain state for each user. We’ll use some unique identified for each user (eg. cell #). This allows our framework and state-machine to *maintain state for multiple users simultaneously*.
+我们的上下文状态是一个字典,他将包含每个用户的状态。每个用户都有唯一的标识符,从而达到让我们的框架能够 **无缝地维持多个用户之间的状态。**
-> # create a data structure to hold user context
+> # 使用字典来维持用户的上下文
> context = {}
-The context handlers are added within the intent processing flow, shown again below:
+上下文处理程序被添加到意图处理流中,如下所示:
+```Python
+ if i['tag'] == results[0][0]:
+ # 在必要时为这个意图设置上下文
+ if 'context_set' in i:
+ if show_details: print ('context:', i['context_set'])
+ context[userID] = i['context_set']
+ # 检查这个意图是否与上下文相关然后与当前用户关联
+ if not 'context_filter' in i or \
+ (userID in context and 'context_filter' in i and i['context_filter'] == context[userID]):
+ if show_details: print ('tag:', i['tag'])
+ # 返回响应
+ return print(random.choice(i['responses']))
```
- if i['tag'] == results[0][0]:
- # set context for this intent if necessary
- if 'context_set' in i:
- if show_details: print ('context:', i['context_set'])
- context[userID] = i['context_set']
- # check if this intent is contextual and applies to this user's conversation
- if not 'context_filter' in i or \
- (userID in context and 'context_filter' in i and i['context_filter'] == context[userID]):
- if show_details: print ('tag:', i['tag'])
- # a random response from the intent
- return print(random.choice(i['responses']))
-```
-
-If an intent wants to **set** context, it can do so:
+如果一个意图想要设置上下文,他可以这样做:
-```
+```Python
{“tag”: “rental”,
“patterns”: [“Can we rent a moped?”, “I’d like to rent a moped”, … ],
“responses”: [“Are you looking to rent today or later this week?”],
@@ -411,9 +406,9 @@ If an intent wants to **set** context, it can do so:
}
```
-If another intent wants to be contextually linked to a context, it can do that:
+如果另外一个意图想要和上下文联系,那么他可以这样做:
-```
+```Python
{“tag”: “today”,
“patterns”: [“today”],
“responses”: [“For rentals today please call 1–800-MYMOPED”, …],
@@ -421,23 +416,23 @@ If another intent wants to be contextually linked to a context, it can do that:
}
```
-In this way, if a user just typed ‘today’ out of the blue (no context), our ‘today’ intent won’t be processed. If they enter ‘today’ *as a response to our clarification question* (intent tag:‘rental’) then the intent is processed.
+用这种方式,当用户只是意料之外地输入“今天“的的时候(没有上下文),“今天” 这个意图就不会被处理。当他们输入的 “今天” 作为回复我们提出的问题的时候,那么这个意图就会被处理。
-```
+```Python
response('we want to rent a moped')
Are you looking to rent today or later this week?
response('today')
Same-day rentals please call 1-800-MYMOPED
```
-Our context state changed:
+我们的上下文状态就会改变
```
context
{'123': 'rentalday'}
```
-We defined our ‘greeting’ intent to clear context, as is often the case with small-talk. We add a ‘show_details’ parameter to help us see inside.
+我们定义“问候”的语句来清除上下文,就像闲聊时经常发生的那样。我们添加了一个 “查看详情” 的参数来帮助我们查看内部的运作。
```
response("Hi there!", show_details=True)
@@ -446,66 +441,60 @@ tag: greeting
Good to see you again
```
-Let’s try the ‘today’ input once again, a few notable things here…
+让我们再尝试一下输入 “今天”,这里有一些需要注意的东西...
-```
+```Python
response('today')
We're open every day from 9am-9pm
classify('today')
[('today', 0.5322513580322266), ('opentoday', 0.2611265480518341)]
```
-First, our response to the context-free ‘today’ was different. Our classification produced 2 suitable intents, and the ‘opentoday’ was selected because the ‘today’ intent, while higher probability, was bound to *a context that no longer applied*. Context matters!
+首先,我们对上下文无关的“今天”的反应是不同的。我们的分类产生了 2 个合适的意图,但是 'opentoday' 被选中, 'today' 意图虽然具备更高的可能性,但是却被限制在一个不再合适的环境中,**所以说上下文很重要**。
-```
+```Python
response("thanks, your great")
Happy to help!
```
---
-![](https://cdn-images-1.medium.com/max/800/1*YsxOYwba2fii9G98UXp1pw.jpeg)
-
-A few things to consider now that contextualization is happening…
+在语境化发生的情况下有几件事情需要考虑。
-#### With state comes statefulness
+#### 维持状态
-That’s right, your chat-bot will no longer be happy *as a stateless service*.
+没错,你的聊天机器人将不再是一种 **无状态的服务**。
-Unless you want to reconstitute state, reload your model and documents — with every call to your chat-bot framework, you’ll need to make it *stateful*.
+除非你想重新构建状态,重新加载模型和文档—每次调用你的聊天机器人框架时,你都需要使其成为有状态的。
-This isn’t that difficult. You can run a stateful chat-bot framework in its own process and call it using an RPC (remote procedure call) or RMI (remote method invocation), I recommend [Pyro](http://pythonhosted.org/Pyro4/).
+这并不是那么难,你可以运行一个有状态的聊天机器人框架的过程,也即使用远程过程调用 RPC 或者远程方法调用 RMI,在这里我推荐使用 [Pyro](http:/。pythonhosted.org/Pyro4/)。
![](https://cdn-images-1.medium.com/max/600/1*hpbuSvovqSyVY-nhBcoIaQ.jpeg)
-RMI client and server setup
-The user-interface (client) is typically stateless, eg. HTTP or SMS.
+RMI 客户端和服务器设置
+用户界面(客户端)通常是无状态的,例如。HTTP 或 SMS。
-Your chat-bot *client* will make a Pyro function call, which your stateful service will handle. Voila!
+你 **客户端** 的聊天机器人将会创建一个 Pyro 函数调用,你的有状态服务将会处理他。
-[Here](https://chatbotslife.com/build-a-working-sms-chat-bot-in-10-minutes-b8278d80cc7a)’s a step-by-step guide to build a Twilio SMS chat-bot client, and [here](https://chatbotnewsdaily.com/build-a-facebook-messenger-chat-bot-in-10-minutes-5f28fe0312cd)’s one for FB Messenger.
+这里有一篇一步一步指导你构建 Twilio SMS 聊天机器人客户端的[文章](https://chatbotslife.com/build-a-working-sms-chat-bot-in-10-minutes-b8278d80cc7a),另外一篇[文章](https://chatbotnewsdaily.com/build-a-facebook-messenger-chat-bot-in-10-minutes-5f28fe0312cd)是关于构建 FB Messenger 的。
-#### Thou shalt not store state in local variables
+#### 不可将状态储存在局部变量中
-All state information must be placed in a data structure such as a dictionary, easily persisted, reloaded, or copied atomically.
+所有的状态信息都必须放在像字典这样的数据结构中,很容易持久化、重新加载或复制。
-Each user’s conversation will carry context which will be carried statefully for that user. The user ID can be their cell #, a Facebook user ID, or some other unique identifier.
+每个用户的对话都将承载为该用户提供状态的上下文。用户的唯一标识 ID 可以是手机号,Facebook 的用户 ID 或者其他的唯一标识符
-There are scenarios where a user’s conversational state needs to be copied (by value) and then restored as a result of intent processing. If your state machine carries state across variables within your framework you will have a difficult time making this work in real life scenarios.
+在一些场景中用户的对话状态需要被复制然后重新储存起来被意图所处理。如果你的状态机携带的一些状态的变量在框架中是共用的话,则很难在实际场景中实现这一工作。
-> Python dictionaries are your friend.
+> Python 字典是你的朋友
---
-So now you have a chat-bot framework, a recipe for making it a stateful service, and a starting-point for adding context. Most chat-bot frameworks [in the future will treat context seamlessly](https://medium.com/@gk_/the-future-of-messaging-apps-590720cfa792).
-
-Think of creative ways for intents to impact and react to different context settings. Your users’ context dictionary can contain a wide-variety of conversation context.
-
-**Enjoy!**
+现在你已经知道如何构建一个聊天机器人的框架以及使它具备有服务状态的方法,[大部分聊天机器人框架都能够无缝地处理上下文](https://medium.com/@gk_/the-future-of-messaging-apps-590720cfa792)。
-![](https://cdn-images-1.medium.com/max/800/1*7nbWVuNCP1sd5ZHVqElG_Q.jpeg)
+多想一些有创意的方法来影响聊天机器人对不同上下文所做出设置。你的用户的上下文字典可以包含各种各样的对话上下文。
-credit: [https://wickedgoodweb.com](https://wickedgoodweb.com/seo-context-is-king/)
+**享受它吧!**
---
diff --git a/TODO/deep-learning-4-embedding-layers.md b/TODO/deep-learning-4-embedding-layers.md
index 7a1c4b0dc04..e948234b142 100644
--- a/TODO/deep-learning-4-embedding-layers.md
+++ b/TODO/deep-learning-4-embedding-layers.md
@@ -3,88 +3,87 @@
> * 原文作者:[Rutger Ruizendaal](https://medium.com/@r.ruizendaal)
> * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
> * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO/deep-learning-4-embedding-layers.md](https://github.com/xitu/gold-miner/blob/master/TODO/deep-learning-4-embedding-layers.md)
-> * 译者:
-> * 校对者:
+> * 译者:[Tobias Lee](http://tobiaslee.top)
+> * 校对者:[LJ147](https://github.com/LJ147)、[changkun](https://github.com/changkun)
-# Deep Learning 4: Why You Need to Start Using Embedding Layers
+# 深度学习系列4: 为什么你需要使用嵌入层
-## And how there’s more to it than word embeddings.
+## 除了词嵌入以外还有很多
![](https://cdn-images-1.medium.com/max/2000/1*sXNXYfAqfLUeiDXPCo130w.png)
-*This post is part of a series on deep learning. Checkout the other parts here:*
+**这是深度学习系列的其中一篇,其他文章地址如下**
-1. [Setting up AWS & Image Recognition](https://medium.com/towards-data-science/deep-learning-1-1a7e7d9e3c07)
-2. [Convolutional Neural Networks](https://medium.com/towards-data-science/deep-learning-2-f81ebe632d5c)
-3. [More on CNNs & Handling Overfitting](https://medium.com/towards-data-science/deep-learning-3-more-on-cnns-handling-overfitting-2bd5d99abe5d)
+1. [设置 AWS & 图像识别](https://github.com/xitu/gold-miner/blob/master/TODO/deep-learning-1-setting-up-aws-image-recognition.md)
+2. [卷积神经网络](https://github.com/xitu/gold-miner/blob/master/TODO/deep-learning-2-convolutional-neural-networks.md)
+3. [CNNs 以及应对过拟合的详细探讨](https://github.com/xitu/gold-miner/blob/master/TODO/deep-learning-3-more-on-cnns-handling-overfitting.md)
---
-Welcome to part 4 of this series on deep learning. As you might have noticed there has been a slight delay between the first three entries and this post. The initial goal of this series was to write along with the fast.ai course on deep learning. However, the concepts of the later lectures are often overlapping so I decided to finish the course first. This way I get to provide a more detailed overview of these topics. In this blog I want to cover a concept that spans multiple lectures of the course (4–6) and that has proven very useful to me in practice:Embedding Layers.
+欢迎阅读深度学习系列的第四部分,你可能注意到这一篇和前面三篇文章之间隔了一小段时间。我写这个系列最初的目的是想记录 fast.ai 上的深度学习课程,然而后面一部分课程的内容有所重叠,所以我决定先把课程完成,这样我能够更为细致地从整体上来把握这些主题。在这篇文章里我想介绍一个在很多节课中都有涉及,并且在实践中被证明非常有用的一个概念:嵌入层(Embedding layer)。
-Upon introduction the concept of the embedding layer can be quite foreign. For example, the Keras documentation provides no explanation other than “Turns positive integers (indexes) into dense vectors of fixed size”. A quick Google search might not get you much further either since these type of documentations are the first things to pop-up. However, in a sense Keras’ documentation describes all that happens. So why should you use an embedding layer? Here are the two main reasons:
+介绍嵌入层这个概念可能会让它变得更加难以理解。比如说,Keras 文档里是这么写的:“把正整数(索引)转换为固定大小的稠密向量”。你 Google 搜索也无济于事,因为文档通常会排在搜索结果的第一个(你还是不能获得更加详细的解释)。然而,从某种意义上来说,Keras 文档的描述是正确的。那么为什么你应该使用嵌入层呢?这里有两个主要原因:
-1. One-hot encoded vectors are high-dimensional and sparse. Let’s assume that we are doing Natural Language Processing (NLP) and have a dictionary of 2000 words. This means that, when using one-hot encoding, each word will be represented by a vector containing 2000 integers. And 1999 of these integers are zeros. In a big dataset this approach is not computationally efficient.
-2. The vectors of each embedding get updated while training the neural network. If you have seen the image at the top of this post you can see how similarities between words can be found in a multi-dimensional space. This allows us to visualize relationships between words, but also between everything that can be turned into a vector through an embedding layer.
+1. 独热编码(One-hot encoding)向量是高维且稀疏的。假如说我们在做自然语言处理(NLP)的工作,并且有一个包含 2000 个单词的字典。这意味着当我们使用独热编码时,每个单词由一个含有 2000 个整数的向量来表示,并且其中的 1999 个整数都是 0。在大数据集下这种方法的计算效率是很低的。
+2. 每个嵌入向量会在训练神经网络时更新。文章的最上方有几张图片,它们展示了在多维空间之中,词语之间的相似程度,这使得我们能够可视化词语之间的关系。同样,对于任何能够通过使用嵌入层而把它变成向量的东西,我们都能够这么做。
-This concept might still be a bit vague. Let’s have a look at what an embedding layer does with an example of words. Nevertheless, the origin of embeddings comes from word embeddings. You can look up [word2vec](https://arxiv.org/pdf/1301.3781.pdf) if you are interested in reading more. Let’s take this sentence as an example (do not take it to seriously):
+嵌入层这个概念可能还是有点模糊,让我们再来看嵌入层作用在词语上的一个例子。嵌入这个概念源自于词嵌入(Word embedding),如果你想了解更多的话可以看看 [word2vec](https://arxiv.org/pdf/1301.3781.pdf) 这篇论文。让我们用下面这个句子作为例子(随便举的一个例子,不用太认真对待):
> “deep learning is very deep”
-The first step in using an embedding layer is to encode this sentence by indices. In this case we assign an index to each unique word. The sentence than looks like this:
+使用嵌入层的第一步是通过索引对这个句子进行编码,在这个例子里,我们给句中每个不同的词一个数字索引,编码后的句子如下所示:
> 1 2 3 4 1
-The embedding matrix gets created next. We decide how many ‘latent factors’ are assigned to each index. Basically this means how long we want the vector to be. General use cases are lengths like 32 and 50. Let’s assign 6 latent factors per index in this post to keep it readable. The embedding matrix than looks like this:
+下一步是创建嵌入矩阵。我们要决定每个索引有多少“潜在因素”,这就是说,我们需要决定词向量的长度。一般我们会使用像 32 或者 50 这样的长度。出于可读性的考虑,在这篇文章里我们每个索引的“潜在因素”个数有 6 个。那么嵌入矩阵就如下图所示:
![](https://cdn-images-1.medium.com/max/1600/1*Di85w_0UTc6C3ilk5_LEgg.png)
-Embedding Matrix
+嵌入矩阵
-So, instead of ending up with huge one-hot encoded vectors we can use an embedding matrix to keep the size of each vector much smaller. In short, all that happens is that the word “deep” gets represented by a vector [.32, .02, .48, .21, .56, .15]. However, not every word gets replaced by a vector. Instead, it gets replaced by index that is used to look-up the vector in the embedding matrix. Once again, this is computationally efficient when using very big datasets. Because the embedded vectors also get updated during the training process of the deep neural network, we can explore what words are similar to each other in a multi-dimensional space. By using dimensionality reduction techniques like [t-SNE ](https://lvdmaaten.github.io/tsne/)these similarities can be visualized.
+所以,和独热编码中每个词向量的长度相比,使用嵌入矩阵能够让每个词向量的长度大幅缩短。简而言之,我们用一个向量 [.32, .02, .48, .21, .56, .15]来代替了词语“deep”。然而并不是每个词被一个向量所代替,而是由其索引在嵌入矩阵中对应的向量代替。再次强调,在大数据集中,这种方法的计算效率是很高的。同时因为在训练深度神经网络过程中,词向量能够不断地被更新,所以我们同样能够在多维空间中探索各个词语之间的相似程度。通过使用像 [t-SNE ](https://lvdmaaten.github.io/tsne/) 这样的降维技术,我们能够把这些相似程度可视化出来。
![](https://cdn-images-1.medium.com/max/1600/1*m8Ahpl-lpVgm16CC-INGuw.png)
-t-SNE visualization of word embeddings
+通过 t-SNE 可视化的词嵌入(向量)
---
-### Not Just Word Embeddings
+### 不仅仅是词嵌入
-These previous examples showed that word embeddings are very important in the world of Natural Language Processing. They allow us to capture relationships in language that are very difficult to capture otherwise. However, embedding layers can be used to embed many more things than just words. In my current research project I am using embedding layers to embed online user behavior. In this case I am assigning indices to user behavior like ‘page view on page type X on portal Y’ or ‘scrolled X pixels’. These indices are then used for constructing a sequence of user behavior.
+前面的例子体现了词嵌入在自然语言处理领域重要的地位,它能够帮助我们找到很难察觉的词语之间的关系。然而,嵌入层不仅仅可以用在词语上。在我现在的一个研究项目里,我用嵌入层来嵌入网上用户的使用行为:我为用户行为分配索引,比如“浏览类型 X 的网页(在门户 Y 上)”或“滚动了 X 像素”。然后,用这些索引构建用户的行为序列。
-In a comparison of ‘traditional’ machine learning models (SVM, Random Forest, Gradient Boosted Trees) with deep learning models (deep neural networks, recurrent neural networks) I found that this embedding approach worked very well for deep neural networks.
+深度学习模型(深度神经网络和循环神经网络)和“传统”的机器学习模型(支持向量机,随机森林,梯度提升决策树)相比,我觉得嵌入方法更适用于深度神经网络。
-The ‘traditional’ machine learning models rely on a tabular input that is feature engineered. This means that we, as researchers, decide what gets turned into a feature. In these cases features could be: amount of homepages visited, amount of searches done, total amount of pixels scrolled. However, it is very difficult to capture the spatial (time) dimension when doing feature-engineering. By using deep learning and embedding layers we can efficiently capture this spatial dimension by supplying a sequence of user behavior (as indices) as input for the model.
+“传统”的机器学习模型,非常依赖经过特征工程的表格式的输入,这意味着需要我们研究者来决定什么是一个特征。在我的那个项目里,作为特征的有:浏览的主页数量、搜索的次数、总共滚动的像素。然而,在特征工程时,我们很难把时间维度方面的特征考虑进去。利用深度学习和嵌入层,我们就能够把用户行为序列(通过索引)作为模型的输入,从而有效地捕捉到时间维度上的特征。
-In my research the Recurrent Neural Network with Gated Recurrent Unit/Long-Short Term Memory performed best. The results were very close. From the ‘traditional’ feature engineered models Gradient Boosted Trees performed best. I will write a blog post about this research in more detail in the future. I think my next blog post will explore Recurrent Neural Networks in more detail.
+在我的研究中,使用 GRU(Gated Recurrent Unit)或者是 LSTM(Long-Short Term Memory)技术的循环神经网络表现地最好,它们的结果很接近。在“传统” 的需要特征工程的模型中,梯度提升决策树表现地最好。关于我的研究项目,我以后会写一篇文章,我的下一篇文章会更细致地讨论关于循环神经网络的问题。
-Other research has explored the use of embedding layers to encode student behavior in MOOCs (Piech et al., 2016) and users’ path through an online fashion store (Tamhane et al., 2017).
+其他还有使用嵌入层来编码学生在慕课上行为的例子(Piech et al., 2016),以及用户浏览在线时尚商店的点击顺序(Tamhane et al., 2017)。
---
-#### Recommender Systems
+#### 推荐系统
-Embedding layers can even be used to deal with the sparse matrix problem in recommender systems. Since the deep learning course (fast.ai) uses recommender systems to introduce embedding layers I want to explore them here as well.
+嵌入层甚至可以用来处理推荐系统中的稀疏矩阵问题。在 fast.ai 的深度学习课程中利用推荐系统来介绍了嵌入层,这里我也想谈谈推荐系统。
-Recommender systems are being used everywhere and you are probably being influenced by them every day. The most common examples are Amazon’s product recommendation and Netflix’s program recommendation systems. Netflix actually held a $1,000,000 challenge to find the best collaborative filtering algorithm for their recommender system. You can see a visualization of one of these models [here](http://abeautifulwww.com/wp-content/uploads/2007/04/netflixAllMovies-blackBack3[5].jpg).
+推荐系统已经广泛地应用在各个领域了,你可能每天都被它们所影响着。亚马逊的产品推荐和 Netflix 的节目推荐系统,是两个最常见的例子。Netflix 举办了一个奖金为一百万美元的比赛,用来寻找最适合他们推荐系统的协同过滤算法。你可以在[这里](http://abeautifulwww.com/wp-content/uploads/2007/04/netflixAllMovies-blackBack3[5].jpg)看到其中一个模型的可视化结果。
-There are two main types of recommender systems and it is important to distinguish between the two.
+推荐系统主要有两种类型,区分它们是很重要的。
-1. Content-based filtering. This type of filtering is based on data about the item/product. For example, we have our users fill out a survey on what movies they like. If they say that they like sci-fi movies we recommend them sci-fi movies. In this case al lot of meta-information has to be available for all items.
-2. Collaborative filtering: Let’s find other people like you, see what they liked and assume you like the same things. People like you = people who rated movies that you watched in a similar way. In a large dataset this has proven to work a lot better than the meta-data approach. Essentially asking people about their behavior is less good compared to looking at their actual behavior. Discussing this further is something for the psychologists among us.
+1. 基于内容过滤:这种过滤是基于物品或者是产品的数据的。比如说,我们让用户填一份他们喜欢的电影的表格。如果他们说喜欢科幻电影,那么我们就给他推荐科幻电影。这种方法需要大量的对应产品的元数据。
+2. 协同过滤:找到和你相似的人,假设你们的爱好相同,看看他们喜欢什么。和你相似的人,意味着他们对你看过的电影有着相似的评价。在大数据集中,这个方法和元数据方法相比,效果更好。另外一点很重要的是,询问用户他们的行为和观察他们实际的行为之间是有出入的,这其中更深沉次的原因需要心理学家来解释。
-In order to solve this problem we can create a huge matrix of the ratings of all users against all movies. However, in many cases this will create an extremely sparse matrix. Just think of your Netflix account. What percentage of their total supply of series and movies have you watched? It’s probably a pretty small percentage. Then, through gradient descent we can train a neural network to predict how high each user would rate each movie. Let me know if you would like to know more about the use of deep learning in recommender systems and we can explore it further together. In conclusion, embedding layers are amazing and should not be overlooked.
+为了解决这个问题,我们可以创建一个巨大的所有用户对所有电影的评价矩阵。然而,在很多情况下,这个矩阵是非常稀疏的。想想你的 Netflix 账号,你看过的电影占他们全部电影的百分之多少?这可能是一个非常小的比例。创建矩阵之后,我们可以通过梯度下降算法训练我们的神经网络,来预测每个用户会给每部电影打多少分。如果你想知道更多关于在推荐系统中使用深度学习的话,请告诉我,我们可以一起来探讨更细节的问题。总而言之,嵌入层的作用是令人惊讶的,不可小觑。
-If you liked this posts be sure to recommend it so others can see it. You can also follow this profile to keep up with my process in the Fast AI course. See you there!
+如果你喜欢这篇文章,请把它推荐给你的朋友们,让更多人的看到它。你也可以按照这篇文章,跟上我在 Fast AI 课程中的进度。到时候那里见!
-#### References
+#### 参考文献
Piech, C., Bassen, J., Huang, J., Ganguli, S., Sahami, M., Guibas, L. J., & Sohl-Dickstein, J. (2015). *Deep knowledge tracing. In Advances in Neural Information Processing Systems* (pp. 505–513).
Tamhane, A., Arora, S., & Warrier, D. (2017, May). *Modeling Contextual Changes in User Behaviour in Fashion e-Commerce*. In Pacific-Asia Conference on Knowledge Discovery and Data Mining (pp. 539–550). Springer, Cham.
-
---
> [掘金翻译计划](https://github.com/xitu/gold-miner) 是一个翻译优质互联网技术文章的社区,文章来源为 [掘金](https://juejin.im) 上的英文分享文章。内容覆盖 [Android](https://github.com/xitu/gold-miner#android)、[iOS](https://github.com/xitu/gold-miner#ios)、[React](https://github.com/xitu/gold-miner#react)、[前端](https://github.com/xitu/gold-miner#前端)、[后端](https://github.com/xitu/gold-miner#后端)、[产品](https://github.com/xitu/gold-miner#产品)、[设计](https://github.com/xitu/gold-miner#设计) 等领域,想要查看更多优质译文请持续关注 [掘金翻译计划](https://github.com/xitu/gold-miner)。
diff --git a/TODO/embracing-java-8-language-features.md b/TODO/embracing-java-8-language-features.md
index a52b61a12e1..d53cf2e3083 100644
--- a/TODO/embracing-java-8-language-features.md
+++ b/TODO/embracing-java-8-language-features.md
@@ -3,20 +3,20 @@
> * 原文作者:[Jeroen Mols](https://jeroenmols.com/)
> * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
> * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO/embracing-java-8-language-features.md](https://github.com/xitu/gold-miner/blob/master/TODO/embracing-java-8-language-features.md)
-> * 译者:
-> * 校对者:
+> * 译者:[tanglie1993](https://github.com/tanglie1993)
+> * 校对者:[lileizhenshuai](https://github.com/lileizhenshuai), [DeadLion](https://github.com/DeadLion)
-# Embracing Java 8 language features
+# 拥抱 Java 8 语言特性
-For years Android developers have been limited to Java 6 features. While RetroLambda or the experimental Jack toolchain would help, proper support from Google was notably missing.
+近年来,Android 开发者一直被限制在 Java 6 的特性中。虽然 RetroLambda 或者实验性的 Jack toolchain 会有一定帮助,来自 Google 官方的适当支持却一直缺失。
-Finally, Android Studio 3.0 brings (backported!) support for most Java 8 features. Continue reading to learn how those work and why you should upgrade.
+终于, Android Studio 3.0 带来了(已经向后移植!)对大多数 Java 8 特性的支持。继续阅读,你将看到其中的原理,以及升级的理由。
-## Enabling java 8 features
+## 引入 Java 8 特性
-While Android Studio already supported many features in the [Jack toolchain](https://developer.android.com/guide/platform/j8-jack.html), starting from Android Studio 3.0 they are supported in the default toolchain.
+虽然 Android Studio 已经支持 [Jack toolchain](https://developer.android.com/guide/platform/j8-jack.html) 中的大量特性,从 Android Studio 3.0 开始,它们会在默认的工具链中被支持。
-First of all, make sure you disable Jack by removing the following from your main `build.gradle`:
+首先,确保你已经把以下内容从你的主要 `build.gradle` 中移除,从而关闭了 Jack:
```
android {
@@ -31,7 +31,7 @@ android {
}
```
-And add the following configuration instead:
+然后加入以下的配置:
```
android {
@@ -43,7 +43,7 @@ android {
}
```
-Also make sure you have the latest Gradle plugin in your root `build.gradle` file:
+并且确保你在根 `build.gradle` 文件中有最新的 Gradle 插件:
```
buildscript {
@@ -54,13 +54,13 @@ buildscript {
}
```
-Congratulations, you can now use most Java 8 features on all API levels!
+恭喜,你现在可以在所有的 API 层级上使用大多数的 Java 8 特性了!
-> Note: In case you’re migrating from [RetroLambda](https://github.com/evant/gradle-retrolambda), the official documentation has a more extensive [migration guide](https://developer.android.com/studio/write/java8-support.html#migrate).
+> 注意:如果你要从 [RetroLambda](https://github.com/evant/gradle-retrolambda) 迁移过来,官方文档有一个更加全面的 [迁移指南](https://developer.android.com/studio/write/java8-support.html#migrate)。
-## Lambda’s
+## 有关 Lambda 表达式
-Passing a listener to another class in Java 6 is quite verbose. A typical case would be where you add an `OnClickListener` to a `View`:
+在 Java 6 中,向另一个类传入监听器的代码是相当冗长的。典型的情况是,你需要向 `View` 添加一个 `OnClickListener`:
```
button.setOnClickListener(new View.OnClickListener() {
@@ -71,83 +71,85 @@ button.setOnClickListener(new View.OnClickListener() {
});
```
-Lambda’s can dramatically simplify this to the following:
+Lambda 表达式可以把它显著地简化成下面这样:
```
button.setOnClickListener(view -> doSomething());
```
-Notice that almost all boilerplate is removed: no access modifier, no return type and no method name!
+注意:几乎全部模板代码都被删除了:没有访问控制修饰符,没有返回值,也没有方法名称!
-Now how do lambda’s actually work?
+Lambda 表达式究竟是怎么工作的呢?
-They are syntactic sugar that reduce the need for anonymous class creation whenever you have an interface with exactly one method. We call such interfaces functional interfaces and `OnClickListener` is an example:
+它们是语法糖,当你有一个只有一个方法的接口时,它们可以减少创建匿名类的需要。我们把这些接口称为功能接口,`OnClickListener` 就是一个例子:
```
-// A functional interface has exactly one method
+// 只有一个方法的功能接口
public interface OnClickListener {
void onClick(View view);
}
```
-Basically the lambda consists out of a three parts:
+基本上 lambda 表达式包括三个部分:
```
button.setOnClickListener((view) -> {doSomething()});
```
-1. declaration of all method arguments between brackets `()`
-2. an arrow `->`
-3. code that needs to execute between brackets `{}`
+1. 括号 `()` 中所有方法参数的声明
+2. 一个箭头 `->`
+3. 括号 `{}` 中需要执行的代码
-Note that in many cases even the brackets `()` and `{}` can be removed. For more details have a look at the [official documentation](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html).
+注意:在很多情况下,甚至 `()` 和 `{}` 这样的括号也可以被移除。更多细节,参见 [官方文档](https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html)。
-## Method references
+## 方法引用
-Recall that lambda expressions remove a lot of boilerplate code for functional interfaces. Method references take that concept one step further when the lambda calls a method that already has a name.
+回忆一下 lambda 表达式为功能接口删除了大量样板代码的情形。当 lambda 表达式调用了一个已经有名字的方法时,方法引用把这个概念更推进了一步。
-In the following example:
+在下面的例子中:
```
button.setOnClickListener(view -> doSomething(view));
```
-All the lambda does is redirecting the work to an existing `doSomething()` method. In such a case, a method reference simplifies things further to:
+Lambda 只是把要做的所有事情重定向到已有的 `doSomething()` 方法。在这种情况下,方法引用把事情简化到:
```
button.setOnClickListener(this::doSomething);
```
-Note that the referenced method must take exactly the same parameters as the functional interface:
+注意,被引用的方法必须和功能接口接收相同的参数:
```
-// functional interface
+// 功能接口
public interface OnClickListener {
void onClick(View view);
}
-// referenced method: must take View as argument, because onClick() does
+// 被引用的方法:必须接收 View 作为参数,因为 onClick() 会这样做:
private void doSomething(View view) {
// do something here
}
```
-So how do method references work?
+那么,方法引用是如何工作的呢?
-They are again syntactic sugar to simplify a lambda expression that invokes an existing method. They can reference to:
+它们同样是语法糖,可以简化调用了现有方法的 lambda 表达式。他们可以引用:
-| static methods | MyClass::doSomething |
-| instance method of object | myObject::doSomething |
-| constructor | MyClass:: new |
-| instance method of any argument type | String::compare |
+| | |
+| - | - |
+| 静态方法 | MyClass::doSomething |
+| 对象的实例方法 | myObject::doSomething |
+| 构造方法 | MyClass:: new |
+| 任何参数类型的实例方法 | String::compare |
-For more examples about this have a look at the [official documentation](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html).
+如果你需要更多关于这个的实例,请查看 [官方文档](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html)。
-## Default interface Methods
+## 默认接口方法
-Default methods make it possible to add new methods to an interface without breaking all classes that implement that interface.
+默认方法使你可以在不破坏实现一个接口的所有的类的情况下,向该接口中加入新的方法。
-Imagine if you have a `MyView` interface that is implemented by a `MyFragment` (typical MVP scenario):
+假设你有一个 `MyView` 接口,它被一个 `MyFragment` 实现(典型 MVP 场景):
```
public interface MyView {
@@ -163,9 +165,9 @@ public class MyFragment implements MyView {
}
```
-When you now want to add an extra method to `MyView` your code will no longer compile, until `MyFragment` also implements that new method. This is annoying, and can be even problematic when many classes are implementing said interface.
+如果你现在想要向 MyView 中加入一个额外的方法,你的代码将不再能够编译,直到 `MyFragment` 同样实现了这个新方法。这很烦人,并且如果很多类都实现这个接口的话,可能会引发新的问题。
-Therefore Java 8 now allows you to define default methods that provide a standard implementation:
+因此 Java 8 允许你定义带有标准实现的默认方法:
```
public interface MyView {
@@ -176,37 +178,37 @@ public interface MyView {
}
```
-So how do default methods work?
+那么默认方法是如何工作的呢?
-Just define a method with the `default` keyword in the interface and provide an actual default method body.
+在接口中定义一个带有 `default` 关键字的方法,并提供一个真实的默认方法体。
-To learn more about this feature, have a look at the [official documentation](https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html).
+要学习关于这个特性的更多知识,请查看 [官方文档](https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html)。
-## How to get started
+## 如何开始
-While this all might seem a bit overwhelming, Android Studio actually offers amazing quick fixes once you enable Java 8 features.
+虽然这看起来有些吓人,但是一旦你打开了 Java 8 特性,Android Studio 就提供了非常好用的快速修复功能。
-Just use `alt/option` + `enter` to convert a functional interface to a lamba or a lambda to a method reference.
+只要使用 `alt/option` + `enter` 就可以把功能接口转化为一个 lambda 表达式,或把 lambda 转为方法引用。
-![Java 8 language quick fixes](https://jeroenmols.com/img/blog/java8language/androidstudioconversion.gif)
+![Java 8 语言的快速修复功能](https://jeroenmols.com/img/blog/java8language/androidstudioconversion.gif)
-This is a great way to get familiar with these new features and allows you to write code like you’re used to. After enough quick fixes by Android Studio you’ll learn in what cases a lambda or method reference would be possible and start writing them yourself.
+这是一种熟悉新特性的好办法,它使你可以按照自己习惯的方式写代码。在使用 Android Studio 的快速修复功能足够多次之后,你将学会 lambda 表达式和方法引用有哪些使用场景,并开始自己写它们。
-## Supported features
+## 支持的特性
-While not all Java 8 features have been backported yet, Android Studio 3.0 offers plenty more features:
+虽然并不是所有的 Java 8 特性都已经被向后移植,但是Android Studio 3.0 提供了很多其他的特性:
-- [static interface methods](https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html)
-- [type annotations](https://docs.oracle.com/javase/tutorial/java/annotations/type_annotations.html)
-- [repeating annotations](https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html)
-- [try with resources](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) (all versions, no longer min SDK 19)
+- [静态接口方法](https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html)
+- [类型注解](https://docs.oracle.com/javase/tutorial/java/annotations/type_annotations.html)
+- [重复标记](https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html)
+- [针对资源的 try 语句](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) (所有版本,最低版本不再是 SDK 19)
- Java 8 APIs (e.g. stream) -> min SDK 24
-## Wrap-up
+## 收尾
-Thanks to Java 8 features, a lot of code can be simplified into lambda’s or method references. Android Studio auto convert is the easiest way to start learning these features.
+Java 8 特性使得很多代码可以被简化为 lambda 表达式或方法引用。 Android Studio 自动转化是最简单的开始学习这些特性的方式。
-If you’ve made it this far, you should probably follow me on [Twitter](https://twitter.com/molsjeroen). Feel free leave a comment below!
+如果你已经读到这里了,你很可能应该在 [Twitter](https://twitter.com/molsjeroen) 上关注我。欢迎评论!
---
diff --git a/TODO/how-chat-bots-work.md b/TODO/how-chat-bots-work.md
index f3d356f67e0..5fafe6aaf88 100644
--- a/TODO/how-chat-bots-work.md
+++ b/TODO/how-chat-bots-work.md
@@ -1,60 +1,61 @@
- > * 原文地址:[Soul of the Machine: How Chatbots Work](https://medium.com/@gk_/how-chat-bots-work-dfff656a35e2)
- > * 原文作者:[George Kassabgi](https://medium.com/@gk_)
- > * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
- > * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO/how-chat-bots-work.md](https://github.com/xitu/gold-miner/blob/master/TODO/how-chat-bots-work.md)
- > * 译者:
- > * 校对者:
+> * 原文地址:[Soul of the Machine: How Chatbots Work](https://medium.com/@gk_/how-chat-bots-work-dfff656a35e2)
+> * 原文作者:[George Kassabgi](https://medium.com/@gk_)
+> * 译文出自:[掘金翻译计划](https://github.com/xitu/gold-miner)
+> * 本文永久链接:[https://github.com/xitu/gold-miner/blob/master/TODO/how-chat-bots-work.md](https://github.com/xitu/gold-miner/blob/master/TODO/how-chat-bots-work.md)
+> * 译者:[lsvih](https://github.com/lsvih)
+> * 校对者:[lileizhenshuai](https://github.com/lileizhenshuai),[jasonxia23](https://github.com/jasonxia23)
- # Soul of the Machine: How Chatbots Work
+# 机器之魂:聊天机器人是怎么工作的
![](https://cdn-images-1.medium.com/max/2000/1*HRgcOpW8vSPqM-GxkoHhWw.jpeg)
-Since the early industrial age, we’ve been fascinated by self-operating devices. They represent the humanization of technology.
+自早期的工业时代以来,人类就被能自主操作的设备迷住了。因为,它们代表了科技的“人化”。
-Today, it is software that that’s becoming more human — most obviously “chatbots.”
+而在今天,各种软件也在逐渐变得人性化。其中变化最明显的当属“聊天机器人”。
-But how do these machines work? First, wind back time and explore an earlier — yet similar — technology.
+但是这些“机械”是如何运作的呢?首先,让我们回溯过去,探寻一种原始,但相似的技术。
-### How a music box works
+### 音乐盒是如何工作的
![](https://cdn-images-1.medium.com/max/1600/1*PveiqDdv2Zsog9ryJTUz-Q.png)
-An early example of automation — the mechanical music box.
-A set of tuned metallic teeth aligned on a comb-like structure are positioned next to a cylinder with pins. Each pin corresponds to a note at a specific interval.
+早期自动化的样例 —— 机械音乐盒。
+一组经过调音的金属齿排列成梳状结构,置于一个有针的圆柱边上。每根针都以一个特定的时间对应着一个音符。
-As the mechanism turns, it creates a tune by striking one or multiple pins at the predefined time. To play a different song, you can swap in a different cylindrical drum (assuming the set of unique notes is equivalent).
+当机械转动时,它便会在预定好的时间通过单个或者多个针的拨动来产生乐曲。如果要播放不同的歌,你得换不同的圆柱桶(假设不同的乐曲对应的特定音符是一样的)。
-In addition to striking a note, the movement of the drum can cause other automation, such as a moving figurine. Either way, the fundamental machinery of the music box remains the same.
+除了发出音符之外,圆筒的转动还可以附加一些其它的动作,例如移动小雕像等。不管怎样,这个音乐盒的基本机械结构是不会变的。
-### How a chatbot works
+### 聊天机器人是如何工作的
-Text input is processed by a software function called a “classifier”, this classification associates an input sentence with an “intent” (a conversational intent) which produces a response.
+输入的文本将经过一种名为“分类器”的函数处理,这种分类器会将一个输入的句子和一种“意图”(聊天的目的)联系起来,然后针对这种“意图”产生回应。
![](https://cdn-images-1.medium.com/max/1600/1*aSGRi9NOM3J5vT2fMlo5ig.png)
-[a chatbot example (http://lauragelston.ghost.io/speakeasy/](http://lauragelston.ghost.io/speakeasy/))
-Think of a classifier as a way of categorizing a piece of data (a sentence) into one of several categories (an intent). The input “how are you?” is classified as an intent, which is associated with a response such as “I’m good” or (better) “I am well.”
+[一个聊天机器人的例子](http://lauragelston.ghost.io/speakeasy/)
-We learned about classification early in elementary science: a chimpanzee is in the class “mammals”, a blue jay is in the class “birds”, the earth is in the class “planets” and so on. Simple.
+你可以将分类器看成是将一段数据(一句话)分入几个分类中的一种(即某种意图)的一种方式。输入一句话“how are you?”,将被分类成一种意图,然后将其与一种回应(例如“I’m good”或者更好的“I am well”)联系起来。
-Generally speaking, there are 3 different kinds of text classifiers. Think of these as software machinery, built for a specific purpose, like the drum of a music box.
+我们在基础科学中早学习了分类:黑猩猩属于“哺乳动物”类,蓝鸟属于“鸟”类,地球属于“行星”等等。
-### **Chatbot text classification approaches**
+一般来说,文本分类有 3 种不同的方法。可以将它们看做是为了一些特定目的制造的软件机械,就如同音乐盒的圆筒一样。
-- **Pattern matchers**
-- **Algorithms**
-- **Neural networks**
+### **聊天机器人的文本分类方法**
-Regardless of which type of classifier is used, the end-result is a response. Like a music box, there can be additional “movements” associated with the machinery. A response can make use of external information (like weather, a sports score, a web lookup, etc.) but this isn’t specific to chatbots, it’s just additional code. A response may reference specific “parts of speech” in the sentence, for example: a proper noun. Also the response (for an intent) can use conditional logic to provide different responses depending on the “state” of the conversation, this can be a random selection (to insert some ‘natural’ feeling).
+- **模式匹配**
+- **算法**
+- **神经网络**
-### Pattern matchers
+无论你使用哪种分类器,最终的结果一定是给出一个回应。音乐盒可以利用一些机械机构的联系来完成一些额外的“动作”,聊天机器人也如此。回应中可以使用一些额外的信息(例如天气、体育比赛比分、网络搜索等等),但是这些信息并不是聊天机器人的组成部分,它们仅仅是一些额外的代码。也可以根据句子中的某些特定“词性”来产生回应(例如某个专有名词)。此外,符合意图的回应也可以使用逻辑条件来判断对话的“状态”,以提供一些不同的回应,这也可以通过随机选择实现(好让对话更加“自然”)。
-Early chatbots used pattern matching to classify text and produce a response. This is often referred to as “brute force” as the author of the system needs to describe every pattern for which there is a response.
+### 模式匹配
-A standard structure for these patterns is “AIML” (artificial intelligence markup language). Its use of the term “artificial intelligence” is quite an embellishment, but [that’s another story](https://medium.com/@gk_/the-ai-label-is-bullshit-559b171867ff).
+早期的聊天机器人通过模式匹配来进行文本分类以及产生回应。这种方法常常被称为“暴力法”,因为系统的作者需要为某个回应详细描述所有模式。
-A simple pattern matching definition:
+这些模式的标准结构是“AIML”(人工智能标记语言)。这个名词里用了“人工智能”作为修饰词,但是[它们完全不是一码事](https://medium.com/@gk_/the-ai-label-is-bullshit-559b171867ff)。
+
+下面是一个简单的模式匹配定义:
```