LiveSvelteGettext (LiveSvelteGettext v0.2.0)
View SourceCompile-time translation extraction for Phoenix + Svelte applications.
This module provides a proof-of-concept solution for using Phoenix Gettext in Svelte components. It was extracted from a real project and addresses the challenge raised in live_svelte#120.
The Approach
Uses Elixir macros at compile time to:
- Scan
.sveltefiles forgettext()andngettext()calls - Generate Elixir code that integrates with
mix gettext.extract - Preserve accurate source references (e.g.,
assets/svelte/Button.svelte:42) - Runtime translations:
.svelte_translationscomponent renders translations as JSON- Lazy initialization on first
gettext()orngettext()call - Translation access via
all_translations/1 - Plural forms read from your
.pofiles, selected with the locale's own plural rules
No generated files are committed - everything happens at compile time using
@external_resource for automatic recompilation when Svelte files change.
Quick Start
1. Setup (using Igniter installer)
mix igniter.install live_svelte_gettextThis automatically creates a separate module for Svelte translations:
defmodule MyAppWeb.Gettext.SvelteStrings do
use Gettext.Backend, otp_app: :my_app
use LiveSvelteGettext,
gettext_backend: MyAppWeb.Gettext,
svelte_path: "assets/svelte"
endImportant: Do not add use LiveSvelteGettext to your main Gettext backend
module, as this creates a circular dependency. Always use a separate module.
2. Install NPM package
npm install live-svelte-gettext
3. Add translations to your template
In your LiveView or layout:
<.svelte_translations />
<.svelte name="MyComponent" props={%{...}} />4. Use translations in Svelte (zero boilerplate!)
<script>
import { gettext } from 'live-svelte-gettext'
</script>
<h1>{gettext("Welcome to our app")}</h1>
<p>{gettext("Hello, %{name}", { name: "World" })}</p>That's it! Translations are automatically initialized on first use - zero setup!
How It Works
Compile time (when you run mix compile):
- The
use LiveSvelteGettextmacro scans all.sveltefiles insvelte_path - Regex patterns extract
gettext()andngettext()calls with file:line metadata - Generated Elixir code includes:
@external_resourceattributes (triggers recompilation on file changes)- Calls to
CustomExtractor.extract_with_location/8(preserves Svelte source locations) - An
all_translations/1function for runtime
- When you run
mix gettext.extract, it discovers these generated calls - The
CustomExtractormodifiesMacro.Envto inject accurate Svelte file:line into.potfiles
Runtime (when the page loads):
- The
<.svelte_translations />component fetches translations and renders JSON in a<script>tag - Translations are lazily initialized on first
gettext()orngettext()call - Svelte components call
gettext()andngettext()- interpolation happens in the browser
Configuration Options
:gettext_backend(required) - The Gettext backend module to use:svelte_path(required) - Path to the directory containing Svelte files (relative to project root)
Runtime API
After using this module, you'll have access to:
all_translations(locale)- Returns a map of all translations for the given localetranslation_payload(locale)- The same translations plus the locale and its plural rules; this is what<.svelte_translations />renders__lsg_metadata__/0- Debug function showing extracted strings and source files
Advanced Usage
Manual Initialization (for edge cases)
If you need more control (e.g., multi-tenant apps, custom loading logic), you can manually pass translations to Svelte components:
# In your LiveView:
def mount(_params, _session, socket) do
payload = MyAppWeb.Gettext.SvelteStrings.translation_payload("en")
{:ok, assign(socket, :translations, payload)}
end
# In your Svelte component (Svelte 5):
<script>
import { initTranslations, gettext } from 'live-svelte-gettext'
let { translations } = $props()
initTranslations(translations)
</script>
<h1>{gettext("Welcome")}</h1>initTranslations/1 also accepts the plain map returned by
all_translations/1, but translation_payload/1 additionally carries the
locale and its plural rules, which the client needs to pick the right plural
form.
Note: Most users should use the automatic lazy initialization shown in Quick Start.
Summary
Functions
Macro for setting up LiveSvelteGettext in your Gettext backend.