Multi Language support #273
Replies: 5 comments 7 replies
-
Hi! Thank you so much for bringing this up. This is really something I've wanted to support for a long time, but haven't figured out a good way to do it. It would have to be something elegant and with good DX. The problem is that there are quite a few ways to both set it up and use it depending on how you want the site to be structured. If possible I would love to hook into the Laravel ![]() And for each build loop we use the translations for that language. What do you think about a DX like that? Could that work? @lucadegasperi In the meantime though, as this feature would require quite a bit of code and testing this would have to come out after HydePHP v2 which is my priority. In the meantime I'm sure you could hook into the build process to do things in userland. A really crude way could be to change the config each time you run the command, so say you have your Swedish files in Like I said, I'd love to hear more ideas about how we can best implement something like this as it's definitely on the roadmap! |
Beta Was this translation helpful? Give feedback.
-
@caendesilva what I did was to create a /en /de folder inside the docs folder and then call the |
Beta Was this translation helpful? Give feedback.
-
Here's how I managed to do the multi build process: $languages = config('hyde.languages', []);
foreach($languages as $language) {
$suffix = '/' . $language;
$kernel = HydeKernel::getInstance();
$kernel->setSourceRoot(Config::getString('hyde.source_root', ''));
$this->registerSourceDirectories([
HtmlPage::class => $this->getSourceDirectoryConfiguration(HtmlPage::class, '_pages') . $suffix,
BladePage::class => $this->getSourceDirectoryConfiguration(BladePage::class, '_pages') . $suffix,
MarkdownPage::class => $this->getSourceDirectoryConfiguration(MarkdownPage::class, '_pages') . $suffix,
MarkdownPost::class => $this->getSourceDirectoryConfiguration(MarkdownPost::class, '_posts') . $suffix,
DocumentationPage::class => $this->getSourceDirectoryConfiguration(DocumentationPage::class, '_docs') . $suffix,
]);
if($language === 'global') {
$this->storeCompiledSiteIn(Config::getString('hyde.output_directory', '_site'));
} else {
$this->storeCompiledSiteIn(Config::getString('hyde.output_directory', '_site') . $suffix);
}
$this->useMediaDirectory(Config::getString('hyde.media_directory', '_media'));
$this->discoverBladeViewsIn(BladePage::sourceDirectory());
$kernel->boot();
$this->call('build');
$this->call('build:search');
} This all runs inside an artisan command as well. At the end of the day I did all this just because the navigation inside the pages and docs wouldn't render properly and it would show the language as the top level folder instead of its content. Hacking the side navigation to ignore the top level language was harder than just building the site multiple times. Plus the search index would mush together the pages of all languages, instead of having separate indexes for each language. I believe the cleanest solution would be to have a configuration for which languages one wants to use, and have only one build that generates a different navigation tree for each language, as well as a different search index. This way both the |
Beta Was this translation helpful? Give feedback.
-
![]() |
Beta Was this translation helpful? Give feedback.
-
Hey @caendesilva and @lucadegasperi, I feel this topic is incredibly important, and I’d love to share my approach that might spark some ideas. This past Christmas, when I first fell in love with HydePHP, my immediate instinct was to make it work for multilingual sites—since it’s a core functionality in my work, and I believe it’s essential for many others too. But as I explored further, I realized that an external module could never be as elegant as a fully integrated solution. So, I took a step back and began studying the layout system. My Approach to Multilingual HydePHPInstead of creating separate sites for each language, my method revolves around dynamically generating localized routes, pages, and translations within a single build process, ensuring a shared set of resources across languages, without the need to run multiple builds. And is along those lines. Localized RoutesEach page gets a unique localized URL without duplicating the entire site structure. Instead of class MultilingualRoute extends BaseRoute {
public function __construct(HydePage $page, string $locale = 'en')
{
parent::__construct($page);
$this->uri = "{$locale}/{$this->uri}";
}
} This ensures that routes are automatically prefixed based on language, without needing multiple build processes. Multilingual Blade Page for LocalizationTo ensure that the pages themselves are properly handled for each language, I extended the class MultilingualBladePage extends BladePage
{
protected string $locale;
public function __construct(string $identifier, string $locale = 'en', array $matter = [])
{
$this->locale = $locale;
// Ensure the identifier is correctly handled for multilingual pages
if ($locale !== config('hyde-multilanguage.default_language', 'en')) {
// Ensure we don't have a nested locale like `de/it/index`
$identifierParts = explode('/', $identifier);
// Only prepend the locale if the first part isn't a locale
if (count($identifierParts) === 1 || $identifierParts[0] !== $locale) {
$identifier = "{$locale}/{$identifier}";
}
}
parent::__construct($identifier, $matter);
}
/**
* Override the route key generation to handle languages correctly.
*/
public function getRouteKey(): string
{
// If the page is in the default language, use the normal route key
if ($this->locale === config('hyde-multilanguage.default_language', 'en')) {
return $this->routeKey;
}
// Avoid prepending the locale when it's already included in the route key
if (strpos($this->routeKey, "{$this->locale}/") === 0) {
return $this->routeKey; // Already prefixed with the locale
}
// Prepend the locale to the route key only once
return "{$this->locale}/{$this->routeKey}";
}
/**
* Override the output path to include the language directory if needed.
*/
public function getOutputPath(): string
{
// If the page is in the default language, use the normal output path
if ($this->locale === config('hyde-multilanguage.default_language', 'en')) {
return parent::getOutputPath();
}
// Ensure the locale is only prepended once to the output path
$outputPath = parent::getOutputPath();
if (strpos($outputPath, "{$this->locale}/") === 0) {
return $outputPath; // Already prefixed with the locale
}
return "{$this->locale}/{$outputPath}";
}
} This class ensures that the pages are generated with the correct output paths and route keys based on the locale, helping avoid duplication and ensuring clean, multilingual page structure. Middleware for Dynamic Locale SwitchingSince the class SetLocale
{
public function handle($request, Closure $next)
{
$locale = $request->segment(1); // Extract language code from URL
$supportedLanguages = config('hyde-multilanguage.languages.supported');
if (in_array($locale, $supportedLanguages)) {
App::setLocale($locale); // Set the app's locale
} else {
$locale = config('hyde-multilanguage.languages.default');
}
return $next($request);
}
} This way, the site dynamically serves the correct language instead of requiring a rebuild for each language. Avoiding Media DuplicationRather than duplicating media files across multiple <img src="{{ asset('media/logo.png') }}" alt="Logo"> This ensures that all languages share the same assets without redundant copies. Rather than treating multilanguage as multiple separate sites, I see it as one site with different entry points. This keeps navigation, assets, and indexing clean while maintaining HydePHP’s static nature. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello,
I've recently discovered Hyde and I like it a lot, it also feels somewhat familiar by being based on Laravel.
So far I have only used it to generare the documentation for a project I'm working on, but I'm now faced with the task of building a multi language version of such documentation.
What I've tried so far is the following:
Write a console command that sets different input and output paths for each language, then call the build command of Hyde for each language. What I don't like about this approach is that the serve command doesn't work at all, and that each language has a copy of the media directory. What I like though, is that each language has its own index and search page.
What I'm asking you is: Is there a plan to implement multiple languages into Hyde, or in general, is there a better way for me to hook into the build process to generate multiple versions of the site?
Thank you,
Luca
Beta Was this translation helpful? Give feedback.
All reactions