This repository contains all the user content of KoboToolbox's official documentation, available at https://support.kobotoolbox.org/.
Please note that the purpose of the issue tracker on this repository is to track work on the technical infrastructure of the documentation site. For requests related to the content of the documentation, please:
- Post in Zulip #Kobo support docs if you are a member of the Kobo team
- Otherwise, please share your feedback through our Community Feedback Form
- For support requests or bug reports, please post in the Community Forum
To build and test this documentation locally follow these steps:
Prerequisites:
- Python 3.10 or later (Python 3.13+ supported)
- git
- npm
- Open terminal
- Clone repository:
git clone https://github.com/kobotoolbox/docs.git - Change into the cloned directory:
cd docs - Build the theme if you made any changes to it:
npm install && npm start - Create a virtual environment:
python -m venv koboenv - Activate the virtual environment
source koboenv/bin/activate - Install requirements
pip install -r requirements.txt - Build the html files:
make html - Open the index page in the browser:
open _build/html/index.html
Note: if you have Python 3, you might need to use python3 command instead of python (and pip3 instead of pip).
Each commit to master is automatically built into production.
When you already did everything from "Local installation" succesfully and just need to come back and work a bit more on the project, please use dev.sh script from the root of the project.
The documentation supports multiple languages. The structure is:
source/- English content (default language)locales/es/- Spanish translationslocales/fr/- French translations
To build everything (English plus all translated locales) in one step:
make html-allThis builds English into _build/html/ and each locale into _build/html/<lang>.
To build a single language on its own:
# Build English (default)
make html
# Build Spanish
sphinx-build -b html locales/es _build/html/es
# Build French
sphinx-build -b html locales/fr _build/html/fr- Create the translated file in
locales/[lang]/with the same filename as the English version (e.g.,locales/es/new_article.md) - Add the file to the corresponding
locales/[lang]/index.rsttoctree
The article content lives in the .md/.rst files, but the surrounding
theme chrome — the header navigation, language picker, search box, feedback
prompt, footer, and homepage forum/academy sections — is translated directly
in the Jinja templates.
Each template that contains UI text defines a translation dictionary keyed by
language code and selects the entry for the page's language. Sphinx exposes
the current language as the language variable (set per locale in each
conf.py: source/conf.py is en, locales/es/conf.py is es,
locales/fr/conf.py is fr). The templates fall back to English when a
language is missing.
The templates that hold translatable strings are:
source/_templates/partials/header.html— nav links + language picker labelssource/_templates/partials/search.html— search heading, description, placeholder, buttonsource/_templates/partials/community_questions.html— forum and academy sectionssource/_templates/layout.html— breadcrumb, "back to top", feedback prompt, footer
A typical block looks like this:
{% set lang = language or 'en' %}
{% set translations = {
'en': { 'heading': 'What do you need help with?' },
'es': { 'heading': '¿Con qué necesitas ayuda?' },
'fr': { 'heading': 'Comment pouvons-nous vous aider ?' }
} %}
{% set t = translations.get(lang, translations['en']) %}
<h1>{{ t.heading }}</h1>To update or correct a UI string: edit the matching value in that template's translation dictionary.
To add a brand-new UI string: add the key to every language in the
dictionary (English is required as the fallback) and reference it with
{{ t.<key> }} in the markup.
To add a whole new language (e.g. de):
- Add the language code to
LOCALESin theMakefile. - Create
locales/de/conf.pywithlanguage = 'de'. - Add a
'de'entry to the translation dictionary in each template listed above, and add the language to the picker inheader.html(thelanguageslist and thecurrent_labelmap). - Translate the
locales/de/content files as described in "Adding new translations".
The dropdown language picker is rendered in
source/_templates/partials/header.html and styled in
sass_source/sass/_header.scss (the .language-picker__* classes). It links
to the current page in each locale using relative paths, so it works from any
page depth. Remember to run npm start after changing the SCSS so the
compiled CSS in source/_static/css/ is regenerated.
Note: the homepage "Topics" heading uses a
.. rst-class:: topics-sectiondirective (instead of relying on the auto-generated#topicsid) so the homepage grid styling survives translated headings such as "Temas" / "Sujets". Keep that directive when editing any locale'sindex.rst.
We build our theme atop Read The Docs theme by replacing their CSS with our own (which is a heavily modified copy of theirs).
To develop the theme:
- Install NPM dependencies:
npm install - Build:
- To watch for style changes use
npm run dev - To build the styles once use
npm start
Useful links:
- Jinja - templating language used in
.htmlfiles - Official Sphinx documentation
- Alabaster theme source code
- Sphinx source code
- Basic Sphinx theme source code
Two icon sets are available for use in articles. If you need to figure out which icon KPI uses, open up your browser's "inspect" command (for Chrome and Firefox, right click on page and choose 'inspect'). Mouse over the icon you are interested in and you can see whether it uses the k-icon or tabler-icon prefix.
KoboToolbox's legacy icon set, generated from SVGs in the KPI repository. Use these for any icon that has a k-icon- class.
<i class="k-icon k-icon-trash"></i>A visual reference of all available KPI icons (with names, minus k-icon- prefix) is available on KPI's Storybook page.
KPI now also uses Tabler Icons for newer UI elements. Use ti-outline for outline style and ti-filled for filled style, along with the icon name.
<i class="ti-outline ti-logout"></i>
<i class="ti-filled ti-trash"></i>The icon name can be found using the in-browser inspect method described above. The class names work slightly differently in the docs repo compared to KPI: If you see tabler-icon-world-filled in KPI, that will become ti-filled ti-world for use in this docs repo.
Only icons listed in scripts/tabler-icons-list.json are available. When KPI adds a new Tabler icon that needs to be referenced in the docs, add its kebab-case name to the appropriate list in that file and run npm run generate-icons.