Phrase Discovery
Loco automatically discovers translatable text on your page using a TreeWalker DOM traversal plus a MutationObserver for live updates.
What gets discovered
1. Plain text nodes
Any visible text between block elements.
<p>Hello, welcome to our app.</p>
→ key: "Hello, welcome to our app."
2. Input values
Button, submit, and reset input values.
<input type="submit" value="Save Changes" />
→ key: "Save Changes"
3. Input attributes
placeholder, title, and aria-label attributes.
<input placeholder="Search..." aria-label="Search field" />
→ two separate phrases: "Search..." and "Search field"
4. Mixed content (variable slots)
Text with inline child elements (<var>, <strong>, <time>, <span>, <em>).
<p>You have <strong>5</strong> unread messages</p>
→ key: "You have {{number:0}} unread messages", slot: { type: 'number', index: 0, value: '5' }
What gets filtered out
Text nodes are skipped if:
- Fewer than 2 characters
- Exceed 4096 characters
- Only punctuation or symbols
- Already contain
{{type:N}}tokens (translation artifacts) - Inside a blocked tag:
<script>,<style>,<noscript>,<textarea>,<code>, etc. - The element has
data-notranslateattribute - The element or an ancestor is hidden
Context tracing
Each phrase records a context string that traces its DOM location for disambiguation:
"button.delete | form.login, email-field"
This lets you translate the same word differently depending on where it appears on the page. Context depth is configurable in Dashboard → Settings.
Dynamic content (MutationObserver)
After the initial scan, a MutationObserver watches for newly added DOM nodes. When new content appears (e.g., from a SPA route change or an AJAX response), Loco automatically discovers and registers those phrases too — no manual trigger needed.
You can pause/resume it:
Loco.stopScan(); // pause
Loco.startScan(); // resume
Loco.rescan(); // force a re-scan right now
Large page optimization
For pages with many text nodes, Loco uses collectPhrasesAsync — a batched traversal that yields to the browser between batches (100 nodes per batch) to avoid freezing the UI during the initial scan.