From 4273de5699d59b9e4943342ba9e18c4d15fbee3b Mon Sep 17 00:00:00 2001
From: Eugene Yokota <eed3si9n@gmail.com>
Date: Sat, 21 Sep 2019 19:17:58 -0400
Subject: [PATCH 1/3] drop build loader

build loader is no longer available.
Fixes https://github.com/sbt/website/issues/571
---
 .../10-DevGuide-Notes/04-Build-Loaders.md     | 283 ------------------
 1 file changed, 283 deletions(-)
 delete mode 100644 src/reference/90-Developers-Guide/10-DevGuide-Notes/04-Build-Loaders.md

diff --git a/src/reference/90-Developers-Guide/10-DevGuide-Notes/04-Build-Loaders.md b/src/reference/90-Developers-Guide/10-DevGuide-Notes/04-Build-Loaders.md
deleted file mode 100644
index 897022534..000000000
--- a/src/reference/90-Developers-Guide/10-DevGuide-Notes/04-Build-Loaders.md
+++ /dev/null
@@ -1,283 +0,0 @@
----
-out: Build-Loaders.html
----
-
-Build Loaders
--------------
-
-Build loaders are the means by which sbt resolves, builds, and
-transforms build definitions. Each aspect of loading may be customized
-for special applications. Customizations are specified by overriding the
-*buildLoaders* methods of your build definition's Build object. These
-customizations apply to external projects loaded by the build, but not
-the (already loaded) Build in which they are defined. Also documented on
-this page is how to manipulate inter-project dependencies from a
-setting.
-
-### Custom Resolver
-
-The first type of customization introduces a new resolver. A resolver
-provides support for taking a build URI and retrieving it to a local
-directory on the filesystem. For example, the built-in resolver can
-checkout a build using git based on a git URI, use a build in an
-existing local directory, or download and extract a build packaged in a
-jar file. A resolver has type:
-
-```scala
-ResolveInfo => Option[() => File]
-```
-
-The resolver should return None if it cannot handle the URI or Some
-containing a function that will retrieve the build. The ResolveInfo
-provides a staging directory that can be used or the resolver can
-determine its own target directory. Whichever is used, it should be
-returned by the loading function. A resolver is registered by passing it
-to *BuildLoader.resolve* and overriding *Build.buildLoaders* with the
-result:
-
-```scala
-...
-object Demo extends Build {
-  ...
-  override def buildLoaders =
-    BuildLoader.resolve(demoResolver) ::
-    Nil
-
-  def demoResolver: BuildLoader.ResolveInfo => Option[() => File] = ...
-
-}
-```
-
-#### API Documentation
-
-Relevant API documentation for custom resolvers:
-
--   [ResolveInfo](../api/sbt/internal/BuildLoader\$\$ResolveInfo.html)
--   [BuildLoader](../api/sbt/internal/BuildLoader\$.html)
-
-#### Full Example
-
-```scala
-import sbt._
-import Keys._
-
-object Demo extends Build
-{
-  // Define a project that depends on an external project with a custom URI
-  lazy val root = Project("root", file(".")).dependsOn(
-    uri("demo:a")
-  )
-
-  // Register the custom resolver
-  override def buildLoaders =
-    BuildLoader.resolve(demoResolver) ::
-    Nil
-
-  // Define the custom resolver, which handles the 'demo' scheme.
-  // The resolver's job is to produce a directory containing the project to load.
-  // A subdirectory of info.staging can be used to create new local
-  //   directories, such as when doing 'git clone ...'
-  def demoResolver(info: BuildLoader.ResolveInfo): Option[() => File] =
-    if(info.uri.getScheme != "demo")
-      None
-    else
-    {
-      // Use a subdirectory of the staging directory for the new local build.
-      // The subdirectory name is derived from a hash of the URI,
-      //   and so identical URIs will resolve to the same directory (as desired).
-      val base = RetrieveUnit.temporary(info.staging, info.uri)
-
-      // Return a closure that will do the actual resolution when requested.
-      Some(() => resolveDemo(base, info.uri.getSchemeSpecificPart))
-    }
-
-  // Construct a sample project on the fly with the name specified in the URI.
-  def resolveDemo(base: File, ssp: String): File =
-  {
-    // Only create the project if it hasn't already been created.
-    if(!base.exists)
-      IO.write(base / "build.sbt", template.format(ssp))
-    base
-  }
-
-  def template =  """
-name := "%s"
-
-version := "1.0"
-"""
-}
-```
-
-### Custom Builder
-
-Once a project is resolved, it needs to be built and then presented to
-sbt as an instance of `sbt.BuildUnit`. A custom builder has type:
-
-```scala
-BuildInfo => Option[() => BuildUnit] 
-```
-
-A builder returns None if it does not want to handle the build
-identified by the `BuildInfo`. Otherwise, it provides a function that
-will load the build when evaluated. Register a builder by passing it to
-*BuildLoader.build* and overriding *Build.buildLoaders* with the result:
-
-```scala
-...
-object Demo extends Build {
-  ...
-  override def buildLoaders =
-    BuildLoader.build(demoBuilder) ::
-    Nil
-
-  def demoBuilder: BuildLoader.BuildInfo => Option[() => BuildUnit] = ...
-
-}
-```
-
-#### API Documentation
-
-Relevant API documentation for custom builders:
-
--   [BuildInfo](../api/sbt/internal/BuildLoader\$\$BuildInfo.html)
--   [BuildLoader](../api/sbt/internal/BuildLoader\$.html)
--   [BuildUnit](../api/sbt/internal/BuildUnit.html)
-
-#### Example
-
-This example demonstrates the structure of how a custom builder could
-read configuration from a pom.xml instead of the standard .sbt files and
-project/ directory.
-
-```scala
-... imports ...
-
-object Demo extends Build
-{
-  lazy val root = Project("root", file(".")) dependsOn( file("basic-pom-project") )
-
-  override def buildLoaders =
-    BuildLoader.build(demoBuilder) ::
-    Nil
-
-  def demoBuilder: BuildInfo => Option[() => BuildUnit] = info =>
-    if(pomFile(info).exists)
-      Some(() => pomBuild(info))
-    else
-      None
-
-  def pomBuild(info: BuildInfo): BuildUnit =
-  {
-    val pom = pomFile(info)
-    val model = readPom(pom)
-
-    val n = Project.normalizeProjectID(model.getName)
-    val base = Option(model.getProjectDirectory) getOrElse info.base
-    val root = Project(n, base) settings( pomSettings(model) )
-    val build = new Build { override def projects = Seq(root) }
-    val loader = this.getClass.getClassLoader
-    val definitions = new LoadedDefinitions(info.base, Nil, loader, build :: Nil, Nil)
-    val plugins = new LoadedPlugins(info.base / "project", Nil, loader, Nil, Nil)
-    new BuildUnit(info.uri, info.base, definitions, plugins)
-  }
-
-  def readPom(file: File): Model = ...
-  def pomSettings(m: Model): Seq[Setting[_]] = ...
-  def pomFile(info: BuildInfo): File = info.base / "pom.xml"
-```
-
-### Custom Transformer
-
-Once a project has been loaded into an `sbt.BuildUnit`, it is
-transformed by all registered transformers. A custom transformer has
-type:
-
-```scala
-TransformInfo => BuildUnit
-```
-
-A transformer is registered by passing it to *BuildLoader.transform* and
-overriding *Build.buildLoaders* with the result:
-
-```scala
-...
-object Demo extends Build {
-  ...
-  override def buildLoaders =
-    BuildLoader.transform(demoTransformer) ::
-    Nil
-
-  def demoTransformer: BuildLoader.TransformInfo => BuildUnit = ...
-
-}
-```
-
-#### API Documentation
-
-Relevant API documentation for custom transformers:
-
--   [TransformInfo](../api/sbt/internal/BuildLoader\$\$TransformInfo.html)
--   [BuildLoader](../api/sbt/internal/BuildLoader\$.html)
--   [BuildUnit](../api/sbt/internal/BuildUnit.html)
-
-##### Manipulating Project Dependencies in Settings
-
-The `buildDependencies` setting, in the Global scope, defines the
-aggregation and classpath dependencies between projects. By default,
-this information comes from the dependencies defined by `Project`
-instances by the `aggregate` and `dependsOn` methods. Because
-`buildDependencies` is a setting and is used everywhere dependencies
-need to be known (once all projects are loaded), plugins and build
-definitions can transform it to manipulate inter-project dependencies at
-setting evaluation time. The only requirement is that no new projects
-are introduced because all projects are loaded before settings get
-evaluated. That is, all Projects must have been declared directly in a
-Build or referenced as the argument to `Project.aggregate` or
-`Project.dependsOn`.
-
-### The BuildDependencies type
-
-The type of the `buildDependencies` setting is
-[BuildDependencies](../api/sbt/internal/BuildDependencies.html).
-`BuildDependencies` provides mappings from a project to its aggregate or
-classpath dependencies. For classpath dependencies, a dependency has
-type `ClasspathDep[ProjectRef]`, which combines a `ProjectRef` with a
-configuration (see [ClasspathDep](../api/sbt/ClasspathDep.html)
-and [ProjectRef](../api/sbt/ProjectRef.html)). For aggregate
-dependencies, the type of a dependency is just `ProjectRef`.
-
-The API for `BuildDependencies` is not extensive, covering only a little
-more than the minimum required, and related APIs have more of an
-internal, unpolished feel. Most manipulations consist of modifying the
-relevant map (classpath or aggregate) manually and creating a new
-`BuildDependencies` instance.
-
-#### Example
-
-As an example, the following replaces a reference to a specific build
-URI with a new URI. This could be used to translate all references to a
-certain git repository to a different one or to a different mechanism,
-like a local directory.
-
-```scala
-buildDependencies in Global := {
-  val deps = (buildDependencies in Global).value
-  val oldURI = uri("...") // the URI to replace
-  val newURI = uri("...") // the URI replacing oldURI
-  def substitute(dep: ClasspathDep[ProjectRef]): ClasspathDep[ProjectRef] =
-    if(dep.project.build == oldURI)
-      ResolvedClasspathDependency(ProjectRef(newURI, dep.project.project), dep.configuration)
-    else
-      dep
-  val newcp = 
-    for( (proj, deps) <- deps.cp) yield
-      (proj, deps map substitute)
-  BuildDependencies(newcp, deps.aggregate)
-}
-```
-
-It is not limited to such basic translations, however. The configuration
-a dependency is defined in may be modified and dependencies may be added
-or removed. Modifying `buildDependencies` can be combined with modifying
-`libraryDependencies` to convert binary dependencies to and from source
-dependencies, for example.

From 1de2a0b6924459f9a97c617751253c315fbe91fa Mon Sep 17 00:00:00 2001
From: Eugene Yokota <eed3si9n@gmail.com>
Date: Sat, 21 Sep 2019 19:21:19 -0400
Subject: [PATCH 2/3] Fix link

Fixes https://github.com/sbt/website/issues/815
---
 .../02-DetailTopics/04-Tasks-and-Commands/01a-Caching.md        | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/reference/02-DetailTopics/04-Tasks-and-Commands/01a-Caching.md b/src/reference/02-DetailTopics/04-Tasks-and-Commands/01a-Caching.md
index 22c9865a3..e18b0fc3c 100644
--- a/src/reference/02-DetailTopics/04-Tasks-and-Commands/01a-Caching.md
+++ b/src/reference/02-DetailTopics/04-Tasks-and-Commands/01a-Caching.md
@@ -3,7 +3,7 @@ out: Caching.html
 ---
 
   [Basic-Def]: Basic-Def.html
-  [Task]: Task.html
+  [Tasks]: Tasks.html
 
 Caching
 -------

From a239e75183f7cfd81c4918d232de52e4a31777f7 Mon Sep 17 00:00:00 2001
From: Eugene Yokota <eed3si9n@gmail.com>
Date: Sat, 21 Sep 2019 20:23:54 -0400
Subject: [PATCH 3/3] Update Linux installaiton steps

Fixes https://github.com/sbt/sbt/issues/4261
Fixes https://github.com/sbt/website/issues/799

Ideally

```
sudo apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
```

should just work. but Ubuntu Bionic (18.04) uses gpg 2.2.4 that does not contain the fix mentioned in https://github.com/microsoft/WSL/issues/3286, and thus end up with

```
gpg: connecting dirmngr at '/tmp/apt-key-gpghome.BG01sRSmD5/S.dirmngr' failed: IPC connect call failed
gpg: keyserver receive failed: No dirmngr
```
---
 src/nanoc/content/download.html               |  2 +-
 .../00-Getting-Started/01-Setup/c.md          | 26 ++++++++++++++-----
 .../es/00-Getting-Started/01-Setup/c.md       | 23 ++++++++++++----
 .../ja/00-Getting-Started/01-Setup/c.md       | 24 ++++++++++++-----
 .../zh-cn/00-Getting-Started/01-Setup/c.md    | 16 +++++++++++-
 5 files changed, 71 insertions(+), 20 deletions(-)

diff --git a/src/nanoc/content/download.html b/src/nanoc/content/download.html
index 87a559623..e4f15b555 100644
--- a/src/nanoc/content/download.html
+++ b/src/nanoc/content/download.html
@@ -34,7 +34,7 @@ <h3>Scoop</h3>
   	<h2>Linux (deb)</h2>
 <pre>
 echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
-sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
+curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add
 sudo apt-get update
 sudo apt-get install sbt
 </pre>
diff --git a/src/reference/00-Getting-Started/01-Setup/c.md b/src/reference/00-Getting-Started/01-Setup/c.md
index 0bd71fc2c..ce7ff5a0a 100644
--- a/src/reference/00-Getting-Started/01-Setup/c.md
+++ b/src/reference/00-Getting-Started/01-Setup/c.md
@@ -13,17 +13,29 @@ out: Installing-sbt-on-Linux.html
 Installing sbt on Linux
 -----------------------
 
-### Installing from a universal package
+### Installing from SDKMAN
 
-Download [ZIP][ZIP] or [TGZ][TGZ] package and expand it.
+To install both JDK and sbt, consider using [SDKMAN](https://sdkman.io/).
+
+```
+\$ sdk list java
+\$ sdk install java 11.0.4.hs-adpt
+\$ sdk install sbt
+```
+
+This has two advantages.
+1. It will install the official packaging by AdoptOpenJDK, as opposed to the ["mystery meat OpenJDK builds"](https://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-May/009330.html).
+2. It will install `tgz` packaging of sbt that contains all JAR files. (DEB and RPM packages do not to save bandwidth)
 
 ### Install JDK
 
-You must first install a JDK. We recommend AdoptOpenJDK JDK 8 or JDK 11. The details around the package names differ from one distribution to another.
+You must first install a JDK. We recommend **AdoptOpenJDK JDK 8** or **JDK 11**.
 
-For example, Ubuntu xenial (16.04LTS) has [openjdk-8-jdk](https://packages.ubuntu.com/hu/xenial/openjdk-8-jdk).
+The details around the package names differ from one distribution to another. For example, Ubuntu xenial (16.04LTS) has [openjdk-8-jdk](https://packages.ubuntu.com/hu/xenial/openjdk-8-jdk). Redhat family calls it [java-1.8.0-openjdk-devel](https://apps.fedoraproject.org/packages/java-1.8.0-openjdk-devel).
 
-Redhat family calls it [java-1.8.0-openjdk-devel](https://apps.fedoraproject.org/packages/java-1.8.0-openjdk-devel).
+### Installing from a universal package
+
+Download [ZIP][ZIP] or [TGZ][TGZ] package and expand it.
 
 ### Ubuntu and other Debian-based distributions
 
@@ -33,7 +45,7 @@ Ubuntu and other Debian-based distributions use the DEB format, but usually you
 Run the following from the terminal to install `sbt` (You'll need superuser privileges to do so, hence the `sudo`).
 
     echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
-    sudo apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
+    curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add
     sudo apt-get update
     sudo apt-get install sbt
 
@@ -45,6 +57,8 @@ Once `sbt` is installed, you'll be able to manage the package in `aptitude` or S
 
 **Note**: There's been reports about SSL error using Ubuntu: `Server access Error: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty url=https://repo1.maven.org/maven2/org/scala-sbt/sbt/1.1.0/sbt-1.1.0.pom`, which apparently stems from OpenJDK 9 using PKCS12 format for `/etc/ssl/certs/java/cacerts` [cert-bug][cert-bug]. According to <https://stackoverflow.com/a/50103533/3827> it is fixed in Ubuntu Cosmic (18.10), but Ubuntu Bionic LTS (18.04) is still waiting for a release. See the answer for a woraround.
 
+**Note**: `sudo apt-key adv --keyserver hkps://keyserver.ubuntu.com:443 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823` may not work on Ubuntu Bionic LTS (18.04) since it's using a buggy GnuPG, so we are advising to use web API to download the public key in the above.
+
 ### Red Hat Enterprise Linux and other RPM-based distributions
 
 [RPM][RPM] package is officially supported by sbt.
diff --git a/src/reference/es/00-Getting-Started/01-Setup/c.md b/src/reference/es/00-Getting-Started/01-Setup/c.md
index 83eb3954d..c5855920d 100644
--- a/src/reference/es/00-Getting-Started/01-Setup/c.md
+++ b/src/reference/es/00-Getting-Started/01-Setup/c.md
@@ -13,21 +13,34 @@ out: Installing-sbt-on-Linux.html
 Installing sbt on Linux
 -----------------------
 
-### Instalar desde un paquete universal
+### Installing from SDKMAN
 
-Descarga el paquete [ZIP][ZIP] o [TGZ][TGZ] y descomprímelo.
+To install both JDK and sbt, consider using [SDKMAN](https://sdkman.io/).
+
+```
+\$ sdk list java
+\$ sdk install java 11.0.4.hs-adpt
+\$ sdk install sbt
+```
+
+This has two advantages.
+1. It will install the official packaging by AdoptOpenJDK, as opposed to the ["mystery meat OpenJDK builds"](https://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-May/009330.html).
+2. It will install `tgz` packaging of sbt that contains all JAR files. (DEB and RPM packages do not to save bandwidth)
 
 ### Instalar JDK
 
 Primero desberás de instalar JDK. Recomendamos AdoptOpenJDK JDK 8 u AdoptOpenJDK JDK 11.
-Los detalles sobre el nombre de los paquetes cambian de una distribución a otra.
 
+Los detalles sobre el nombre de los paquetes cambian de una distribución a otra.
 Por ejemplo, Ubuntu xenial (16.04LTS) usa
 [openjdk-8-jdk](https://packages.ubuntu.com/hu/xenial/openjdk-8-jdk).
-
 La familia Redhat lo llama
 [java-1.8.0-openjdk-devel](https://apps.fedoraproject.org/packages/java-1.8.0-openjdk-devel).
 
+### Instalar desde un paquete universal
+
+Descarga el paquete [ZIP][ZIP] o [TGZ][TGZ] y descomprímelo.
+
 ### Ubuntu y otras distribuciones basadas en Debian
 
 Los paquetes [DEB][DEB] son oficialmente soportados por sbt.
@@ -41,7 +54,7 @@ Ejecuta lo siguiente desde el terminal para instalar `sbt`
 (necesitarás tener privilegios de administrador para hacerlo, de ahí el `sudo`).
 
     echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
-    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
+    curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add
     sudo apt-get update
     sudo apt-get install sbt
 
diff --git a/src/reference/ja/00-Getting-Started/01-Setup/c.md b/src/reference/ja/00-Getting-Started/01-Setup/c.md
index 980104849..68de311c7 100644
--- a/src/reference/ja/00-Getting-Started/01-Setup/c.md
+++ b/src/reference/ja/00-Getting-Started/01-Setup/c.md
@@ -13,13 +13,25 @@ out: Installing-sbt-on-Linux.html
 Linux への sbt のインストール
 --------------------------
 
-### JDK のインストール
+### SDKMAN からのインストール
+
+JDK と sbt をするのに、[SDKMAN](https://sdkman.io/) の導入を検討してほしい。
+
+```
+\$ sdk list java
+\$ sdk install java 11.0.4.hs-adpt
+\$ sdk install sbt
+```
 
-まず JDK をインストールする必要がある。AdoptOpenJDK JDK 8 もしくは AdoptOpenJDK JDK 11 を推奨する。パッケージ名はディストリビューションによって異なる。
+この方法は 2つの利点がある。
+1. [「闇鍋 OpenJDK ビルド」](https://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-May/009330.html)と揶揄されているディストロ管理の JDK ではなく、AdoptOpenJDK が出している公式のパッケージをインストールできる。
+2. sbt の全ての JAR ファイルを含んだ `tgz` パッケージをインストールできる (DEB と RPM版は帯域の節約のために JAR ファイルが含まれていない)。
 
-例えば、Ubuntu xenial (16.04LTS) には [openjdk-8-jdk](https://packages.ubuntu.com/hu/xenial/openjdk-8-jdk) がある。
+### JDK のインストール
+
+まず JDK をインストールする必要がある。AdoptOpenJDK JDK 8 もしくは AdoptOpenJDK JDK 11 を推奨する。
 
-Redhat 系は [java-1.8.0-openjdk-devel](https://apps.fedoraproject.org/packages/java-1.8.0-openjdk-devel) と呼んでいる。
+パッケージ名はディストリビューションによって異なる。例えば、Ubuntu xenial (16.04LTS) には [openjdk-8-jdk](https://packages.ubuntu.com/hu/xenial/openjdk-8-jdk) がある。Redhat 系は [java-1.8.0-openjdk-devel](https://apps.fedoraproject.org/packages/java-1.8.0-openjdk-devel) と呼んでいる。
 
 ### ユニバーサルパッケージからのインストール
 
@@ -36,7 +48,7 @@ Ubuntu 及びその他の Debian ベースのディストリビューション
 ターミナル上から以下を実行すると `sbt` をインストールできる (superuser 権限を必要とするため、`sudo` を使っている)。
 
     echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
-    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
+    curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add
     sudo apt-get update
     sudo apt-get install sbt
 
@@ -44,8 +56,6 @@ Ubuntu 及びその他の Debian ベースのディストリビューション
 sbt のバイナリは Bintray にて公開されており、都合の良いことに Bintray は APT リポジトリを提供している。
 そのため、このリポジトリをパッケージ・マネージャに追加しさえすればよい。
 
->**注意** [sbt/website#127][website127] で報告されている通り、https を使用するとセグメンテーション違反が発生する場合がある。
-
 `sbt` を最初にインストールした後は、このパッケージは `aptitude` や Synaptic
 上から管理することができる (パッケージ・キャッシュの更新を忘れずに)。
 追加された APT リポジトリは「システム設定 -> ソフトウェアとアップデート -> 他のソフトウェア」 の一番下に表示されているはずだ:
diff --git a/src/reference/zh-cn/00-Getting-Started/01-Setup/c.md b/src/reference/zh-cn/00-Getting-Started/01-Setup/c.md
index 152d7591d..f4f269ed8 100644
--- a/src/reference/zh-cn/00-Getting-Started/01-Setup/c.md
+++ b/src/reference/zh-cn/00-Getting-Started/01-Setup/c.md
@@ -10,6 +10,20 @@ out: Installing-sbt-on-Linux.html
 在 Linux 上安装 sbt
 -----------------------
 
+### Installing from SDKMAN
+
+To install both JDK and sbt, consider using [SDKMAN](https://sdkman.io/).
+
+```
+\$ sdk list java
+\$ sdk install java 11.0.4.hs-adpt
+\$ sdk install sbt
+```
+
+This has two advantages.
+1. It will install the official packaging by AdoptOpenJDK, as opposed to the ["mystery meat OpenJDK builds"](https://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-May/009330.html).
+2. It will install `tgz` packaging of sbt that contains all JAR files. (DEB and RPM packages do not to save bandwidth)
+
 ### 通过通用的安装包安装
 
 下载 [ZIP][ZIP] 或者 [TGZ][TGZ] 包并解压。
@@ -22,7 +36,7 @@ Ubuntu和其他基于Debian的发行版使用DEB格式,但通常你不从本
 从终端运行下面的命令安装`sbt`(你需要超级用户权限,因此需要`sudo`)。
 
     echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
-    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
+    curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add
     sudo apt-get update
     sudo apt-get install sbt