Localization support in HTML docs, simplification of checklinks.sh (#5342)
* Add localization support to HTML docs site and simplify checklinks.sh * Support localization in the html build process * Show language selection menu * Get the Chinese content additional pages into the localization project * Have PRs in `netdata/localization` automatically trigger the `netdata/netdata` Netlify builds. The checks must pass before a PR is merged * Make link to edit lead to the root directory of localization, which contains instructions
Chris Akritidis committed
Feb 13, 2019 at 16:19 UTC
bbd4d59f94b22ca6998ed2737cf639508a1197f5
7 files changed
+199
-101
CONTRIBUTING.md
+4
@@ -21,6 +21,10 @@ Community growth allows the project to attract new talent willing to contribute.
21
22
Is there anything that bothers you about netdata? Did you experience an issue while installing it or using it? Would you like to see it evolve to you need? Let us know. [Open a github issue](https://github.com/netdata/netdata/issues) to discuss it. Feedback is very important for open-source projects. We can't commit we will do everything, but your feedback influences our road-map significantly. **We rely on your feedback to make Netdata better**.
23
24
+### Translate some documentation
25
+
26
+The [netdata localization project](https://github.com/netdata/localization) contains instructions on how to provide translations for parts of our documentation. Translating the entire documentation is a daunting task, but you can contribute as much as you like, even a single file. The Chinese translation effort has already begun and we are looking forward to more contributions.
27
+
28
### Sponsor a part of Netdata
29
30
Netdata is a complex system, with many integrations for the various collectors, backends and notification endpoints. As a result, we rely on help from "sponsors", a concept similar to "power users" or "product owners". To become a sponsor, just let us know in any Github issue and we will record your GitHub username in a "CONTRIBUTORS.md" in the appropriate directory.
docs/generator/buildhtml.sh
+63
-29
@@ -13,27 +13,27 @@ if [ "$currentdir" = "generator" ]; then
13
cd ../..
14
fi
15
GENERATOR_DIR="docs/generator"
16
-
16
+SRC_DIR="${GENERATOR_DIR}/src"
17
# Fetch go.d.plugin docs
18
-rm -rf ./collectors/go.d.plugin
19
-git clone https://github.com/netdata/go.d.plugin.git ./collectors/go.d.plugin
18
+GO_D_DIR="collectors/go.d.plugin"
19
+rm -rf ${GO_D_DIR}
20
+git clone https://github.com/netdata/go.d.plugin.git ${GO_D_DIR}
21
22
# Copy all netdata .md files to docs/generator/src. Exclude htmldoc itself and also the directory node_modules generatord by Netlify
23
echo "Copying files"
23
-rm -rf ${GENERATOR_DIR}/src
24
-find . -type d \( -path ./${GENERATOR_DIR} -o -path ./node_modules \) -prune -o -name "*.md" -print | cpio -pd ${GENERATOR_DIR}/src
24
+rm -rf ${SRC_DIR}
25
+find . -type d \( -path ./${GENERATOR_DIR} -o -path ./node_modules \) -prune -o -name "*.md" -print | cpio -pd ${SRC_DIR}
26
27
# Copy netdata html resources
27
-cp -a ./${GENERATOR_DIR}/custom ./${GENERATOR_DIR}/src/
28
-
28
+cp -a ./${GENERATOR_DIR}/custom ./${SRC_DIR}/
29
30
31
# Modify the first line of the main README.md, to enable proper static html generation
32
echo "Modifying README header"
33
-sed -i -e '0,/# netdata /s//# Introduction\n\n/' ${GENERATOR_DIR}/src/README.md
33
+sed -i -e '0,/# netdata /s//# Introduction\n\n/' ${SRC_DIR}/README.md
34
35
# Remove all GA tracking code
36
-find ${GENERATOR_DIR}/src -name "*.md" -print0 | xargs -0 sed -i -e 's/\[!\[analytics.*UA-64295674-3)\]()//g'
36
+find ${SRC_DIR} -name "*.md" -print0 | xargs -0 sed -i -e 's/\[!\[analytics.*UA-64295674-3)\]()//g'
37
38
# Remove specific files that don't belong in the documentation
39
declare -a EXCLUDE_LIST=(
@@ -43,28 +43,62 @@ declare -a EXCLUDE_LIST=(
43
)
44
45
for f in "${EXCLUDE_LIST[@]}"; do
46
- rm "${GENERATOR_DIR}/src/$f"
46
+ rm "${SRC_DIR}/$f"
47
done
48
49
-echo "Creating mkdocs.yaml"
50
-
51
-# Generate mkdocs.yaml
52
-${GENERATOR_DIR}/buildyaml.sh >${GENERATOR_DIR}/mkdocs.yml
53
-
54
-echo "Fixing links"
55
-
56
-# Fix links (recursively, all types, executing replacements)
57
-${GENERATOR_DIR}/checklinks.sh -rax
58
-
59
-echo "Calling mkdocs"
60
-
61
-# Build html docs
62
-mkdocs build --config-file=${GENERATOR_DIR}/mkdocs.yml
63
-
64
-# Fix edit buttons for the markdowns that are not on the main netdata repo
65
-find ${GENERATOR_DIR}/build/collectors/go.d.plugin -name "*.html" -print0 | xargs -0 sed -i -e 's/https:\/\/github.com\/netdata\/netdata\/blob\/master\/collectors\/go.d.plugin/https:\/\/github.com\/netdata\/go.d.plugin\/blob\/master/g'
49
+echo "Fetching localization project"
50
+LOC_DIR=${GENERATOR_DIR}/localization
51
+rm -rf ${LOC_DIR}
52
+git clone https://github.com/netdata/localization.git ${LOC_DIR}
53
+
54
+echo "Preparing directories"
55
+MKDOCS_CONFIG_FILE="${GENERATOR_DIR}/mkdocs.yml"
56
+MKDOCS_DIR="doc"
57
+DOCS_DIR=${GENERATOR_DIR}/${MKDOCS_DIR}
58
+rm -rf ${DOCS_DIR}
59
+mkdir ${DOCS_DIR}
60
+
61
+prep_html() {
62
+ lang="${1}"
63
+ echo "Creating ${lang} mkdocs.yaml"
64
+
65
+ if [ "${lang}" = "en" ] ; then
66
+ SITE_DIR="build"
67
+ else
68
+ SITE_DIR="build/${lang}"
69
+ fi
70
+
71
+ # Generate mkdocs.yaml
72
+ ${GENERATOR_DIR}/buildyaml.sh ${MKDOCS_DIR} ${SITE_DIR} ${lang}>${MKDOCS_CONFIG_FILE}
73
+
74
+ echo "Fixing links"
75
+
76
+ # Fix links (recursively, all types, executing replacements)
77
+ ${GENERATOR_DIR}/checklinks.sh -rax
78
+
79
+ echo "Calling mkdocs"
80
+
81
+ # Build html docs
82
+ mkdocs build --config-file="${MKDOCS_CONFIG_FILE}"
83
+
84
+ # Fix edit buttons for the markdowns that are not on the main netdata repo
85
+ find "${GENERATOR_DIR}/${SITE_DIR}/${GO_D_DIR}" -name "*.html" -print0 | xargs -0 sed -i -e 's/https:\/\/github.com\/netdata\/netdata\/blob\/master\/collectors\/go.d.plugin/https:\/\/github.com\/netdata\/go.d.plugin\/blob\/master/g'
86
+ if [ "${lang}" != "en" ] ; then
87
+ find "${GENERATOR_DIR}/${SITE_DIR}" -name "*.html" -print0 | xargs -0 sed -i -e 's/https:\/\/github.com\/netdata\/netdata\/blob\/master\/\S*md/https:\/\/github.com\/netdata\/localization\//g'
88
+ fi
89
+}
90
+
91
+for d in "en" $(find ${LOC_DIR} -mindepth 1 -maxdepth 1 -name .git -prune -o -type d -printf '%f ') ; do
92
+ echo "Preparing source for $d"
93
+ cp -a ${SRC_DIR}/* ${DOCS_DIR}/
94
+ if [ "${d}" != "en" ] ; then
95
+ cp -a ${LOC_DIR}/${d}/* ${DOCS_DIR}/
96
+ fi
97
+ prep_html $d
98
+ rm -rf ${DOCS_DIR}/*
99
+done
100
67
-# Remove the cloned go.d.plugin project
68
-rm -rf ./collectors/go.d.plugin
101
+# Remove cloned projects and temp directories
102
+rm -rf ${GO_D_DIR} ${LOC_DIR} ${DOCS_DIR} ${SRC_DIR}
103
104
echo "Finished"
docs/generator/buildyaml.sh
+9
-3
@@ -1,7 +1,12 @@
1
#!/bin/bash
2
3
GENERATOR_DIR="docs/generator"
4
-cd ${GENERATOR_DIR}/src
4
+
5
+docs_dir="${1}"
6
+site_dir="${2}"
7
+language="${3}"
8
+
9
+cd ${GENERATOR_DIR}/${docs_dir}
10
11
# create yaml nav subtree with all the files directly under a specific directory
12
# arguments:
@@ -48,8 +53,8 @@ repo_name: GitHub
53
edit_uri: blob/master
54
site_description: Netdata Documentation
55
copyright: Netdata, 2018
51
-docs_dir: src
52
-site_dir: build
56
+docs_dir: '${docs_dir}'
57
+site_dir: '${site_dir}'
58
#use_directory_urls: false
59
strict: true
60
extra:
@@ -64,6 +69,7 @@ theme:
69
name: "material"
70
custom_dir: custom/themes/material
71
favicon: custom/img/favicon.ico
72
+ language: '${language}'
73
extra_css:
74
- "https://cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css"
75
- "custom/css/netdata.css"
docs/generator/checklinks.sh
+3
-69
@@ -36,72 +36,6 @@ fix () {
36
fi
37
}
38
39
-ck_netdata_absolute () {
40
- f=$1
41
- alnk=$2
42
- lnkinfile=$3
43
- testURL "$alnk"
44
-
45
- if [[ $f =~ ^(.*)/([^/]*)$ ]] ; then
46
- fpath="${BASH_REMATCH[1]}"
47
- dbg "-- Current file is at $fpath"
48
- fi
49
-
50
- if [ $? -eq 0 ] ; then
51
- rlnk=$(echo "$alnk" | sed 's/https:\/\/github.com\/netdata\/netdata\/....\/master\///g')
52
- case $rlnk in
53
- \#* ) dbg "-- (#somelink)" ;;
54
- */ ) dbg "-- # (path/)" ;;
55
- */#* ) dbg "-- # (path/#somelink)" ;;
56
- */*.md ) dbg "-- # (path/filename.md)" ;;
57
- */*.md#* ) dbg "-- # (path/filename.md#somelink)" ;;
58
- *#* )
59
- dbg "-- # (path#somelink) -> (path/#somelink)"
60
- if [[ $rlnk =~ ^(.*)#(.*)$ ]] ; then
61
- dbg "-- $rlnk -> ${BASH_REMATCH[1]}/#${BASH_REMATCH[2]}"
62
- rlnk="${BASH_REMATCH[1]}/#${BASH_REMATCH[2]}"
63
- fi
64
- ;;
65
- * )
66
- if [ -f "$rlnk" ] ; then
67
- dbg "-- # (path/someotherfile) $rlnk"
68
- else
69
- if [ -d "$rlnk" ] ; then
70
- dbg "-- # (path) -> (path/)"
71
- rlnk="$rlnk/"
72
- else
73
- echo "-- ERROR: $f - $alnk is neither a file nor a directory. Giving up!"
74
- EXITCODE=1
75
- return
76
- fi
77
- fi
78
- ;;
79
- esac
80
-
81
- if [[ $rlnk =~ ^(.*)/([^/]*)$ ]] ; then
82
- abspath="${BASH_REMATCH[1]}"
83
- rest="${BASH_REMATCH[2]}"
84
- dbg "-- Target file is at $abspath"
85
- fi
86
- relativelink=$(realpath --relative-to="$fpath" "$abspath")
87
- if [ $? -eq 0 ] ; then
88
- srch=$(echo "$lnkinfile" | sed 's/\//\\\//g')
89
- if [ "$relativelink" = "." ] ; then
90
- rplc=$(echo "$rest" | sed 's/\//\\\//g')
91
- else
92
- rplc=$(echo "$relativelink/$rest" | sed 's/\//\\\//g')
93
- fi
94
- fix "sed -i 's/($srch)/($rplc)/g' $f"
95
- else
96
- echo "-- ERROR: $f - Can't determine relative path of $alnk"
97
- fi
98
- else
99
- echo "-- ERROR: $f - $alnk is a broken link"
100
- EXITCODE=1
101
- return
102
- fi
103
-}
104
-
39
testURL () {
40
if [ "$TESTURLS" -eq 0 ] ; then return 0 ; fi
41
dbg "-- Testing URL $1"
@@ -278,7 +212,7 @@ ck_netdata_relative () {
212
if [[ ! -z $s ]] ; then
213
srch=$(echo "$rlnk" | sed 's/\//\\\//g')
214
rplc=$(echo "$s" | sed 's/\//\\\//g')
281
- fix "sed -i 's/($srch)/($rplc)/g' $GENERATOR_DIR/src/$f"
215
+ fix "sed -i 's/($srch)/($rplc)/g' $GENERATOR_DIR/doc/$f"
216
fi
217
}
218
@@ -299,8 +233,8 @@ checklinks () {
233
if [ "$CHKWIKI" -eq 1 ] ; then echo "-- WARNING: $f - $lnk points to the wiki. Please replace it manually" ; fi
234
;;
235
https://github.com/netdata/netdata/????/master* )
302
- dbg "-- Absolute link $lnk"
303
- if [ "$CHKABSOLUTE" -eq 1 ] ; then ck_netdata_absolute "$f" "$lnk" "$lnk" ; fi
236
+ echo "-- ERROR: $f - $lnk is an absolute link to a netdata file. Please convert to relative."
237
+ EXITCODE=1
238
;;
239
http* )
240
dbg "-- External link $lnk"
docs/generator/custom/img/geography-16.png
Binary files /dev/null and b/docs/generator/custom/img/geography-16.png differ
docs/generator/custom/themes/material/partials/footer.html
+13
@@ -52,3 +52,16 @@
52
</div>
53
</footer>
54
<script>!function(e,a,t,n,o,c,i){e.GoogleAnalyticsObject=o,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,c=a.createElement(t),i=a.getElementsByTagName(t)[0],c.async=1,c.src="https://www.google-analytics.com/analytics.js",i.parentNode.insertBefore(c,i)}(window,document,"script",0,"ga"),ga("create","UA-64295674-3",""),ga("set","anonymizeIp",!0),ga("send","pageview","/doc"+window.location.pathname);var links=document.getElementsByTagName("a");if(Array.prototype.map.call(links,function(a){a.host!=document.location.host&&a.addEventListener("click",function(){var e=a.getAttribute("data-md-action")||"follow";ga("send","event","outbound",e,a.href)})}),document.forms.search){var query=document.forms.search.query;query.addEventListener("blur",function(){if(this.value){var e=document.location.pathname;ga("send","pageview",e+"?q="+this.value)}})}</script>
55
+<script>
56
+ let currentLang = getLanguage();
57
+
58
+ let sel = document.getElementById('sel');
59
+ let opts = sel.options;
60
+ for (let opt, j = 0; opt = opts[j]; j++) {
61
+ if (opt.value == currentLang) {
62
+ sel.selectedIndex = j;
63
+ break;
64
+ }
65
+ }
66
+
67
+</script>
docs/generator/custom/themes/material/partials/header.html
new
+107
@@ -0,0 +1,107 @@
1
+<header class="md-header" data-md-component="header">
2
+ <nav class="md-header-nav md-grid">
3
+ <div class="md-flex">
4
+ <div class="md-flex__cell md-flex__cell--shrink">
5
+ <a href="{{ config.site_url | default(nav.homepage.url, true) | url }}" title="{{ config.site_name }}" class="md-header-nav__button md-logo">
6
+ {% if config.theme.logo.icon %}
7
+ <i class="md-icon">{{ config.theme.logo.icon }}</i>
8
+ {% else %}
9
+ <img src="{{ config.theme.logo | url }}" width="24" height="24">
10
+ {% endif %}
11
+ </a>
12
+ </div>
13
+ <div class="md-flex__cell md-flex__cell--shrink">
14
+ <label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
15
+ </div>
16
+ <div class="md-flex__cell md-flex__cell--stretch">
17
+ <div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
18
+ {% block site_name %}
19
+ {% if config.site_name == page.title %}
20
+ {{ config.site_name }}
21
+ {% else %}
22
+ <span class="md-header-nav__topic">
23
+ {{ config.site_name }}
24
+ </span>
25
+ <span class="md-header-nav__topic">
26
+ {{ page.title }}
27
+ </span>
28
+ {% endif %}
29
+ {% endblock %}
30
+ </div>
31
+ </div>
32
+ <div class="md-flex__cell md-flex__cell--shrink">
33
+ {% block search_box %}
34
+ {% if "search" in config["plugins"] %}
35
+ <label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
36
+ {% include "partials/search.html" %}
37
+ {% endif %}
38
+ {% endblock %}
39
+ </div>
40
+
41
+ <!-- netdata -->
42
+ <style>
43
+ .language-selector li {
44
+ list-style: none;
45
+ }
46
+
47
+ .language-option.selected {
48
+ background-color: #ccc;
49
+ }
50
+ </style>
51
+ <script>
52
+ function getLanguage() {
53
+ const lang = window.location.pathname.split("/")[1];
54
+
55
+ if (lang.length == 0 || lang.length > 2) {
56
+ return "en";
57
+ }
58
+
59
+ return lang;
60
+ }
61
+
62
+ function languagePrefix(lang) {
63
+ if (lang === "en") {
64
+ return "";
65
+ }
66
+
67
+ return `/${lang}`;
68
+ }
69
+
70
+ function updatePathname(pathname, lang) {
71
+ if (currentLang !== "en") {
72
+ const parts = pathname.split("/");
73
+ parts.shift();
74
+ parts.shift();
75
+ pathname = `/${parts.join("/")}`;
76
+ }
77
+
78
+ return `${languagePrefix(lang)}${pathname}`;
79
+ }
80
+
81
+ function setLanguage(sel) {
82
+ if (sel.value === currentLang) {
83
+ return;
84
+ }
85
+
86
+ window.location.pathname = updatePathname(window.location.pathname, sel.value);
87
+ }
88
+ </script>
89
+
90
+ <div style="vertical-align: middle; white-space: nowrap; padding-left: 20px;" class="md-flex__cell md-flex__cell--shrink">
91
+ <img src="/custom/img/geography-16.png" style="vertical-align: middle;"/>
92
+ <select id="sel" onchange="setLanguage(this);" style="vertical-align: middle; background-color: #3f51b5; color: white; border: none;">
93
+ <option href="#" value='en'>English</option>
94
+ <option href="#" value='zh'>中文</option>
95
+ </select>
96
+ </div>
97
+
98
+ {% if config.repo_url %}
99
+ <div class="md-flex__cell md-flex__cell--shrink">
100
+ <div class="md-header-nav__source">
101
+ {% include "partials/source.html" %}
102
+ </div>
103
+ </div>
104
+ {% endif %}
105
+ </div>
106
+ </nav>
107
+</header>