Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Template I18N Bundle Laravel Package

ruwork/template-i18n-bundle

Symfony bundle that brings internationalization to templates, letting you translate template strings and manage locale-aware content. Integrates with Symfony's translator and Twig to keep multi-language templates clean and organized.

View on GitHub
Deep Wiki
Context7

Getting Started

First, a framework reality check: ruwork/template-i18n-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/template_i18n.php. If you are working in a Laravel codebase you cannot composer require this and expect it to boot — you would be porting concepts, not code. The rest of this assessment assumes a Symfony application (or a deliberate evaluation of whether to port).

Minimal steps in a Symfony app:

composer require ruwork/template-i18n-bundle

Then register the bundle — config/bundles.php on Symfony 4+, AppKernel::registerBundles() on Symfony 3:

return [
    // ...
    Ruwork\TemplateI18nBundle\RuworkTemplateI18nBundle::class => ['all' => true],
];

Where to look first: the bundle is small, so read the DependencyInjection/Configuration.php and the bundle's README in that order. The config root key and the service IDs it wires up are the real documentation — the README on a 2018 bundle with 0 stars is typically a stub. Identify (a) the locale/fallback options, (b) which service is the template resolver/loader, and (c) whether it decorates Twig's loader or exposes a standalone resolver.

First use case: localized transactional email templates. You have templates/email/welcome.html.twig and want templates/email/welcome.ru.html.twig (or a locale subdirectory) selected automatically from the request locale, with a fallback to the default. That is the canonical reason to reach for a template-i18n bundle, and it is the fastest way to confirm the package does what you think it does.

// quick smoke test in a controller
$html = $this->renderView('email/welcome.html.twig', ['user' => $user]);
// with the request locale set to 'ru', you expect the .ru variant to win

If that doesn't behave as expected on the first try, stop and read the loader before building anything on top of it.

Implementation Patterns

Locale-aware template resolution. The bundle's core value is picking a template variant from the active locale. Wire the locale from the request ($request->getLocale()) or from the security/user context for async work (queued mailers, console commands) where there is no request. Always set it explicitly before rendering:

$renderer->render($template, $parameters, $locale); // or via RequestContext / LocaleAwareInterface

Fallback chain over "one file per locale." Do not duplicate the entire template tree per locale. Structure it so the base template holds layout and the variant only overrides blocks or strings:

templates/email/welcome.html.twig       # base, default locale
templates/email/welcome.ru.html.twig    # overrides only what changes

This keeps drift manageable and makes diff review sane when marketing changes copy in one locale.

Separate strings from structure. Use this bundle for template selection, and Symfony's Translator ({{ 'email.welcome.subject'|trans }}) for string translation. Mixed responsibilities are the number-one source of "why is my Russian email half-English" bugs. In Laravel terms: this bundle is a view-resolver concern; __() is a translation concern — same split.

Service injection over Twig trickery. Inject the resolver/rendering service into mailers, notification services, and event listeners rather than calling Twig globals from templates. Template selection is application logic, and it is far easier to test when it lives in a service:

final class WelcomeMailer
{
    public function __construct(private TemplateI18nRenderer $renderer) {}

    public function send(User $user): void
    {
        $body = $this->renderer->render('email/welcome.html.twig', ['user' => $user], $user->getLocale());
        // ...
    }
}

Test the locale matrix explicitly. A small data-provider test per critical template (default, ru, unknown locale → fallback) catches most regressions. Assert on the rendered output, not on which file was loaded — the latter couples you to internals.

Laravel port pattern (if you go that way). The equivalent is a custom view resolver or a helper that checks view()->exists() against a locale-suffixed name before falling back:

function localized_view(string $name, array $data = [], ?string $locale = null): View
{
    $locale = $locale ?? app()->getLocale();
    foreach (["{$name}.{$locale}", $name] as $candidate) {
        if (view()->exists($candidate)) {
            return view($candidate, $data);
        }
    }
    throw new InvalidArgumentException("No view for [{$name}]");
}

That is roughly 10 lines and covers 90% of what this bundle offers, which is worth weighing against adopting an unmaintained dependency.

Gotchas and Tips

  • Archived, last released 2018-07-20. No security patches, no Symfony 5/6/7 support, PHP 7-era constraints. On any modern Symfony this will likely fail composer resolution or fail at runtime on removed APIs. Pin-and-patch only if you accept owning the code.
  • Zero stars, zero dependents. There is no community to answer questions, no issue history to search, and no Stack Overflow corpus. Every problem is your problem. Treat the source as the documentation.
  • Bundle registration failures look like "class not found" or silent no-ops. If templates aren't localized, first verify the bundle is actually in bundles.php, then bin/console cache:clear. Symfony caches bundle metadata aggressively.
  • Template caching masks changes. Twig caches compiled templates keyed by path. When you add a new locale variant at runtime or in a deploy, clear the cache (cache:clear / cache:pool:clear) — otherwise the fallback template keeps winning and you'll chase a ghost.
  • Locale context is absent in console/queue workers. Symfony's locale is request-scoped. Mailers and async listeners must receive and set the locale explicitly; assuming the ambient locale is a classic production-only bug.
  • Don't conflate with Translator. If you find yourself putting whole sentences into template files per locale, you are fighting the tool. Structural variants belong here; strings belong in translations/.
  • Extension point: the resolver/loader is almost certainly a normal Symfony service. Prefer decorating it (Symfony's service decoration) over forking the bundle — you keep upgrade paths open and can drop the bundle later by deleting the decoration.
  • Exit criteria. Because the package is tiny and unmaintained, set a threshold: if you need more than locale-fallback template selection, reimplement the ~50 lines yourself. For a 0-star archived bundle, "own the code" is usually cheaper than "depend on the code."
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle