tobento / app-language
App language support.
Requires
- php: >=8.0
- tobento/app: ^1.0
- tobento/app-database: ^1.0
- tobento/app-http: ^1.0.6
- tobento/app-migration: ^1.0
- tobento/service-dater: ^1.0.2
- tobento/service-language: ^1.0.4
- tobento/service-repository: ^1.0
- tobento/service-repository-storage: ^1.0
- tobento/service-requester: ^1.0.2
- tobento/service-routing: ^1.0.8
- tobento/service-support: ^1.0
Requires (Dev)
- nyholm/psr7: ^1.4
- phpunit/phpunit: ^9.5
- tobento/app-translation: ^1.0
- vimeo/psalm: ^4.0
README
Language support for the app.
Table of Contents
Getting Started
Add the latest version of the app language project running this command.
composer require tobento/app-language
Requirements
- PHP 8.0 or greater
Documentation
App
Check out the App Skeleton if you are using the skeleton.
You may also check out the App to learn more about the app in general.
Language Boot
The language boot does the following:
- installs and loads language config file
- language interfaces implementation based on config
- determines current language
- sets current language on the date formatter
use Tobento\App\AppFactory; // Create the app $app = (new AppFactory())->createApp(); // Add directories: $app->dirs() ->dir(realpath(__DIR__.'/../'), 'root') ->dir(realpath(__DIR__.'/../app/'), 'app') ->dir($app->dir('app').'config', 'config', group: 'config') ->dir($app->dir('root').'public', 'public') ->dir($app->dir('root').'vendor', 'vendor'); // Adding boots: $app->boot(\Tobento\App\Language\Boot\Language::class); // Run the app: $app->run();
Language Config
The configuration for the language is located in the app/config/language.php
file at the default App Skeleton config location.
App Languages
use Tobento\App\AppFactory; use Tobento\Service\Language\LanguagesInterface; $app = (new AppFactory())->createApp(); // Add directories: $app->dirs() ->dir(realpath(__DIR__.'/../'), 'root') ->dir(realpath(__DIR__.'/../app/'), 'app') ->dir($app->dir('app').'config', 'config', group: 'config') ->dir($app->dir('root').'public', 'public') ->dir($app->dir('root').'vendor', 'vendor'); // Adding boots: $app->boot(\Tobento\App\Language\Boot\Language::class); $app->booting(); // Gets the app languages: $languages = $app->get(LanguagesInterface::class); // Run the app: $app->run();
You may check out the Language Service to learn more about it.
Current And Default App Language
use Tobento\App\AppFactory; use Tobento\Service\Language\LanguagesInterface; use Tobento\Service\Language\LanguageInterface; $app = (new AppFactory())->createApp(); // Add directories: $app->dirs() ->dir(realpath(__DIR__.'/../'), 'root') ->dir(realpath(__DIR__.'/../app/'), 'app') ->dir($app->dir('app').'config', 'config', group: 'config') ->dir($app->dir('root').'public', 'public') ->dir($app->dir('root').'vendor', 'vendor'); // Adding boots: $app->boot(\Tobento\App\Language\Boot\Language::class); $app->booting(); // Gets the app languages: $languages = $app->get(LanguagesInterface::class); // Current language: $currentLanguage = $languages->current(); // var_dump($currentLanguage instanceof LanguageInterface); // bool(true) // Default language: $defaultLanguage = $languages->default(); // var_dump($defaultLanguage instanceof LanguageInterface); // bool(true) // Run the app: $app->run();
You may check out the Language Service to learn more about it.
Resolving Current Language
By default, the current language is resolved by the Tobento\App\Language\CurrentLanguageRouterResolver::class
. You may change the implementation in the language config.
Localizing Routes
You may localize your routes by the following way:
use Tobento\App\AppFactory; use Tobento\App\Language\RouteLocalizerInterface; use Tobento\Service\Language\LanguagesInterface; $app = (new AppFactory())->createApp(); // Add directories: $app->dirs() ->dir(realpath(__DIR__.'/../'), 'root') ->dir(realpath(__DIR__.'/../app/'), 'app') ->dir($app->dir('app').'config', 'config', group: 'config') ->dir($app->dir('root').'public', 'public') ->dir($app->dir('root').'vendor', 'vendor'); // Adding boots: $app->boot(\Tobento\App\Language\Boot\Language::class); $app->booting(); // Localize Routes: $routeLocalizer = $app->get(RouteLocalizerInterface::class); $route = $app->route('GET', '{?locale}/team', function(LanguagesInterface $languages): array { return ['page' => 'team', 'locale' => $languages->current()->locale()]; })->name('team'); $routeLocalizer->localizeRoute($route); /* print_r($app->routeUrl('team')->translated()); Array ( [de] => https://example.com/de/team [en] => https://example.com/team ) */ // Run the app: $app->run();
Translation Routing
Simply, install the App Translation bundle and boot the \Tobento\App\Translation\Boot\Translation::class
:
composer require tobento/app-translation
use Tobento\App\AppFactory; use Tobento\App\Language\RouteLocalizerInterface; use Tobento\Service\Language\LanguagesInterface; use Tobento\Service\Translation\TranslatorInterface; use Tobento\Service\Translation\Resource; $app = (new AppFactory())->createApp(); // Add directories: $app->dirs() ->dir(realpath(__DIR__.'/../'), 'root') ->dir(realpath(__DIR__.'/../app/'), 'app') ->dir($app->dir('app').'config', 'config', group: 'config') ->dir($app->dir('root').'public', 'public') ->dir($app->dir('root').'vendor', 'vendor'); // Adding boots: $app->boot(\Tobento\App\Language\Boot\Language::class); $app->boot(\Tobento\App\Translation\Boot\Translation::class); $app->booting(); // Add routes translations: $app->on(TranslatorInterface::class, function(TranslatorInterface $translator) { $translator->resources()->add(new Resource( name: 'routes', locale: 'en', translations: [ 'checkout' => 'checkout', 'payment' => 'payment', 'products' => 'products', 'edit' => 'edit' ], )); $translator->resources()->add(new Resource( name: 'routes', locale: 'de', translations: [ 'checkout' => 'kasse', 'payment' => 'zahlung', 'products' => 'produkte', 'edit' => 'bearbeiten', ], )); }); // Localize Routes: $routeLocalizer = $app->get(RouteLocalizerInterface::class); $route = $app->route('GET', '{?locale}/{checkout}/{payment}', function(LanguagesInterface $languages) { return ['page' => 'checkout', 'locale' => $languages->current()->locale()]; })->name('checkout.payment'); // checkout and payment will be translated // by the TranslatorInterface::class if implemented, otherwise // checkout and payment is used: $routeLocalizer->localizeRoute($route, 'checkout', 'payment'); /* print_r($app->routeUrl('checkout.payment')->translated()); Array ( [de] => https://example.com/de/kasse/zahlung [en] => https://example.com/checkout/payment ) */ // Resource example: $routeResource = $app->routeResource('{?locale}/{products}', ResourceController::class)->name('products'); $routeLocalizer->localizeRoute($routeResource, 'products', 'edit.edit'); // define resource verbs with a dot if you want to translate them too! // e.g. 'create.create' or 'edit.edit' /* print_r($app->routeUrl('products.edit', ['id' => 5])->translated()); Array ( [de] => https://example.com/de/produkte/5/bearbeiten [en] => https://example.com/products/5/edit ) */ // Run the app: $app->run();
By default, translations are loaded from the routes
named resources.
You may change the localization strategy by changing the RouteLocalizerInterface::class
implemenation in the language config file.
Localizing Routes With Domains
You will need to specify the languages with its domain in the app/config/language.php
file:
// ... $storage = new InMemoryStorage([ 'languages' => [ 1 => [ 'id' => 1, 'locale' => 'de-DE', // The key is used for translations and storing resources! 'key' => 'de', 'domain' => 'example.de', 'default' => true, ], 2 => [ 'id' => 2, 'locale' => 'de-CH', // The key is used for translations and storing resources! 'key' => 'de', // or if specific translations and storing resources! //'key' => 'de-CH', 'slug' => 'de', 'domain' => 'example.ch', 'fallback' => 'de-DE', 'default' => true, ], 3 => [ 'id' => 3, 'locale' => 'fr-CH', 'slug' => 'fr', 'domain' => 'example.ch', 'fallback' => 'de-DE', ], ], ]); // ...
App Example
use Tobento\App\AppFactory; use Tobento\App\Language\RouteLocalizerInterface; use Tobento\Service\Translation\TranslatorInterface; $app = (new AppFactory())->createApp(); // Add directories: $app->dirs() ->dir(realpath(__DIR__.'/../'), 'root') ->dir(realpath(__DIR__.'/../app/'), 'app') ->dir($app->dir('app').'config', 'config', group: 'config') ->dir($app->dir('root').'public', 'public') ->dir($app->dir('root').'vendor', 'vendor'); // Adding boots: $app->boot(\Tobento\App\Language\Boot\Language::class); $app->booting(); // Localize Routes: $routeLocalizer = $app->get(RouteLocalizerInterface::class); $route = $app->route('GET', '{?locale}/team', function(null|string $locale): array { return ['page' => 'team', 'locale' => $locale]; })->name('team'); $routeLocalizer->localizeRoute($route); /* print_r($app->routeUrl('team')->domained()); Array ( [example.ch] => http://example.ch/team [example.de] => http://example.de/team ) print_r($app->routeUrl('team')->domain('example.ch')->translated()); Array ( [de] => http://example.ch/team [fr] => http://example.ch/fr/team ) print_r($app->routeUrl('team')->domain('example.de')->translated()); Array ( [de-de] => http://example.de/team ) */ // Run the app: $app->run();
Area Languages
use Tobento\App\AppFactory; use Tobento\Service\Language\AreaLanguagesInterface; use Tobento\Service\Language\LanguagesInterface; $app = (new AppFactory())->createApp(); // Add directories: $app->dirs() ->dir(realpath(__DIR__.'/../'), 'root') ->dir(realpath(__DIR__.'/../app/'), 'app') ->dir($app->dir('app').'config', 'config', group: 'config') ->dir($app->dir('root').'public', 'public') ->dir($app->dir('root').'vendor', 'vendor'); // Adding boots: $app->boot(\Tobento\App\Language\Boot\Language::class); $app->booting(); // Gets the area languages: $areaLanguages = $app->get(AreaLanguagesInterface::class); // Run the app: $app->run();
You may check out the Area Languages to learn more about it.