Skip to content

Commit 0060dd4

Browse files
committed
fix: core and trees translations never loaded under any locale
Found while fixing the identical bug shape reported in php-tenant. Both LangServiceProvider::loadTranslations() and Trees\Boot::boot() registered their translation hint path as the locale subfolder itself (__DIR__.'/en_GB' and __DIR__.'/Lang/en_GB') instead of its parent. loadTranslationsFrom() appends "/{locale}/{group}.php" to whatever hint it is given, so Laravel was looking for src/Core/Lang/en_GB/en_GB/core.php and src/Mod/Trees/Lang/en_GB/en_GB/trees.php — neither ever existed. Every `core::*` key (framework branding/UI text, per this module's own CLAUDE.md) and every `trees::*` key round-tripped back out as the raw key instead of resolving, for every locale, since these files were added. LangServiceProvider also had a second, now-redundant call guarded by is_dir(__DIR__.'/en') meant to register a base-locale fallback; folded away since a single correct hint already covers every locale Laravel tries via the fallback chain the same provider sets up in setupFallbackChain(). Added tests/Feature/CoreTranslationsTest.php and tests/Feature/TreesTranslationsTest.php, each registering the respective provider directly (the base TestCase only wires LifecycleEventProvider) and asserting a known key resolves under en_GB. Both fail on the pre-fix code with the key echoed back unresolved. phpstan level 1 clean, pint clean, full Pest suite 448 failed/567 passed (two more passing than before, zero regressions — the 448 are the pre-existing dappcore/php-tenant-shaped gap noted in the previous commit). Co-Authored-By: Virgil <virgil@lethean.io>
1 parent e4bce8c commit 0060dd4

4 files changed

Lines changed: 86 additions & 7 deletions

File tree

‎src/Core/Lang/LangServiceProvider.php‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,20 @@ protected function registerCommands(): void
141141

142142
/**
143143
* Load translation files from the Lang directory.
144+
*
145+
* loadTranslationsFrom() registers a *hint path* that Laravel appends
146+
* "/{locale}/{group}.php" onto at resolution time — it must NOT already
147+
* contain the locale segment. The files live at Lang/en_GB/core.php (and
148+
* would live at Lang/en/core.php for the fallback), so the hint is the
149+
* Lang directory itself; passing __DIR__.'/en_GB' made Laravel look for
150+
* Lang/en_GB/en_GB/core.php, which never existed, so `core::*` keys
151+
* never resolved for any locale. One hint covers every locale Laravel
152+
* tries via the fallback chain below, so there is nothing further to
153+
* register for the 'en' fallback.
144154
*/
145155
protected function loadTranslations(): void
146156
{
147-
$this->loadTranslationsFrom(__DIR__.'/en_GB', 'core');
148-
149-
// Also register translations under the base locale (en) for fallback
150-
if (is_dir(__DIR__.'/en')) {
151-
$this->loadTranslationsFrom(__DIR__.'/en', 'core');
152-
}
157+
$this->loadTranslationsFrom(__DIR__, 'core');
153158
}
154159

155160
/**

‎src/Mod/Trees/Boot.php‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ class Boot extends ServiceProvider
2727

2828
public function boot(): void
2929
{
30-
$this->loadTranslationsFrom(__DIR__.'/Lang/en_GB', 'trees');
30+
// Hint path must be the Lang directory itself, not the locale
31+
// subfolder — Laravel appends "/{locale}/trees.php" at resolution
32+
// time. The file lives at Lang/en_GB/trees.php, so passing
33+
// Lang/en_GB here made it look for Lang/en_GB/en_GB/trees.php,
34+
// which never existed and so never loaded.
35+
$this->loadTranslationsFrom(__DIR__.'/Lang', 'trees');
3136
}
3237

3338
// -------------------------------------------------------------------------
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Core\Tests\Feature;
6+
7+
use Core\Lang\LangServiceProvider;
8+
use Core\Tests\TestCase;
9+
use Illuminate\Support\Facades\App;
10+
11+
/**
12+
* Regression coverage: LangServiceProvider::loadTranslations() registered
13+
* its hint path as __DIR__.'/en_GB', but the file lives at
14+
* src/Core/Lang/en_GB/core.php. loadTranslationsFrom() appends
15+
* "/{locale}/{group}.php" to whatever hint it is given, so Laravel looked
16+
* for src/Core/Lang/en_GB/en_GB/core.php — which never existed — and the
17+
* `core::*` namespace never resolved a single key, for any locale, in
18+
* production.
19+
*/
20+
class CoreTranslationsTest extends TestCase
21+
{
22+
protected function getPackageProviders($app): array
23+
{
24+
return array_merge(parent::getPackageProviders($app), [
25+
LangServiceProvider::class,
26+
]);
27+
}
28+
29+
public function test_core_namespace_translations_load_under_en_gb_locale(): void
30+
{
31+
App::setLocale('en_GB');
32+
33+
$this->assertSame('Core PHP', trans('core::core.brand.name'));
34+
}
35+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Core\Tests\Feature;
6+
7+
use Core\Mod\Trees\Boot;
8+
use Core\Tests\TestCase;
9+
use Illuminate\Support\Facades\App;
10+
11+
/**
12+
* Regression coverage: Core\Mod\Trees\Boot::boot() registered its
13+
* translations hint as __DIR__.'/Lang/en_GB', but the file lives at
14+
* Lang/en_GB/trees.php. loadTranslationsFrom() appends
15+
* "/{locale}/{group}.php" to whatever hint it is given, so Laravel looked
16+
* for Lang/en_GB/en_GB/trees.php — which never existed — and the
17+
* `trees::*` namespace never resolved a single key, for any locale.
18+
*/
19+
class TreesTranslationsTest extends TestCase
20+
{
21+
protected function getPackageProviders($app): array
22+
{
23+
return array_merge(parent::getPackageProviders($app), [
24+
Boot::class,
25+
]);
26+
}
27+
28+
public function test_trees_namespace_translations_load_under_en_gb_locale(): void
29+
{
30+
App::setLocale('en_GB');
31+
32+
$this->assertSame('Trees for Agents', trans('trees::trees.hero.badge'));
33+
}
34+
}

0 commit comments

Comments
 (0)