OstimGPT
A locally hosted Retrieval-Augmented Generation chatbot answering questions from university sources.
A locally hosted automatic translation system for an Odoo 18 university website. I developed a reusable Ollama client service, a translation job platform with tracking and analytics, an HTML chunking pipeline that recombines translated content while preserving page structure, configuration and security settings pages, prompt engineering, rate limiting and multilingual support, alongside testing and technical documentation.
This project added automatic translation to an Odoo 18 university website, running entirely on locally hosted AI models through Ollama rather than a commercial translation API.
Translating a website is not the same problem as translating text. Page content is HTML: it carries structure, links, formatting and attributes that must survive the round trip intact. The core of the work was a pipeline that divides HTML into translatable chunks, translates them, and recombines the results without damaging the page.
I contributed the reusable model client, the job platform around it, the chunking and recombination pipeline, the administrative configuration surfaces, and the prompt engineering and rate limiting that made the system usable in practice.
A university website serves audiences who do not share one language. Keeping a multilingual site current by hand means every content change becomes several content changes, and translations drift out of date between updates.
The Digital Transformation Coordination Office ran the university’s Odoo 18 website. The goal was to make translation something the platform could perform itself, on the university’s own infrastructure.
Website content is structured HTML, and language models work on text. Sending a whole page to a model returns damaged markup; sending it in fragments loses the context needed to translate well. The system had to reconcile those two facts, and do it repeatedly and observably.
My Role
I developed a reusable Ollama client service and built a translation job platform on top of it, with job tracking and analytics. I developed the HTML chunking pipeline that divides page content into translatable units, and the recombination step that reassembles translated sections while preserving page structure. I created the configuration and security settings pages, applied prompt engineering to the translation requests, implemented rate limiting and added multilingual support. I also contributed testing and technical documentation.
Team Context
This system was developed within the university’s software development team in the Digital Transformation Coordination Office, under the same Scrum and CMMI process standards as the office’s other projects. I contributed the components described here; the surrounding Odoo website, its deployment and its content are the university’s and the wider team’s responsibility.
The pipeline treats an HTML page as a structure with translatable content inside it, rather than as a block of text. Structure is preserved on the way out and restored on the way back, and the slow model work in between is managed as tracked jobs.
Page HTML enters a chunking pipeline that divides it into translatable units. Each unit is sent through a reusable Ollama client service to a locally hosted model, using prompts written to translate content while leaving markup untouched, with rate limiting applied between the platform and the model. Translated units are recombined into the original page structure. The whole sequence runs as a tracked job, with job tracking and analytics feeding administrative views, and configuration and security settings pages controlling behaviour.
One service through which every part of the system talks to the local model.
Divides page content into units that fit a model request without losing context.
Translated sections are reassembled with the page’s markup and formatting intact.
Long-running translation work is managed as jobs rather than as requests.
Administrators can see what ran, and what happened when it did.
Behaviour is adjustable from administrative pages rather than in code.
Request volume is kept within what local model capacity can serve.
The pipeline handles more than a single target language.
Passing whole HTML pages through a language model returns damaged markup — tags dropped, attributes rewritten, structure altered.
I built the pipeline to divide HTML into chunks and recombine the translated results into the original structure, and engineered the prompts so the model’s task is translating content rather than reproducing markup.
Chunking too aggressively strips away the context a translator needs; chunking too little exceeds what a single request can handle.
Chunk boundaries were chosen to fit a model request while keeping units coherent enough to translate sensibly, which is a balance rather than a fixed rule.
Translating a whole site is slow, long-running work that does not fit a request-response shape.
I built a job platform around the translation pipeline, with tracking and analytics, so work could be started, observed and reasoned about after the fact.
Local model capacity is finite, and unconstrained demand degrades everything sharing it.
I implemented rate limiting between the platform and the model, and surfaced the relevant settings in a configuration page so limits could be tuned without a code change.
| Decision | Alternative considered | Why |
|---|---|---|
| Use locally hosted models through Ollama. | A commercial translation API. | Website content stays on university infrastructure, there is no per-word cost, and the system has no external dependency. The trade is throughput and model choice bounded by local hardware — which is exactly why rate limiting was needed. |
| Chunk and recombine HTML rather than translating whole pages. | Sending complete pages to the model. | Chunking adds a recombination step and its own edge cases, but it is what keeps page structure intact and keeps each request within what the model can handle reliably. |
| Manage translation as tracked jobs. | Translating synchronously on request. | Jobs add a platform to build and maintain, but long-running work needs to be observable and reviewable after it finishes. A synchronous request gives you neither. |
| Wrap model access in one reusable client service. | Calling the model directly from each caller. | A single client is where rate limiting, prompt handling and error behaviour can live once. Direct calls would have spread all three across the codebase. |
The Odoo 18 website can translate its own content using locally hosted models, with page structure preserved through the chunking and recombination pipeline.
Translation work runs as tracked jobs with analytics, so administrators can see what was translated and how the run completed.
Configuration and security settings pages let the system be adjusted without code changes, and rate limiting keeps demand within local model capacity.
Testing and technical documentation were contributed alongside the implementation.
Screenshots to be added
Have a software, AI, RAG, or web application project in mind? Let’s discuss what you need and determine the right technical approach.