Full page translation
translatePage() translates an entire HTML document in one pass. It automatically:
- Sets the
langattribute on<html> - Ensures
<meta charset="utf-8">exists - Translates
<title>, meta description, OpenGraph tags, Twitter cards - Extracts and translates body content (phrases and content blocks)
- Registers new phrases automatically (if write key)
- Falls back to original content when translations are missing
ob_start();// ... your application generates the HTML page ...$html = ob_get_contents();ob_end_clean();
$client = new Client();$client->setLocale('es-es');echo $client->translatePage($html, 'homepage');Locale detection
Section titled “Locale detection”$client->setLocale('fr-ca');
$locale = $client->getLocale(); // detected from HTTP_ACCEPT_LANGUAGE, or project's base_locale
echo (new Client())->setLocale('de-de')->translatePage($html, 'contact');How it classifies content
Section titled “How it classifies content”- Single-phrase blocks are registered as simple phrases (
<p>Hello</p>→ phrase"Hello"; inline formatting on a single phrase is preserved) - Multi-phrase blocks are registered as content blocks (
<nav><a>Home</a><a>About</a></nav>) - Head section is processed for translatable meta tags
translate="no"is respected to skip elements- Script/style tags are never processed
The key distinction: if a block element contains exactly one phrase that matches its text content, it’s a simple phrase. Multiple phrases (from text nodes or attributes) = content block.
With a read-only API key, translatePage() translates content that has existing translations, silently skips registration of new phrases, and falls back to original content for untranslated items.
Per-section categories with data-langsys-category
Section titled “Per-section categories with data-langsys-category”By default, all phrases on a page use the category passed to translatePage(). Override per section:
<header data-langsys-category="header"> <h1>Welcome</h1> <!-- category: header --></header><main> <p>Hello World</p> <!-- category: homepage (default) --> <section data-langsys-category="widgets/contact"> <h2>Contact Us</h2> <!-- category: widgets/contact --> </section></main>Categories are inherited — child elements use their parent’s category unless they specify their own. Empty string (data-langsys-category="") falls back to __uncategorized__.
Selector-based category mapping
Section titled “Selector-based category mapping”echo $client->translatePage($html, 'homepage', [ 'nav li' => ['category' => 'Navigation'], '.action, .btn' => ['category' => 'UI Elements'], 'section.contact' => [ 'category' => 'Contact Form', 'overrideParentElementCategory' => true, ],]);Supported selectors: tag, class, ID, tag+class, attribute, descendant, child, and comma-separated lists.
Priority order (highest to lowest):
- Selector with
overrideParentElementCategory: true - Element’s
data-langsys-categoryattribute - Inherited category from parent
- Selector with
overrideParentElementCategory: false - Default category parameter
__uncategorized__
overrideParentElementCategory defaults to false so HTML attributes win unless you opt in.
Forcing a content block with data-langsys-contentblock
Section titled “Forcing a content block with data-langsys-contentblock”<section data-langsys-contentblock="true"> <h2>Contact Us</h2> <p>Fill out the form below</p></section>Truthy values: "true", "1", "yes", or any non-empty string (but not "false", "0", or ""). Use it for complex widgets that should be translated as a unit.
See also keeping a run together and excluding content.