diff --git a/README.md b/README.md index f1bad8e..06a9850 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ![i18n](https://user-images.githubusercontent.com/700119/27761666-f3ed6746-5e60-11e7-955a-3030453c68ff.jpg) ## Scheme -![i18n scheme](https://user-images.githubusercontent.com/700119/140646548-fcf6433d-1fa0-4323-98e2-9cc49550e5ee.png) +![i18n scheme](https://user-images.githubusercontent.com/700119/141124503-59576527-e5b1-47b3-a38e-d06e51555bde.png) ## Introduction Pimcore already comes with some great features to build internationalized websites. @@ -58,15 +58,17 @@ When using this bundle, you should: - If you're using the country detection, you need a valid maxmind geo ip [data provider](docs/10_GeoControl.md) ## Further Information +- [I18n Overview Page](./docs/1_I18n.md): Learn all about the i18n principals. - [Geo IP/Control](docs/10_GeoControl.md): Enable GeoIP Data Provider. - [Zone Definitions](docs/20_Zones.md): Learn more about i18n zone definitions and how to manage them. - - [Custom I18n Context Look-Up](docs/21_CustomI18nContextLookUp.md)] (🔥 New!) + - [Custom I18n Context Look-Up](docs/21_I18nContext.md)] (🔥 New!) - [Href-Lang](docs/25_HrefLang.md): Find out more about the href-lang tag generator. - [Language Configuration](docs/26_Languages.md): Configure languages. - [Country Configuration](docs/27_Countries.md): Configure countries. -- Dynamic Routing - - [Static Routes](docs/28_StaticRoutes.md): Configure translatable static routes and implement href-lang tags. - - [Symfony Route](docs/29_SymfonyRoutes.md): Configure translatable symfony routes and implement href-lang tags. +- Route and Alternate Links Generation + - [Document Routes](docs/90_DocumentRoutes.md): Build document routes + - [Static Routes](docs/91_StaticRoutes.md): Build translatable static routes and implement href-lang tags. + - [Symfony Route](docs/92_SymfonyRoutes.md): Build translatable symfony routes and implement href-lang tags. - [Front Page Mapping](docs/30_FrontPageMapping.md): Learn how to map a custom front page. - [Localized Error Documents](docs/40_LocaleErrorDocument.md): Learn how to create localized error documents. - [Custom Locale Adapter](docs/50_CustomLocaleAdapter.md): Learn how to create a custom locale adapter. diff --git a/UPGRADE.md b/UPGRADE.md index 9c50e82..333ee22 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -34,7 +34,8 @@ i18n: ### Global Changes - `$staticRoute->assemble()` is **not** supported anymore, you always need to call `$router->generate()`: - Every PIMCORE LinkGenerator needs to implement the `I18nLinkGeneratorInterface` - - You need to pass the `_18n => [ type = RouteItemInterface::TYPE, routeParameters => [] ]` block via `$router->generate()` + - You need to pass the `_18n => [ type = RouteItemInterface::TYPE, routeParameters => [] ]` block via `$router->generate()` (Or use `RouteParameterBuilder` for parameter building) +- `url()`, `path()`, `pimcore_url()` twig helper are not supported, use `i18n_entity_route()`, `i18n_static_route()` and `i18n_symfony_route()` instead - Context Adapter and Manager have been removed (All corresponding information are available via `I18nContextInterface` directly) - PHP8 return type declarations added: you may have to adjust your extensions accordingly - `LocaleProviderInterface` changes: @@ -79,7 +80,7 @@ i18n: ### Additional new Features - Check Akamai CDN header [@florian25686](https://github.com/dachcom-digital/pimcore-i18n/pull/76/files) -- Allow different I18nContext look-ups [#70](https://github.com/dachcom-digital/pimcore-i18n/issues/70), read more about it [here](./docs/21_CustomI18nContextLookUp.md) +- Allow different I18nContext look-ups [#70](https://github.com/dachcom-digital/pimcore-i18n/issues/70), read more about it [here](./docs/21_I18nContext.md) - Allow symfony routes [#65](https://github.com/dachcom-digital/pimcore-i18n/issues/65) *** diff --git a/docs/1_I18n.md b/docs/1_I18n.md index bcea396..de7b046 100644 --- a/docs/1_I18n.md +++ b/docs/1_I18n.md @@ -1,5 +1,5 @@ # I18n Workflow -![i18n scheme](https://user-images.githubusercontent.com/700119/140646548-fcf6433d-1fa0-4323-98e2-9cc49550e5ee.png) +![i18n scheme](https://user-images.githubusercontent.com/700119/141124503-59576527-e5b1-47b3-a38e-d06e51555bde.png) ## I18n Context I18n will generate a `I18nContextInterface` object at **every request** which is accessible via the resolver @@ -136,126 +136,32 @@ my_symfony_route: matching_route_key: '(%i18n.route.translations.mySymfonyRouteKey%)' ## returns (meine-symfony-route|my-symfony-route) ``` -## Command Line -Generating absolute URLs in CL is easy! Let's create a static route (which will dispatch your LinkGenerator): +## Twig|PHP Route Generation +- [Current Request Routes for Documents](./90_DocumentRoutes.md#generating-routes-in-current-request) +- [Current Request Routes for Static Routes](./91_StaticRoutes.md#generating-routes-in-current-request) +- [Current Request Routes for Symfony Routes](./92_SymfonyRoutes.md#generating-routes-in-current-request) -```php -$routeParameters = [ - '_i18n' => [ - 'type' => RouteItemInterface::STATIC_ROUTE, - 'entity' => $object, - 'routeParameters' => [ - '_locale' => 'en' - ], - 'context' => [ - ## if you're having sites, you need to define zones - ## if you're having zones, you MUST pass the site context parameter - ## that's the rule! - 'site' => Site::getByDomain('test-domain1.test') - ] - ] -]; - -echo $this->router->generate('', $routeParameters, UrlGeneratorInterface::ABSOLUTE_URL); -``` - -## Twig Helper -Generating a complete headless context object via twig: - -```twig -{# SECTION A: simple i18n route generation #} - -{# simple url() #} -{{ url('my_symfony_route', {_i18n: { type: 'symfony', routeParameters: {_locale: 'de'}, context: { site: pimcore_site_by_domain('test-domain1.test') }}}) }} -{# simple path() without configured zones #} -{{ path('my_symfony_route', {_i18n: { type: 'symfony', routeParameters: {_locale: 'de'} }}) }} - - -{# SECTION B: complete i18n context generation #} - -{% set object_context = i18n_create_context_by_symfony_route('my_symfony_route', {_locale: 'en'}) %} -{{ dump(object_context) }} -{{ dump(object_context.linkedLanguages) }} - -{# - if you're having sites, you need to define zones - if you're having zones, you MUST pass the site context parameter - that's the rule! -#} -{% set route_site = pimcore_site_by_domain('test-domain1.test') %} -{% set zone_aware_object_context = i18n_create_context_by_symfony_route('my_symfony_route', {_locale: 'en'}, route_site) %} -{{ dump(zone_aware_object_context) }} -{{ dump(zone_aware_object_context.linkedLanguages) }} -``` +## Command Line Route Generation +Generating absolute URLs in CLI is easy! +- [CLI Routes for Documents](./90_DocumentRoutes.md#generating-routes-in-cli) +- [CLI Routes for Static Routes](./91_StaticRoutes.md#generating-routes-in-cli) +- [CLI Routes for Symfony Routes](./92_SymfonyRoutes.md#generating-routes-in-cli) -## PHP Helper -Generating a complete headless context object via php api. Let's dump some examples: +## Non-I18n Routes +I18n always requires the `_i18n` parameter node in `urlGenerator->generate`. +If this node is not present, the default route generation will be triggered. ```php +dump($router->generate('my_non_i18n_aware_symfony_route', ['_locale' => 'en'], UrlGeneratorInterface::ABSOLUTE_URL)); +``` -// SECTION A: complete i18n context generation - -// $i18nContextManager = [DI] I18nBundle\Manager\I18nContextManager -$routeItemParameters = [ - 'type' => RouteItemInterface::SYMFONY_ROUTE, - 'routeParameters' => [ - '_locale' => 'de' - // ... and all your special route params which i18n are not aware off - ], - 'routeName' => 'my_static_route', - 'context' => [ - 'site' => Site::getByDomain('test-domain1.test') - ] -]; - -// if you want to use the `$i18nContext.getLinkedLanguages()` -// you need to pass the second boolean argument as true to boot the path generator adapter -// this is disabled by default because it is not required when generating default routes -$i18nContext = $i18nContextManager->buildContextByParameters($routeItemParameters, true); - -// SECTION B: simple i18n route generation - -// $router = [DI] Symfony\Component\Routing\RouterInterface -dump('static route (without entity) and site:' . $router->generate('my_static_route', [ - '_i18n' => [ - 'type' => RouteItemInterface::STATIC_ROUTE, - 'routeName' => 'my_static_route' - 'routeParameters' => [ - '_locale' => 'de' - // ... and all your special route params which i18n are not aware off - ], - 'context' => [ - ## if you're having sites, you need to define zones - ## if you're having zones, you MUST pass the site context parameter - ## that's the rule! - 'site' => Site::getByDomain('test-domain1.test') - ] - ] -], UrlGeneratorInterface::ABSOLUTE_URL)); - -dump('static route (with entity): ' . $router->generate('', [ - '_i18n' => [ - 'type' => RouteItemInterface::STATIC_ROUTE, - 'entity' => $object, - 'routeParameters' => [ - '_locale' => 'de' - // ... and all your special route params which i18n are not aware off - ] - ] -], UrlGeneratorInterface::ABSOLUTE_URL)); - -dump('symfony route: ' . $router->generate('my_symfony_route', [ - '_i18n' => [ - 'type' => RouteItemInterface::SYMFONY_ROUTE, - 'routeParameters' => [ - '_locale' => 'de' - // ... and all your special route params which i18n are not aware off - ] - ] -], UrlGeneratorInterface::ABSOLUTE_URL)); +## Context +I18n allows you to easily fetch the current context via a given request object. +Read more about it [here](21_I18nContext.md#current-context). -dump('non i18n symfony route: ' . $router->generate('my_non_i18n_aware_symfony_route', ['_locale' => 'en'], UrlGeneratorInterface::ABSOLUTE_URL)); -``` +## Custom Context Boot +Generating a complete headless context object via twig or php api. +Read more about it [here](21_I18nContext.md#custom-context-look-up). ## Code Examples Please check out the [code examples](./60_CodeExamples.md) doc section to learn more about accessing zone information. \ No newline at end of file diff --git a/docs/21_CustomI18nContextLookUp.md b/docs/21_I18nContext.md similarity index 55% rename from docs/21_CustomI18nContextLookUp.md rename to docs/21_I18nContext.md index beffc98..b069857 100644 --- a/docs/21_CustomI18nContextLookUp.md +++ b/docs/21_I18nContext.md @@ -1,28 +1,68 @@ +# Current Context + +Fetch the current context to list linked languages for example: + +```twig +
i18n Current Context
+{% set i18n_current_context = i18n_current_context() %} +{{ dump(i18n_current_context) }} +{{ dump(i18n_current_context.linkedLanguages) }} + +``` + +**PHP** + +```php +getContext($requestStack->getMainRequest()); + $linkedLanguages = $i18nContext->getLinkedLanguages(); + } +} +``` + # Custom Context Look-Up -In some cases, you want to retrieve all available links for a specific document or object (Generating links via commandline for example). + +In some cases, you want to retrieve all available links for a specific document or object. + +## Boot Context in TWIG ```twig

I18n Context Look-Up (document)

{% set document_context = i18n_create_context_by_entity(pimcore_document(16), { _locale: 'en' }) %} {{ dump(document_context) }} {{ dump(document_context.linkedLanguages) }} -
+ +

I18n Context Look-Up (object [will call correspondig link generator])

{% set object_context = i18n_create_context_by_entity(pimcore_object(16), { _locale: 'en' }) %} {{ dump(object_context) }} {{ dump(object_context.linkedLanguages) }} -
+ +

I18n Context Look-Up (symfony route)

{% set object_context = i18n_create_context_by_symfony_route('my_symfony_route, { _locale: 'en' } }) %} {{ dump(object_context) }} {{ dump(object_context.linkedLanguages) }} -
+ +

I18n Context Look-Up (static route)

{% set object_context = i18n_create_context_by_static_route('my_static_route', { _locale: 'fr', object_id: 16 } }) %} {{ dump(object_context) }} {{ dump(object_context.linkedLanguages) }} -## If you're using zones, you NEED to pass the site as context! +{# If you're using zones, you NEED to pass the site as context! #}

I18n Context Look-Up with Zones (document)

{% set zone_aware_document_context = i18n_create_context_by_entity(pimcore_document(16), { _locale: 'en' }, pimcore_site_by_domain('my-site.test')) %} @@ -30,10 +70,13 @@ In some cases, you want to retrieve all available links for a specific document {{ dump(zone_aware_document_context.linkedLanguages) }} ``` +## Boot Context in PHP + ```php i18nContextManager = $i18nContextManager; } - public function build(Pimcore\Document $document, array $routeParameter) + public function build(Pimcore\DataObject $object, array $routeParameter) { + ## I. no zones defined $parameters = [ 'routeParameters' => $routeParameter, - 'entity' => $document + 'entity' => $object ]; - $i18nContext = $this->i18nContextManager->buildContextByParameters($parameters, true); - - ## If you're using zones, you NEED to pass the site as context! + // third argument needs to be true to fully boot context (initialize linked zone sites) + $i18nContext = $this->i18nContextManager->buildContextByParameters(RouteItemInterface::STATIC_ROUTE, $parameters, true); - $zoneAwareParameters = [ + ## II. zones available + ## You MUST pass the site as context! + $zoneAwareParameters = [ 'routeParameters' => $routeParameter, - 'entity' => $document, + 'entity' => $object, 'context' => [ 'site' => $site ] ]; - $zoneAwareI18nContext = $this->i18nContextManager->buildContextByParameters($zoneAwareParameters, true); + $zoneAwareI18nContext = $this->i18nContextManager->buildContextByParameters(RouteItemInterface::STATIC_ROUTE, $zoneAwareParameters, true); dump($zoneAwareI18nContext); } diff --git a/docs/60_CodeExamples.md b/docs/60_CodeExamples.md index e9de24b..1cf2422 100644 --- a/docs/60_CodeExamples.md +++ b/docs/60_CodeExamples.md @@ -20,66 +20,40 @@ | getLanguageNameByIsoCode | helper to get language name by iso code | | getCountryNameByIsoCode | helper to get country name by iso code | -## Zone -The zone represents an instance of `I18nZoneInterface` which comes with some helper methods: - -| Name | Description | -|------|-------------| -| getId | given zone id (null, if it no zones have been configured | -| getName | given zone name (null, if no zones have been configured | -| getDomains | all available domains for given zone. | -| getMode | returns `language` or `country` | -| getTranslations | array, translations for dynamic routes | -| isActiveZone | check if zone is active one | -| getLocaleUrlMapping | For example: `de-ch`. Mostly used to build [static routes](./28_StaticRoutes.md#naming-convention-in-country-context) | -| getGlobalInfo | international state | -| getSites | get all corresponding sites | - -**Twig** +### Fetch Context Data in Twig ```twig {# - be careful, i18n_context is allowed to return null! + be careful, i18n_current_context is allowed to return null! #} -{% set current_locale = i18n_context().localeDefinition.locale %} -{% set current_language_iso = i18n_context().localeDefinition.languageIso %} -{% set current_country_iso = i18n_context().localeDefinition.countryIso %} +{% set current_locale = i18n_current_context().localeDefinition.locale %} +{% set current_language_iso = i18n_current_context().localeDefinition.languageIso %} +{% set current_country_iso = i18n_current_context().localeDefinition.countryIso %} -{{ dump(i18n_context().mode) }} -{{ dump(i18n_context().localeDefinition.locale) }} -{{ dump(i18n_context().linkedLanguages) }} -{{ dump(i18n_context().activeLanguages) }} -{{ dump(i18n_context().activeCountries) }} -{{ dump(i18n_context().languageNameByIsoCode(current_language_iso, current_locale)) }} -{{ dump(i18n_context().countryNameByIsoCode(current_country_iso, current_locale)) }} +{{ dump(i18n_current_context().localeDefinition.locale) }} +{{ dump(i18n_current_context().linkedLanguages) }} +{{ dump(i18n_current_context().activeLanguages) }} +{{ dump(i18n_current_context().activeCountries) }} +{{ dump(i18n_current_context().languageNameByIsoCode(current_language_iso, current_locale)) }} +{{ dump(i18n_current_context().countryNameByIsoCode(current_country_iso, current_locale)) }} -{{ dump(i18n_context().zoneActiveLocales()) }} -{{ dump(i18n_context().localeInfo('de', 'id')) }} +{{ dump(i18n_current_context().zoneActiveLocales()) }} +{{ dump(i18n_current_context().localeInfo('de', 'id')) }} ``` -**PHP** +### Fetch Context Data in PHP ```php requestStack = $requestStack; - $this->i18nContextResolver = $i18nContextResolver; - } - - public function getInformation() - { - $i18nContext = $this->i18nContextResolver->getContext($this->requestStack->getMainRequest()); + $i18nContext = $i18nContextResolver->getContext($requestStack->getMainRequest()); - $mode = $i18nContext->getZone()->getMode(); $LinkedLanguages = $i18nContext->getLinkedLanguages(); // get current locale @@ -104,6 +78,57 @@ class ExampleService } ``` +## Zone +The zone represents an instance of `I18nZoneInterface` which comes with some helper methods: + +| Name | Description | +|------|-------------| +| getId | given zone id (null, if it no zones have been configured | +| getName | given zone name (null, if no zones have been configured | +| getDomains | all available domains for given zone. | +| getMode | returns `language` or `country` | +| getTranslations | array, translations for dynamic routes | +| isActiveZone | check if zone is active one | +| getLocaleUrlMapping | For example: `de-ch`. Mostly used to build [static routes](./28_StaticRoutes.md#naming-convention-in-country-context) | +| getGlobalInfo | international state | +| getSites | get all corresponding sites | + + +### Fetch Zone Data in Twig +```twig +{# + be careful, i18n_current_context is allowed to return null! +#} + +{{ dump(i18n_current_context().zone.mode) }} +{{ dump(i18n_current_context().zone.sites) }} + +``` + +### Fetch Zone Data in PHP +```php +getContext($requestStack->getMainRequest()); + + $zone = $i18nContext->getZone(); + + // get zone mode (language or country + $mode = $zone->getMode(); + + // list all zone sites + $zoneSites = $zone->getSites(true); + } +} +``` + ### Zone Current Site Information To retrieve data from an active site, you may want to use the `$i18nContext->getCurrentZoneSite()` method. Since the current site gets defined via the current locale, be sure that locale is always available. @@ -132,47 +157,39 @@ The current site represents an instance of `ZoneSiteInterface` which comes with | getSubSites | array | | hasSubSites | bool | -**Twig** +### Fetch Zone Site Data in Twig ```twig {# get current context info #} -{{ dump(i18n_context().currentZoneSite.url) }} -{{ dump(i18n_context().currentZoneSite.localeUrlMapping) }} +{{ dump(i18n_current_context().currentZoneSite.url) }} +{{ dump(i18n_current_context().currentZoneSite.localeUrlMapping) }} ``` -**PHP** +### Fetch Zone Site Data in Twig ```php requestStack = $requestStack; - $this->i18nContextResolver = $i18nContextResolver; - } - - public function getInformation() - { - $i18nContext = $this->i18nContextResolver->getContext($this->requestStack->getMainRequest()); + $i18nContext = $i18nContextResolver->getContext($requestStack->getMainRequest()); $currentContextInfo = $i18nContext->getCurrentZoneSite()->getUrl(); $currentContextInfo = $i18nContext->getCurrentZoneSite()->getLocaleUrlMapping(); } } ``` + ## Navigation Examples ### Language Drop-Down ```twig -{% set i18n_context = i18n_context() %} -{% if i18n_context is not null %} - {% set languages = i18n_context.activeLanguages %} +{% set current_context = i18n_current_context() %} +{% if current_context is not null %} + {% set languages = current_context.activeLanguages %} {% if languages is iterable %}