1yFZA7ezVoz2PPt4dxFdI0Q
About this Series
Frontend engineering at Palantir goes far beyond building standard web apps. Our engineers design interfaces for mission-critical decision-making, build operational applications that translate insight to action, and create systems that handle massive datasets — thinking not just about what the user needs, but what they need when the network is unreliable, the stakes are high, and the margin for error is zero.
This series pulls back the curtain on what that work really looks like: the technical problems we solve, the impact we have, and the approaches we take. Whether you’re just curious or exploring opportunities to join us, these posts offer an authentic look at life on our Frontend teams.
In this blog post, Rahma, a frontend engineer based in CA, shares how building Dossier’s translation mode — a recent project she tackled at Palantir — deepened her appreciation for frontend engineering, while tackling challenges of secure, multilingual collaboration for global teams.
When people think about Palantir, they often imagine impressive data pipelines, backend wizardry, and compelling ontologies — but there is a lot more to the story, especially if you care about frontend engineering.
Recently, I worked on a project to bring read-only translation mode to Dossier, one of our collaborative text editor applications. This feature is particularly important for our defense and intelligence customers, who often operate in multilingual and highly restrictive environements. We’ve also implemented translation in our presentation tool, our messaging tool, and our commenting library, creating an ecosystem of multilingual collaboration across all our communication apps.
In this post, I’ll share how we built Dossier’s translation mode, the technical challenges we faced, and why it’s a great example of the kind of end-to-end, high-impact frontend that keeps me excited and motivated at work.
In almost any important news headline you see today, you’ll see how most operations require deep, multi-national collaboration. These different partner nations often speak different languages, but we can’t let that be a barrier to high-signal collaboration and teamwork. Users, analysts, planners, and operators are working with global teammates more than ever. But many of them are on closed or classified networks, where standard, public, consumer translation tools simply aren’t available or allowed.
To make our productivity suite truly collaborative, we needed to bring translation into Dossier, our rich-text document editor, and make it as seamless as possible. We already had rolled out translation features in Chat and Slides, but Dossier posed a new set of challenges. Unlike chat messages or slide decks, Dossier documents can be hundreds of pages long, full of complex formatting, tables, and live collaborative edits. Our goal was to let users toggle into a translation mode, see the entire document in their chosen language, and still interact with the content (copying text and adding comments) without losing context or performance.
Our vision was simple: with one click, users could view any Dossier in a translated, read-only mode. Under the hood, this required:
1. Shared components
We’d already built translation UI components for Slides and Chat, so we extracted these into a shared library to ensure a consistent experience across apps. But Dossier’s document model is significantly more complex — we had to extend these components to handle deeply nested rich-text structures, tables, and custom widgets.
2. Redux state for translation
Translation isn’t a feature you can bolt on — it touches the entire application. A user’s language preference, the loading state of every translated block, caching, toggling on and off without losing your place in the document — all of this needs to be coordinated globally. So we were intentional about how we modeled state, adding a dedicated slice to Dossier’s Redux store to manage it cleanly.
export interface TranslationsCacheValue {
originalText: string;
translatedText: IAsyncLoaded<string>;
}
export interface TranslationsCache {
[elementId: string]: TranslationsCacheValue;
}
export interface TranslationState {
isInTranslationMode: boolean;
supportedLanguages: IAsyncLoaded<LanguageMetadata[]>;
translations: TranslationsCache;
detectedLanguage?: string;
sourceLanguage?: string;
targetLanguage?: string;
} This state is also responsible for tracking which blocks are loading, succeeded, or failed, so we can shown detailed feedback to the user.
3. Chunking: balancing translation quality and speed
Translation has to feel fast and seamless, even for large multi-page Dossiers. Sending the entire document at once would leave users staring at a loading screen; translating word-by-word or sentence-by-sentence would be faster but degrade quality, since most translation models rely on broader context to produce natural results.
We settled on chunking at the block level — paragraphs, list items, table cells — which strikes the right balance. Users see incremental progress as blocks appear in their translated form as soon as they’re ready, rather than waiting for the whole document.
For the next version of chunking, we’d like to tackle a few interesting edge cases:
For now, we rolled out our block-level chunking, but there is plenty of of room for future improvement as we get more usage data and feedback.
4. Lazy, incremental translation
In addition to our strategy of chunking, we also had to think about which chunks to prioritize for 100+ page documents. We used the Intersection Observer API to “lazy load” translations. Only the blocks currently visible in the user’s viewport are sent to LMS for translation. As users scroll, new blocks are translation on demand.
// IntersectionObserver API hook for "has entered screen" detection
function useHasEnteredScreen(ref) {
const [hasEntered, setHasEntered] = React.useState(false);
useEffect(() => {
if (hasEntered || ref.current == null) return;
const el = ref.current;
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
setHasEntered(true);
observer.disconnect();
}
});
observer.observe(el);
return () => observer.disconnect();
}, [hasEntered]);
return hasEntered;
}
This keeps the UI responsive and avoids hammering the backend with huge requests. We often have many users accessing the same document at the same time, so we implemented batching, debouncing, and caching to avoid re-translating the same block multiple times.
Each paragraph or block shows a status indicator: loading, failed, or translated. If translations fail due to translation resource constraints or model limitations, users can retry failed translations with a click.
5. Handling collaboration & live edits
Dossier is a collaborative editor, multiple users can edit the same document in real time. If someone edits a paragraph while you’re viewing the translation, we detect the change, invalidate the cached translation, and reloads the updated text for translation.
We use a per-block cache (keyed by element ID) to track translation status. When a block is edited, the cache entry is invalidated and translation is re-triggered as long as the block is still on the user’s screen. This ensures that the translated view is always up to date, even as the document evolves.
6. Stripping formatting for translation quality
One of the hard tradeoffs: to get the best translation results, we strip all inline formatting (bold, italics, hyperlinks, mentions) before sending text to LMS. This is because translation models work best when given the full, unbroken sentence context.
If we were to split text around formatting, say translating “I love frontend engineering” by sending “I” and “frontend engineering” separately, and “love” as a bolded chunk, the translation model loses the sentence structure. This can produce incorrect or nonsensical results, especially in languages where word order or agreement depends on the whole sentence.
Consider the English sentence:
I love frontend engineering
Suppose we tried to preserve formatting by splitting:
If we translate these fragments separately into French:
If we stitch it back together:
Je amour ingénierie frontend
This is not correct and doesn’t make sense, but if we send the full sentence to the translation model:
“I love frontend engineering.” → “J’adore l’ingénierie frontend.”
Here, “J’adore” is the correct verb form and the sentence flows naturally. This is why preserving sentence context is critical for translation quality, and why we currently strip formatting before translation, otherwise users could end up with confusing or misleading results.
That is why, for now, the translated view is plain text, but we’re exploring more ways to preserve more formatting as model and API support improves. For example, future support for HTML or Markdown-aware translations.
The project covered many aspects of frontend development:
Today, users can toggle translation mode in any Dossier, select source and target languages, and instantly see a translated, read-only version of their document. All text content is “lazy” translated as you scroll, and any incoming edits are re-translated in real time.
As a frontend engineer who loves building real products that solve real problems, especially under constraints like security, performance and collaboration, projects like Dossier translation keep me motivated and excited to work. I really enjoyed balancing the technical and performance constraints with a delightful experience for users and leveraging modern web APIs to deliver Dossier translation.
If this sounds like the kind of project and impact you’re interested in, check out our open roles today: https://www.palantir.com/careers/open-positions/. Our most applicable frontend postings are the “Web Application Developer” roles. We’re also hiring for these two specific roles right now: Software Engineer — Core Interfaces (Palo Alto), and Software Engineer — Defense Applications (DC).
Frontend Engineering at Palantir: Engineering Multilingual Collaboration was originally published in Palantir Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.
submitted by /u/ai_happy [link] [comments]
FastAPI has become one of the most popular ways to serve machine learning models because…
Apple is advancing AI and ML with fundamental research, much of which is shared through…
Many organizations are archiving large media libraries, analyzing contact center recordings, preparing training data for…
Last year at Google Cloud Next ‘25, we asked you to imagine a new future…
“To be clear, we were never approached … nor were we in any discussions regarding…