Skip to content

Commit f905e4a

Browse files
feat:Add chinese doc (areal-project#969)
* fix(docs): add language toggle button with proper styling and icon - Add lang-toggle.js and lang-toggle.css to en/zh _static directories - Update _config.yml to reference correct paths - Modify build_all.sh to copy static files and figures - Fix URL redirect logic (remove trailing slash) - Style button with translate icon, gray theme matching nav icons - Dynamically adjust icon size based on existing header icons * fix(docs): add language toggle button with proper styling and icon - Add lang-toggle.js and lang-toggle.css to en/zh _static directories - Update _config.yml to reference correct paths - Modify build_all.sh to copy static files and figures - Fix URL redirect logic (remove trailing slash) - Style button with translate icon, gray theme matching nav icons - Dynamically adjust icon size based on existing header icons * Update docs/build_all.sh Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update docs/_static/js/lang-toggle.js Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent dd693a2 commit f905e4a

70 files changed

Lines changed: 8221 additions & 142 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/deploy-docs.yml

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Deploy Jupyter Book to GitHub Pages
22

33
on:
44
push:
5-
branches: [ main ] # Change to your default branch if different
5+
branches: [ main, add_chinese_doc ]
66

77
# Allow one concurrent deployment
88
concurrency:
@@ -28,30 +28,35 @@ jobs:
2828
with:
2929
python-version: '3.12'
3030

31-
- name: Cache pip dependencies
31+
- name: Install uv
32+
uses: astral-sh/setup-uv@v4
33+
34+
- name: Cache uv dependencies
3235
uses: actions/cache@v3
3336
with:
34-
path: ~/.cache/pip
35-
key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }}
37+
path: ~/.cache/uv
38+
key: ${{ runner.os }}-uv-${{ hashFiles('**/pyproject.toml') }}
3639
restore-keys: |
37-
${{ runner.os }}-pip-
40+
${{ runner.os }}-uv-
3841
3942
- name: Install dependencies
4043
run: |
4144
python -m pip install --upgrade pip
42-
pip install --upgrade jupyter-book==1.0.4.post1
45+
python -m pip install uv
4346
4447
- name: Build the book
4548
run: |
46-
jupyter-book build docs
49+
cd docs
50+
chmod +x ./build_all.sh
51+
./build_all.sh
4752
4853
- name: Setup Pages
4954
uses: actions/configure-pages@v4
5055

5156
- name: Upload artifact
5257
uses: actions/upload-pages-artifact@v3
5358
with:
54-
path: docs/_build/html
59+
path: docs/_build
5560

5661
# Deployment job
5762
deploy:

docs/README.md

Lines changed: 0 additions & 55 deletions
This file was deleted.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,7 @@ repository:
2727
html:
2828
use_issues_button: true
2929
use_repository_button: true
30+
extra_footerjs:
31+
- js/lang-toggle.js
32+
extra_css:
33+
- css/lang-toggle.css

docs/_static/css/lang-toggle.css

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* AReaL Documentation Language Toggle Styles
3+
* Gray theme to match navigation icons
4+
*/
5+
6+
/* Language toggle button - gray theme to match nav icons */
7+
.areal-lang-toggle-btn {
8+
display: inline-flex;
9+
align-items: center;
10+
justify-content: center;
11+
padding: 0;
12+
margin: 0;
13+
font-weight: 400;
14+
font-family: inherit;
15+
color: #6b7280;
16+
background-color: transparent;
17+
border: none;
18+
border-radius: 4px;
19+
cursor: pointer;
20+
transition: all 0.2s ease;
21+
white-space: nowrap;
22+
vertical-align: middle;
23+
line-height: 1;
24+
height: auto;
25+
}
26+
27+
.areal-lang-toggle-btn svg {
28+
vertical-align: middle;
29+
margin-right: 4px;
30+
}
31+
32+
.areal-lang-toggle-btn:hover {
33+
color: #374151;
34+
background-color: rgba(0, 0, 0, 0.05);
35+
}
36+
37+
.areal-lang-toggle-btn:active {
38+
background-color: rgba(0, 0, 0, 0.1);
39+
}
40+
41+
/* Position in header-article-items__end (right side of header) */
42+
.header-article-items__end .areal-lang-toggle-btn,
43+
.header-article-items .areal-lang-toggle-btn {
44+
display: inline-flex;
45+
align-items: center;
46+
margin-left: 8px;
47+
margin-right: 0;
48+
vertical-align: middle;
49+
}
50+
51+
/* Make sure the button aligns with other icons in the header */
52+
.header-article-items__end {
53+
align-items: center !important;
54+
}
55+
56+
/* Dark mode support */
57+
@media (prefers-color-scheme: dark) {
58+
.areal-lang-toggle-btn {
59+
color: #9ca3af;
60+
background-color: transparent;
61+
}
62+
63+
.areal-lang-toggle-btn:hover {
64+
color: #d1d5db;
65+
background-color: rgba(255, 255, 255, 0.1);
66+
}
67+
68+
.areal-lang-toggle-btn:active {
69+
background-color: rgba(255, 255, 255, 0.15);
70+
}
71+
}
72+
73+
/* Mobile responsiveness */
74+
@media (max-width: 768px) {
75+
.areal-lang-toggle-btn {
76+
padding: 3px 6px;
77+
font-size: 11px;
78+
margin: 0 3px;
79+
}
80+
}

docs/_static/js/lang-toggle.js

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/**
2+
* AReaL Documentation Language Toggle
3+
* Provides EN/ZH language switching with localStorage preference
4+
* Implementation differs from slime to maintain uniqueness
5+
*/
6+
7+
(function() {
8+
'use strict';
9+
10+
var STORAGE_KEY = 'areal-doc-lang';
11+
var LANG_EN = 'en';
12+
var LANG_ZH = 'zh';
13+
14+
/**
15+
* Extract language from current URL path
16+
* Supports: /en/, /zh/, /AReaL/en/, /AReaL/zh/
17+
*/
18+
function getCurrentLanguage() {
19+
var path = window.location.pathname;
20+
var segments = path.split('/').filter(Boolean);
21+
22+
// Check for language in first or second position
23+
if (segments[0] === LANG_EN || segments[0] === LANG_ZH) {
24+
return segments[0];
25+
}
26+
if (segments[1] === LANG_EN || segments[1] === LANG_ZH) {
27+
return segments[1];
28+
}
29+
return null;
30+
}
31+
32+
/**
33+
* Determine repository root from URL
34+
* Returns: 'AReaL' for project site, or null for user site
35+
*/
36+
function getRepoRoot() {
37+
var host = window.location.host;
38+
var segments = window.location.pathname.split('/').filter(Boolean);
39+
40+
// GitHub Pages project site: ends with github.io and has repo name
41+
if (host.endsWith('github.io') && segments.length > 0) {
42+
// Check if first segment could be repo name (not 'en' or 'zh')
43+
if (segments[0] !== LANG_EN && segments[0] !== LANG_ZH) {
44+
return segments[0];
45+
}
46+
}
47+
return null;
48+
}
49+
50+
/**
51+
* Build target URL for language switch
52+
*/
53+
function buildTargetUrl(targetLang) {
54+
var currentLang = getCurrentLanguage();
55+
var repoRoot = getRepoRoot();
56+
var segments = window.location.pathname.split('/').filter(Boolean);
57+
var hasLang = segments[0] === LANG_EN || segments[0] === LANG_ZH ||
58+
segments[1] === LANG_EN || segments[1] === LANG_ZH;
59+
60+
if (hasLang) {
61+
// Replace existing language prefix
62+
if (segments[0] === LANG_EN || segments[0] === LANG_ZH) {
63+
segments[0] = targetLang;
64+
} else if (segments[1] === LANG_EN || segments[1] === LANG_ZH) {
65+
segments[1] = targetLang;
66+
}
67+
} else {
68+
// Insert language prefix
69+
if (repoRoot) {
70+
// Project site: insert after repo root
71+
segments.splice(1, 0, targetLang);
72+
} else {
73+
// User site: insert at beginning
74+
segments.unshift(targetLang);
75+
}
76+
}
77+
78+
var newPath = '/' + segments.join('/');
79+
var url = new URL(window.location.href);
80+
url.pathname = newPath;
81+
// Remove trailing slash if it was originally a file (not directory)
82+
var originalPath = window.location.pathname;
83+
if (originalPath.endsWith('/') && !newPath.endsWith('/')) {
84+
newPath = newPath + '/';
85+
} else if (!originalPath.endsWith('/') && newPath.endsWith('/')) {
86+
newPath = newPath.replace(/\/$/, '');
87+
}
88+
url.pathname = newPath;
89+
return url.toString();
90+
}
91+
92+
/**
93+
* Save language preference to localStorage
94+
*/
95+
function savePreference(lang) {
96+
try {
97+
localStorage.setItem(STORAGE_KEY, lang);
98+
} catch (e) {
99+
console.warn('Could not save language preference to localStorage.', e);
100+
}
101+
}
102+
103+
/**
104+
* Get size from existing header icons
105+
*/
106+
function getIconSize() {
107+
// Try to find existing icons in the header
108+
var iconSelectors = [
109+
'.header-article-items__end .btn svg',
110+
'.header-article-items__end i',
111+
'.header-article-items__end .dropdown-toggle svg',
112+
'.bd-header .btn svg'
113+
];
114+
115+
for (var i = 0; i < iconSelectors.length; i++) {
116+
var icon = document.querySelector(iconSelectors[i]);
117+
if (icon) {
118+
// Get computed size
119+
var style = window.getComputedStyle(icon);
120+
var width = parseFloat(style.width);
121+
var height = parseFloat(style.height);
122+
if (width > 0 && height > 0) {
123+
return { width: width, height: height };
124+
}
125+
// Try getAttribute for svg
126+
var w = icon.getAttribute('width');
127+
var h = icon.getAttribute('height');
128+
if (w && h) {
129+
return { width: parseFloat(w), height: parseFloat(h) };
130+
}
131+
}
132+
}
133+
// Default size
134+
return { width: 16, height: 16 };
135+
}
136+
137+
/**
138+
* Create and insert language toggle button
139+
*/
140+
function createButton() {
141+
var currentLang = getCurrentLanguage();
142+
if (!currentLang) return;
143+
144+
var targetLang = currentLang === LANG_EN ? LANG_ZH : LANG_EN;
145+
var buttonText = currentLang === LANG_EN ? '中文' : 'EN';
146+
var titleText = currentLang === LANG_EN ? 'Switch to Chinese' : 'Switch to English';
147+
148+
// Get icon size from existing icons
149+
var iconSize = getIconSize();
150+
var fontSize = iconSize.width * 0.85;
151+
152+
var button = document.createElement('button');
153+
button.id = 'areal-lang-toggle';
154+
button.className = 'areal-lang-toggle-btn';
155+
button.type = 'button';
156+
button.title = titleText;
157+
button.setAttribute('aria-label', titleText);
158+
button.style.fontSize = fontSize + 'px';
159+
160+
// Add translate icon with dynamic size + text
161+
button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="' + iconSize.width + '" height="' + iconSize.height + '" fill="currentColor" viewBox="0 0 16 16" class="areal-lang-icon"><path d="M4.545 6.714 4.11 8H3l1.862-5h1.284L8 8H6.833l-.435-1.286zm1.634-.736L5.5 3.956h-.049l-.679 2.022z"/><path d="M0 2a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v3h3a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-3H2a2 2 0 0 1-2-2zm2-1a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h7a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1zm7.138 9.995q.289.451.63.846c-.748.575-1.673 1.001-2.768 1.292.178.217.451.635.555.867 1.125-.359 2.08-.844 2.886-1.494.777.665 1.739 1.165 2.93 1.472.133-.254.414-.673.629-.89-1.125-.253-2.057-.694-2.82-1.284.681-.747 1.222-1.651 1.621-2.757H14V8h-3v1.047h.765c-.318.844-.74 1.546-1.272 2.13a6 6 0 0 1-.415-.492 2 2 0 0 1-.94.31"/></svg><span class="areal-lang-text">' + buttonText + '</span>';
162+
163+
button.addEventListener('click', function(e) {
164+
e.preventDefault();
165+
var targetUrl = buildTargetUrl(targetLang);
166+
savePreference(targetLang);
167+
window.location.href = targetUrl;
168+
});
169+
170+
// Find appropriate container - append to header-article-items__end (right side of header)
171+
var container = document.querySelector('.header-article-items__end');
172+
173+
if (container) {
174+
container.appendChild(button);
175+
}
176+
}
177+
178+
/**
179+
* Initialize on page load
180+
*/
181+
function init() {
182+
if (!getCurrentLanguage()) return;
183+
184+
if (document.readyState === 'loading') {
185+
document.addEventListener('DOMContentLoaded', createButton);
186+
} else {
187+
createButton();
188+
}
189+
}
190+
191+
init();
192+
})();

0 commit comments

Comments
 (0)