|
1 | 1 | #!/bin/bash |
2 | 2 | # Patch mdbook theme to add language selector and utility links |
3 | | -# Usage: patch-mdbook-theme.sh <coreutils-docs-dir> [current-lang] |
| 3 | +# Usage: patch-mdbook-theme.sh <coreutils-docs-dir> <coreutils-l10n-dir> |
4 | 4 |
|
5 | 5 | set -euo pipefail |
6 | 6 |
|
7 | | -DOCS_DIR="${1:?Usage: $0 <coreutils-docs-dir> [current-lang]}" |
8 | | -CURRENT_LANG="${2:-en}" |
| 7 | +DOCS_DIR="${1:?Usage: $0 <coreutils-docs-dir> <coreutils-l10n-dir>}" |
| 8 | +L10N_DIR="${2:?Usage: $0 <coreutils-docs-dir> <coreutils-l10n-dir>}" |
9 | 9 |
|
10 | 10 | HEAD_HBS="$DOCS_DIR/theme/head.hbs" |
11 | 11 |
|
12 | | -# Append language selector and utility links to head.hbs |
| 12 | +# Language display names (ftl filename -> display name) |
| 13 | +declare -A LANG_NAMES=( |
| 14 | + [en-US]="English" |
| 15 | + [ar]="العربية" [ast]="Asturianu" [ca]="Català" [cs]="Čeština" |
| 16 | + [da]="Dansk" [de]="Deutsch" [eo]="Esperanto" [es-ES]="Español" |
| 17 | + [fi]="Suomi" [fr-FR]="Français" [he]="עברית" [id]="Bahasa Indonesia" |
| 18 | + [it]="Italiano" [ja]="日本語" [kab]="Taqbaylit" [ko]="한국어" |
| 19 | + [nb-NO]="Norsk Bokmål" [ne]="नेपाली" [pl]="Polski" [pt]="Português" |
| 20 | + [pt-BR]="Português (Brasil)" [ru]="Русский" [sv]="Svenska" |
| 21 | + [tr]="Türkçe" [uk]="Українська" [vi]="Tiếng Việt" |
| 22 | + [zh-Hans]="中文 (简体)" [zh-Hant]="中文 (繁體)" |
| 23 | +) |
| 24 | + |
| 25 | +# ftl filename -> URL lang code (used in /coreutils/docs-{code}/) |
| 26 | +declare -A FTL_TO_URL=( |
| 27 | + [en-US]="en" [fr-FR]="fr" [es-ES]="es" [zh-Hans]="zh" [zh-Hant]="zh-Hant" |
| 28 | + [pt-BR]="pt-BR" [nb-NO]="nb-NO" |
| 29 | +) |
| 30 | +# For others, the ftl name IS the URL code (ar, de, it, ja, etc.) |
| 31 | + |
| 32 | +# Scan l10n repo to find which locales have translations |
| 33 | +# Use a representative utility (ls) to find available locales |
| 34 | +LANGS_JSON="['en', 'English']" |
| 35 | +for ftl in "$L10N_DIR"/src/uu/ls/locales/*.ftl; do |
| 36 | + [ -f "$ftl" ] || continue |
| 37 | + ftl_name=$(basename "$ftl" .ftl) |
| 38 | + [ "$ftl_name" = "en-US" ] && continue |
| 39 | + |
| 40 | + display="${LANG_NAMES[$ftl_name]:-$ftl_name}" |
| 41 | + url_code="${FTL_TO_URL[$ftl_name]:-$ftl_name}" |
| 42 | + LANGS_JSON="$LANGS_JSON, ['$url_code', '$display']" |
| 43 | +done |
| 44 | + |
| 45 | +# Append styles and JS to head.hbs |
13 | 46 | cat >> "$HEAD_HBS" << 'ENDSTYLE' |
14 | 47 | <style> |
15 | | - .util-bar { |
| 48 | + .util-links { |
16 | 49 | display: flex; |
17 | | - justify-content: flex-end; |
18 | | - gap: 15px; |
| 50 | + gap: 12px; |
19 | 51 | align-items: center; |
20 | | - font-size: 0.85em; |
21 | | - margin-bottom: 10px; |
| 52 | + font-size: 0.75em; |
22 | 53 | } |
23 | | - .util-bar a { |
| 54 | + .util-links a { |
24 | 55 | color: var(--links); |
25 | 56 | text-decoration: none; |
26 | 57 | } |
27 | | - .util-bar a:hover { |
| 58 | + .util-links a:hover { |
28 | 59 | text-decoration: underline; |
29 | 60 | } |
30 | 61 | .lang-selector { |
31 | 62 | position: relative; |
| 63 | + display: inline-block; |
32 | 64 | } |
33 | 65 | .lang-selector select { |
34 | 66 | appearance: none; |
35 | 67 | background: var(--bg); |
36 | 68 | color: var(--fg); |
37 | 69 | border: 1px solid var(--table-border-color); |
38 | 70 | border-radius: 4px; |
39 | | - padding: 4px 24px 4px 8px; |
40 | | - font-size: 0.85em; |
| 71 | + padding: 2px 20px 2px 6px; |
| 72 | + font-size: 1em; |
41 | 73 | cursor: pointer; |
42 | 74 | } |
43 | 75 | .lang-selector::after { |
44 | 76 | content: "▾"; |
45 | 77 | position: absolute; |
46 | | - right: 8px; |
| 78 | + right: 6px; |
47 | 79 | top: 50%; |
48 | 80 | transform: translateY(-50%); |
49 | 81 | pointer-events: none; |
50 | 82 | color: var(--fg); |
| 83 | + font-size: 0.8em; |
51 | 84 | } |
52 | 85 | </style> |
53 | 86 | ENDSTYLE |
54 | | - |
55 | | -# Add JavaScript for language switching and utility bar injection |
56 | | -cat >> "$HEAD_HBS" << ENDSCRIPT |
| 87 | +cat >> "$HEAD_HBS" << 'ENDSCRIPT' |
57 | 88 | <script> |
58 | 89 | document.addEventListener('DOMContentLoaded', function() { |
59 | | - // Only add util-bar on utility pages |
60 | 90 | var path = window.location.pathname; |
61 | | - var match = path.match(/\/coreutils\/docs(?:-([a-z]{2}(?:-[A-Z]{2})?))?\/utils\/(\w+)\.html/); |
| 91 | + // Match both deployed (/coreutils/docs[-lang]/utils/X.html) and local (book[-lang]/utils/X.html) |
| 92 | + var match = path.match(/\/(?:coreutils\/)?docs(?:-([a-z]{2}(?:-[A-Z]{2})?))?\/utils\/(\w+)\.html/) |
| 93 | + || path.match(/\/book(?:-([a-z]{2}(?:-[A-Z]{2})?))?\/utils\/(\w+)\.html/); |
62 | 94 | if (!match) return; |
63 | 95 |
|
64 | 96 | var currentLang = match[1] || 'en'; |
65 | 97 | var utilName = match[2]; |
66 | 98 |
|
67 | | - var bar = document.createElement('div'); |
68 | | - bar.className = 'util-bar'; |
| 99 | + // Find the existing .additional div and append our links there |
| 100 | + var additional = document.querySelector('.additional'); |
| 101 | + if (!additional) return; |
| 102 | +
|
| 103 | + var links = document.createElement('div'); |
| 104 | + links.className = 'util-links'; |
69 | 105 |
|
70 | 106 | // Source code link |
71 | 107 | var srcLink = document.createElement('a'); |
72 | 108 | srcLink.href = 'https://github.com/uutils/coreutils/tree/main/src/uu/' + utilName; |
73 | | - srcLink.textContent = 'Source code'; |
| 109 | + srcLink.textContent = 'Source'; |
74 | 110 | srcLink.target = '_blank'; |
75 | | - bar.appendChild(srcLink); |
| 111 | + links.appendChild(srcLink); |
76 | 112 |
|
77 | 113 | // Report issue link |
78 | 114 | var issueLink = document.createElement('a'); |
79 | 115 | issueLink.href = 'https://github.com/uutils/coreutils/issues/new?title=' + utilName + ':%20&labels=bug'; |
80 | | - issueLink.textContent = 'Report an issue'; |
| 116 | + issueLink.textContent = 'Report a bug'; |
81 | 117 | issueLink.target = '_blank'; |
82 | | - bar.appendChild(issueLink); |
| 118 | + links.appendChild(issueLink); |
83 | 119 |
|
84 | 120 | // Language selector |
85 | 121 | var langDiv = document.createElement('div'); |
86 | 122 | langDiv.className = 'lang-selector'; |
87 | 123 | var select = document.createElement('select'); |
88 | | - var langs = { |
89 | | - 'en': 'English', 'fr': 'Français', 'de': 'Deutsch', 'es': 'Español', |
90 | | - 'it': 'Italiano', 'pt': 'Português', 'pt-BR': 'Português (BR)', |
91 | | - 'ja': '日本語', 'ko': '한국어', 'ru': 'Русский', 'zh': '中文', |
92 | | - 'uk': 'Українська', 'sv': 'Svenska', 'pl': 'Polski', 'tr': 'Türkçe' |
93 | | - }; |
94 | | - for (var code in langs) { |
| 124 | + var langs = LANGS_PLACEHOLDER; |
| 125 | + langs.forEach(function(l) { |
95 | 126 | var opt = document.createElement('option'); |
96 | | - opt.value = code; |
97 | | - opt.textContent = langs[code]; |
98 | | - if (code === currentLang) opt.selected = true; |
| 127 | + opt.value = l[0]; |
| 128 | + opt.textContent = l[1]; |
| 129 | + if (l[0] === currentLang) opt.selected = true; |
99 | 130 | select.appendChild(opt); |
100 | | - } |
| 131 | + }); |
101 | 132 | select.addEventListener('change', function() { |
102 | 133 | var newLang = this.value; |
103 | | - var suffix = newLang === 'en' ? '' : '-' + newLang; |
104 | | - window.location.href = '/coreutils/docs' + suffix + '/utils/' + utilName + '.html'; |
| 134 | + var curPath = window.location.pathname; |
| 135 | + // Replace the directory segment right before /utils/: |
| 136 | + // .../book[-lang]/utils/X.html or .../docs[-lang]/utils/X.html |
| 137 | + var newPath = curPath.replace( |
| 138 | + /\/(book|docs)(?:-[a-zA-Z]{2}(?:-[a-zA-Z]+)?)?\/utils\//, |
| 139 | + function(m, base) { |
| 140 | + return '/' + base + (newLang === 'en' ? '' : '-' + newLang) + '/utils/'; |
| 141 | + } |
| 142 | + ); |
| 143 | + window.location.href = newPath; |
105 | 144 | }); |
106 | 145 | langDiv.appendChild(select); |
107 | | - bar.appendChild(langDiv); |
| 146 | + links.appendChild(langDiv); |
108 | 147 |
|
109 | | - // Insert bar at the top of the content |
110 | | - var main = document.querySelector('main'); |
111 | | - if (main) main.insertBefore(bar, main.firstChild); |
| 148 | + additional.appendChild(links); |
112 | 149 | }); |
113 | 150 | </script> |
114 | 151 | ENDSCRIPT |
115 | 152 |
|
| 153 | +# Inject the dynamically-built language list |
| 154 | +sed -i "s|LANGS_PLACEHOLDER|[${LANGS_JSON}]|" "$HEAD_HBS" |
| 155 | + |
116 | 156 | echo "Patched $HEAD_HBS with language selector and utility links" |
0 commit comments