title from the profile page too, so the browser * tab said "Profile settings" over the password form. * * Two scans, matching the two shapes of that miss: * * - Every page under pages/auth and pages/settings must use the hook. These * screens always carry copy of their own (a title at minimum), so a page * here with no useTranslation is a page somebody forgot, not a page with * nothing to say. Pages elsewhere are not scanned — a public theme page * can legitimately render nothing but data. * - No literal anywhere. A browser-tab title is user- * facing copy like any other, and the literal form is also where the * copy-paste mistake above lived. */ // dirname() rather than base_path(): this runs at file scope, where the // application container is not booted yet. $root = dirname(__DIR__, 2); $untranslatedPages = []; foreach (['auth', 'settings'] as $section) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($root.'/resources/js/pages/'.$section, FilesystemIterator::SKIP_DOTS) ); foreach ($files as $file) { if ($file->getExtension() !== 'tsx') { continue; } if (! str_contains((string) file_get_contents($file->getPathname()), 'useTranslation')) { $untranslatedPages[] = str_replace($root.'/', '', $file->getPathname()); } } } $literalTitles = []; $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($root.'/resources/js', FilesystemIterator::SKIP_DOTS) ); foreach ($files as $file) { if ($file->getExtension() !== 'tsx') { continue; } $relative = str_replace($root.'/', '', $file->getPathname()); foreach (file($file->getPathname()) as $number => $line) { if (str_contains($line, 'toBe([], implode("\n", array_merge( ['These titles are string literals, so the tab reads English in every language.'], ['Pass the title through t() — .'], $literalTitles, ))); });