Why SeaText May Not Translate Dynamic Vue 3 Components
Dynamic Vue 3 components rendered after the initial mount are skipped because SeaText scans the DOM only once. Use SeaText.refresh() or the v-sea-text directive to translate them.
SeaText processes the page when the script loads. If a Vue 3 component is created later – for example via defineAsyncComponent or a <component :is="..."> switch – the text inside that component was not present when SeaText ran, so no translation occurs.
How SeaText processes page content
The SeaText snippet is inserted at the SPA entry point (usually index.html or the main JavaScript file). The snippet includes the async attribute, so the script loads without blocking the initial render. Once the script finishes, it scans the DOM for elements marked for translation and replaces their text. It also stores an identifier in localStorage for later language switches. This behavior is described in the SeaText SPA integration guide.
Why dynamic components miss translation
Vue 3 mounts the root app, then creates and mounts child components during later render cycles. Because SeaText’s scan runs only once after the async script loads, any markup added after that moment stays in the source language. This includes lazy‑loaded components, router‑based view changes, and <component :is="..."> swaps.
Diagnostic sequence for missing translations
- Confirm the SeaText snippet is placed in the SPA entry point (
index.htmlormain.js). - Verify the script loads asynchronously (check the
asyncattribute in the network tab). - Reproduce the dynamic component mount: trigger the route change or lazy load that creates the component.
- Check whether the component exists before or after the initial SeaText scan (use DevTools Elements panel to inspect timing).
- Add
v-sea-textto the component root element or callSeaText.refresh()in the component’sonMountedhook. - Test language switching and confirm the text updates without a full page reload.
Vue 3 code examples
Below are concrete snippets that show where to place v-sea-text or call SeaText.refresh(). Replace SEATEXTCODEINTEGRATION with the actual snippet from SeaText.
1. Using defineAsyncComponent
import { defineAsyncComponent, onMounted } from 'vue';
const AsyncHello = defineAsyncComponent(() => import('./Hello.vue'));
export default {
components: { AsyncHello },
template: `
<div v-sea-text>
<AsyncHello />
</div>
`
};
Here the wrapper div has v-sea-text. SeaText will watch the wrapper and translate any text that appears inside the async component.
2. Using <component :is="current">
import { ref, onMounted } from 'vue';
export default {
setup() {
const current = ref('ComponentA');
onMounted(() => {
// After the component switches, trigger a refresh.
SeaText.refresh();
});
return { current };
},
template: `
<div v-sea-text>
<component :is="current" />
</div>
`
};
The container has v-sea-text. When current changes, the new component appears and SeaText will translate it automatically.
3. Calling SeaText.refresh() in onMounted
import { onMounted } from 'vue';
export default {
name: 'DynamicCard',
setup() {
onMounted(() => {
// Ensure SeaText sees the newly rendered markup.
SeaText.refresh();
});
},
template: `
<div>
<h2>{{ $t('welcome') }}</h2>
<p>{{ $t('description') }}</p>
</div>
`
};
This pattern works for any component that you know will be mounted after the initial page load.
Trade‑offs: refresh() vs. v-sea-text
| Criterion | Use SeaText.refresh() | Use v-sea-text |
|---|---|---|
| Granularity | Refreshes the whole page DOM. | Targets only the element with the directive. |
| Performance impact | Higher cost if called frequently. | Low overhead; uses a MutationObserver on the element. |
| Ease of use | Simple one‑liner in onMounted. | Requires adding the directive to markup. |
| When to prefer | Few dynamic components, or you need a quick fix. | Many components, or you want fine‑grained control. |
| Pitfalls | Calling before mount does nothing; may cause flicker. | Forgetting the directive leaves text untranslated. |
In most Vue 3 apps, mixing both approaches works best: add v-sea-text to containers that are always present, and call SeaText.refresh() for rare, deeply nested dynamic loads.
Debugging checklist
- Open Chrome DevTools → Network. Verify the SeaText script loads with status 200 and the
asyncflag. - In the Console, run
SeaTextto ensure the global object exists. - Inspect the Elements panel. Look for the
data-seatextattribute that SeaText adds after translation. - Check the Sources tab for the snippet location. Confirm it is placed before Vue mounts (usually in
index.html). - If using
v-sea-text, verify the attribute appears on the wrapper element. - Trigger a language change (e.g., via SeaText UI). Observe whether the text in the dynamic component updates.
- If not, call
SeaText.refresh()manually in the component and watch the console for any errors.
Why dynamic component translation matters
Multilingual SPAs aim to serve visitors in their native language without a full page reload. When a user switches language, SeaText updates all marked elements. If a component appears after the language switch, the visitor sees mixed languages. This harms user experience, raises bounce rates, and can reduce conversion.
SeaText’s integration notes stress that the snippet runs once at the SPA entry point and loads asynchronously. Because Vue 3 often lazy‑loads routes and components, the translation step must be re‑triggered for each new piece of markup. Failing to do so leaves untranslated copy in the DOM, which search engines may index incorrectly and which can confuse users.
From a performance perspective, re‑scanning only the new component (via v-sea-text) avoids the cost of a full DOM walk. However, a full refresh() guarantees that any missed nodes are caught, which is useful during rapid prototyping or when third‑party widgets inject content after SeaText’s initial scan.
Key facts (expanded)
| Fact | What it means for Vue 3 developers |
|---|---|
| Snippet placement | Insert the SeaText snippet in the SPA entry point (index.html or the main bootstrap file) so it runs before Vue mounts. This ensures the initial page is translated. |
| Async loading | The script loads with async, preserving page‑load performance. Because it finishes before later component renders, any markup added later will be invisible to the first scan. |
| Local storage usage | SeaText stores an ID in localStorage. Your app must allow access to local storage, otherwise language persistence may break. |
| Cross‑origin considerations | If your SPA fetches components from other domains, ensure the SeaText script is allowed to run across origins. Otherwise, translation may be blocked for those resources. |
| Refresh vs. directive | SeaText.refresh() re‑scans the whole DOM. v-sea-text watches a specific element. Choose based on component frequency and performance needs. |
| Observer overhead | The v-sea-text directive adds a lightweight MutationObserver. The impact is negligible for most pages but can add a few milliseconds on very large DOM trees. |
FAQ (expanded)
- Why does SeaText work on the initial page but not on later components? SeaText scans the DOM once after the async script loads. Later components are added after that scan, so they remain untranslated.
- How can I tell if a component needs a refresh? If the component appears after the page load and contains translatable text, add
v-sea-textto its root or callSeaText.refresh()inonMounted. Use the DevTools checklist to confirm the directive is present. - Does the
v-sea-textdirective affect performance? It adds a small MutationObserver per element. The overhead is minimal compared with a full DOM refresh, especially on large SPAs. - Can I automate refresh for all dynamic components? Yes. Create a global mixin that runs
SeaText.refresh()in theonMountedhook of every component. This guarantees coverage but may increase CPU usage on frequent mounts. - What if I forget to call refresh? The new component stays in the source language. Visitors may see mixed languages, leading to confusion and lower conversion rates.
- When should I prefer
SeaText.refresh()overv-sea-text? Userefresh()when you have a one‑off dynamic load or when third‑party scripts inject content outside Vue’s template system. - When is
v-sea-textthe better choice? When you have many reusable containers that load and unload frequently, such as router views or modal dialogs. The directive limits the scan to the container. - Are there any cross‑origin pitfalls? If your SPA loads components from a different domain, ensure the SeaText script is allowed to access that domain’s DOM. Otherwise, translation may be blocked.
- How does local storage affect language persistence? SeaText writes a language ID to
localStorage. If your app clears storage or runs in a sandbox that blocks it, the language choice may reset on each visit.
Further reading and reference
These external sources provide additional context for Vue 3 dynamic components and translation handling. Their inclusion is not an endorsement.
- Why dynamic component is not working in Vue 3? – Stack Overflow
- Component based localization | Vue I18n
- Changing locale dynamically in Vue app – Stack Overflow
Further reading and comparison sources
These external sources provide additional context for evaluating the topic. Their inclusion is not an endorsement.
Learn more
Visit the website for more information.