fix i18n cache on about/guidelines

pull/7330/head
Your Name 1 week ago
parent 8aadedb56c
commit d1d15c76f9

@ -61,7 +61,12 @@ class SiteController extends Controller
public function about()
{
return Cache::remember('site.about_v2', now()->addMinutes(15), function () {
// Scope the cache key by locale: the rendered view contains many
// translated site.* strings, so a single shared key would let one
// locale's render be served to visitors of other locales.
$cacheKey = 'site.about_v2:'.app()->getLocale();
return Cache::remember($cacheKey, now()->addMinutes(15), function () {
$user_count = number_format(User::count());
$post_count = number_format(StatusService::totalLocalStatuses());
$rules = config_cache('app.rules') ? json_decode(config_cache('app.rules'), true) : null;
@ -77,7 +82,11 @@ class SiteController extends Controller
public function communityGuidelines(Request $request)
{
return Cache::remember('site:help:community-guidelines', now()->addDays(120), function () {
// Scope by locale: the rendered layout contains translated strings,
// so a shared key would leak one locale's render to other locales.
$cacheKey = 'site:help:community-guidelines:'.app()->getLocale();
return Cache::remember($cacheKey, now()->addMinutes(15), function () {
$slug = '/site/kb/community-guidelines';
$page = Page::whereSlug($slug)->whereActive(true)->first();

@ -4,6 +4,7 @@ use App\Models\User;
use App\Util\Localization\Localization;
use Illuminate\Auth\Events\Login;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File;
@ -278,6 +279,46 @@ describe('language settings via /settings/home', function () {
});
});
describe('locale-aware caching of rendered site pages', function () {
beforeEach(function () {
Cache::flush();
});
it('caches /site/about under a locale-scoped key', function () {
$this->withSession(['locale' => 'en-US'])
->get('/site/about')
->assertOk();
expect(Cache::has('site.about_v2:en-US'))->toBeTrue()
// The old, locale-unaware key must not be used.
->and(Cache::has('site.about_v2'))->toBeFalse();
});
it('does not let a non-default locale poison the cached render of another', function () {
$other = firstNonDefaultLocale();
// A visitor on a non-default locale warms the cache first (cold cache).
$this->withSession(['locale' => $other])
->get('/site/about')
->assertOk();
// Then an en-US visitor: must get its own cache entry, not the
// other locale's render.
$this->withSession(['locale' => 'en-US'])
->get('/site/about')
->assertOk();
// Each locale gets its own cache entry, so the first (non-default)
// render cannot overwrite / be served as the en-US render. We assert
// key isolation rather than content difference, since a partially
// translated locale may legitimately render identically to English.
expect(Cache::has('site.about_v2:'.$other))->toBeTrue()
->and(Cache::has('site.about_v2:en-US'))->toBeTrue()
// The old shared key must never be written.
->and(Cache::has('site.about_v2'))->toBeFalse();
})->skip(fn () => firstNonDefaultLocale() === 'en-US', 'needs a second locale');
});
describe('empty string translation fallback', function () {
it('falls back to the fallback locale for empty (untranslated) strings', function () {
Config::set('app.fallback_locale', 'en-US');

Loading…
Cancel
Save