From 3b0a0e8d5fdc6887063fa09d127fe0932204867c Mon Sep 17 00:00:00 2001 From: Guite Date: Sat, 25 Jan 2020 12:15:54 +0100 Subject: [PATCH] updated translation docs, fixed #4057 --- Refactoring for 3.0.md | 234 +----------------- src/docs/TranslationAndLanguage/Debugging.md | 11 +- src/docs/TranslationAndLanguage/Extraction.md | 118 ++++++++- .../TranslationAndLanguage/Installation.md | 12 +- src/docs/TranslationAndLanguage/Javascript.md | 3 +- .../TranslationAndLanguage/PluralForms.md | 30 +++ src/docs/TranslationAndLanguage/README.md | 15 ++ .../TranslationAndLanguage/Terminology.md | 19 +- .../TranslationAndLanguage/Translation.md | 24 +- src/docs/TranslationAndLanguage/Usage.md | 86 ++++++- .../TranslationAndLanguage/UserInterface.md | 20 ++ 11 files changed, 288 insertions(+), 284 deletions(-) create mode 100644 src/docs/TranslationAndLanguage/PluralForms.md create mode 100644 src/docs/TranslationAndLanguage/README.md create mode 100644 src/docs/TranslationAndLanguage/UserInterface.md diff --git a/Refactoring for 3.0.md b/Refactoring for 3.0.md index 4feb2f46db..f5edb81bd3 100644 --- a/Refactoring for 3.0.md +++ b/Refactoring for 3.0.md @@ -52,239 +52,7 @@ information and examples. ## Translations All custom Zikula translation mechanisms have been removed in favour of Symfony's native translation system. -### PHP files -Some examples for how to convert translations in PHP files: - -```php -// import -use Zikula\Common\Translator\TranslatorInterface; // old -use Symfony\Contracts\Translation\TranslatorInterface; // new - -// 1. Simple: -$this->__('Hello') // old -$this->trans('Hello') // new - -// 2. With simple substitution parameters -$this->__f('Hello %userName%', ['%userName%' => 'Mark Smith']) // old -$this->trans('Hello %userName%', ['%userName%' => 'Mark Smith']) // new - -// 3. With explicit domain -$this->__('Hello', 'acmefoomodule') // old -$this->trans('Hello', [], 'acmefoomodule') // new - -// 4. With plural forms and advanced substitution (see note below) -$this->_fn('User deleted!', '%n users deleted!', count($deletedUsers), ['%n' => count($deletedUsers)]); -/** @Desc("{count, plural,\n one {User deleted!}\n other {# users deleted!}\n}") */ -$this->getTranslator()->trans('plural_n.users.deleted', ['%count%' => count($deletedUsers)]); -``` - -You can still use `Zikula\Bundle\CoreBundle\Translation\TranslatorTrait`, but it has only one method left now: -```php -public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string -``` -You can/should remove the `setTranslator` method from your class which uses the trait. It is not needed anymore. - -#### Automatic translations -You should remove all translation calls from the following elements: - -- Strings inside form type classes: - - Form field labels - - Choice labels - - Placeholders - - String values for `empty_value` attribute - - Invalid messages - - Single help messages - - Input group addons - - Alert messages -- Flash messages (`$this->addFlash()` as well as `getFlashBag()->add()`); except when substitution parameters are used. -- Knp menu entries: - - Labels (`$menu->addChild('foo')` as well as `$menu['foo']->setLabel('bar')`) - - Link titles (`setLinkAttribute('title', 'my.title')`) - -They will be picked up by the extractor nevertheless. - -More information about how translation of form messages work can be found [here](https://symfony.com/blog/new-in-symfony-4-3-improved-form-translation). - -For a help array with multiple strings an example follows below. - -#### Using the extractor - -To extract translations use the console command `translation:extract`. To see all of it's option, do this: -``` -php bin/console translation:extract -h -# or -php bin/console translation:extract --help -``` - -Example for Zikula core: -``` -# extract for all configured locales -php bin/console translation:extract zikula -# extract only for English -php bin/console translation:extract zikula en -``` - -Note `zikula` is the name of our configuration. - -Examples for a module or a theme: -``` -php bin/console translation:extract -b AcmeFooModule extension -php bin/console translation:extract --bundle AcmeFooModule extension en -php bin/console translation:extract -b AcmeFooModule acmefoomodule -php bin/console translation:extract --bundle AcmeFooModule acmefoomodule en - -# or with more memory: -php -dmemory_limit=2G bin/console translation:extract --bundle AcmeFooModule extension -php -dmemory_limit=2G bin/console translation:extract --bundle AcmeFooModule acmefoomodule en -``` - -You can always check the status of your translation using the `translation:status` command. -Check the available options using `-h` or `--help` like shown above. - -#### Translation annotations - -To influence the extraction behaviour you can utilise some annotations from the `Translation\Extractor\Annotation` namespace. -Import them like any other php class: -```php -use Translation\Extractor\Annotation\Desc; -use Translation\Extractor\Annotation\Ignore; -use Translation\Extractor\Annotation\Translate; -``` - -##### `@Desc` -The `@Desc` annotation allows specifying a default translation for a key. - -Examples: - -```php -$builder->add('title', 'text', [ - /** @Desc("Title:") */ - 'label' => 'post.form.title', -]); - -/** @Desc("We have changed the permalink because the post '%slug%' already exists.") */ -$errors[] = $this->translator->trans( - 'post.form.permalink.error.exists', ['%slug%' => $slug] -); -``` - -##### `@Ignore` -The `@Ignore` annotation allows ignoring extracting translation subjects which are not a string, but a variable. -You can use it for example for `trans()` calls, form labels and form choices. - -Examples: - -```php -echo $this->translator->trans(/** @Ignore */$description); - -$builder->add('modulecategory' . $module['name'], ChoiceType::class, [ - /** @Ignore */ - 'label' => $module['displayname'], - 'empty_data' => null, - 'choices' => /** @Ignore */$options['categories'] -]); -``` - -##### `@Translate` -With the `/** @Translate */` you can explicitly add phrases to the dictionary. This helps to extract strings -which would have been skipped otherwise. - -Examples: - -```php -$placeholder = /** @Translate */'delivery.user.not_chosen'; -``` - -It can be also used to force specific domain: - -```php -$errorMessage = /** @Translate(domain="validators") */'error.user_email.not_unique'; -``` - -##### Combined example - -If you have a form class which uses a help array with multiple help messages strings you need to prepare it like this: - -```php -$builder->add('myField', [ - // ... - /** @Ignore */ - 'help' => [ - /** @Translate */'This is the first help message.', - /** @Translate */'This is the second help message.' - ] -]); -``` - -### JavaScript files -Follows basically the same rules as translations in PHP files shown above. See [BazingaJsTranslation docs](https://github.com/willdurand/BazingaJsTranslationBundle/blob/master/Resources/doc/index.md#the-js-translator) for further details and examples. - -### Twig template files -Some examples for how to convert translations in templates: - -```twig -1. Simple: -Old: {{ __('Hello') }} -New: {% trans %}Hello{% endtrans %} or {{ 'Hello'|trans }} - -2. With simple substitution parameters -Old: {{ __f('Hello %userName%', {'%userName%': 'Mark Smith'}) }} -New: {% trans with {'%userName%': 'Mark Smith'} %}Hello %userName%{% endtrans %} - -3. With explicit domain and locale -Old: {{ __('Hello', 'acmefoomodule', 'fr') }} -New: {% trans with {} from 'acmefoomodule' into 'fr' %}Hello{% endtrans %} or {{ 'Hello'|trans({}, 'acmefoomodule', 'fr' }} -``` - -See [Symfony docs](https://symfony.com/doc/current/translation/templates.html) for further details and examples of simple translation. - -There is also a `desc` filter for specifying a default translation for a key (same as the `@Desc` annotation shown above). Use it like this: - -```twig -{{ 'post.form.title'|trans|desc('Title:') }} -{{ 'welcome.message'|trans({'%userName%': 'John Smith'})|desc('Welcome %userName%!') }} -``` - -### Translation domains -Earlier we used the bundle name as translation domain. The new translation system uses different configurations for different bundles though. You are encouraged to use multiple translation domains now. They should cover different semantical topics and act as a context for translators, like for example `mail`, `messages`, `navigation`, `validators` and `admin`). - -### About plural forms -Here is an example using plural forms, advanced substitution and the `desc` filter: -```twig -Old: {% set amountOfUsers = _fn('%amount% registered user', '%amount% registered users', users|length, {'%amount%': users|length}) %} -New: {% set amountOfUsers = 'plural_n.registered.user'|trans({count: users|length})|desc('{count, plural,\n one {one registered user}\n other {# registered users}\n}') %} -``` - -The `plural_n` portion of the translation key is simply a convention established to note that this key requires plural translation. - -The translation of this would look something like: -```yaml -#messages+intl-icu.en.yaml -plural_n.registered.user: "{count, plural,\n one {one registered user}\n other {# registered users}\n}" -``` - -More advanced translation like plurals and other substitutions require using the Symfony ICU MessageFormatter. See [How to Translate Messages using the ICU MessageFormat](https://symfony.com/doc/current/translation/message_format.html). This requires a specific name format on the translation file and other adjustments. - -### UI-based translations -Zikula 3 introduces two new abilities for creating and changing translations. - -Both can be accessed in the Settings module at the localisation settings if the environment is set to `dev`. - -**Edit in place functionality** -Allows to edit translations directly in the context of a page ([demo](https://php-translation.readthedocs.io/en/latest/_images/edit-in-place-demo.gif)). - -Edit in place has some limitations you should be aware of: - -- It always works for the current locale only; so in order to update translation for multiple languages you need to switch your site's language. -- It can only work with one single configuration. By default this is set to `zikula`, so it works for the core. If you want to use it for a module or a theme, you need to lookup the corresponding configuration name (e.g. `zikulabootstraptheme`) in `/app/config/dynamic/generated.yml` and use this in `/app/config/packages/dev/php_translation.yaml` at `translation.edit_in_place.config_name`. - -You can utilise HTML formatting options when your translation keys end with the `.html` suffix ([screenshot](https://php-translation.readthedocs.io/en/latest/_images/demo-html-editor.png)). - -**Web UI: provides a web interface to add, edit and remove translations.** - -It features a dashboard page ([screenshot](https://php-translation.readthedocs.io/en/latest/_images/webui-dashboard.png)) for the overall progress. When you dive into a translation domain you can use a form to change the translation messages ([screenshot](https://php-translation.readthedocs.io/en/latest/_images/webui-page.png)). - -The web UI is able to handle multiple configurations and target languages. +For more information please refer to the documents in `docs/TranslationAndLanguage/`. ## Twig diff --git a/src/docs/TranslationAndLanguage/Debugging.md b/src/docs/TranslationAndLanguage/Debugging.md index 168bed1b06..594e7ce3f8 100644 --- a/src/docs/TranslationAndLanguage/Debugging.md +++ b/src/docs/TranslationAndLanguage/Debugging.md @@ -1,11 +1,10 @@ # Debugging translations Symfony comes with `bin/console debug:translation` command line tool to debug translations. -**This tool work only with Symfony and Zikula Core-2.0 translation paths.** -Example output for more information please check https://symfony.com/doc/current/translation.html#debugging-translations +Example output: - %> php bin/console debug:translation pl KaikmediaPagesModule + %> php bin/console debug:translation pl --domain=mydomain +----------+-------------+----------------------+ | State(s) | Id | Message Preview (pl) | +----------+-------------+----------------------+ @@ -23,7 +22,11 @@ Example output for more information please check https://symfony.com/doc/current o Unused message = Same as the fallback message +For more information please check https://symfony.com/doc/current/translation.html#debugging-translations + ## Important notes -From Symfony translator documentation + +From Symfony translator documentation: + > Each time you create a new translation resource (or install a bundle that includes a translation resource), be sure to clear your cache so that Symfony can discover the new translation resources. diff --git a/src/docs/TranslationAndLanguage/Extraction.md b/src/docs/TranslationAndLanguage/Extraction.md index 04330d30e7..23d48e93f7 100644 --- a/src/docs/TranslationAndLanguage/Extraction.md +++ b/src/docs/TranslationAndLanguage/Extraction.md @@ -1,11 +1,119 @@ # Translation extraction +To extract translations use the console command `translation:extract`. -Extract all the core translations +To see all of it's option, do this: +``` +php bin/console translation:extract -h +# or +php bin/console translation:extract --help +``` - php bin/console translation:extract zikula en +Example for Zikula core: +``` +# extract for all configured locales +php bin/console translation:extract zikula +# extract only for English +php bin/console translation:extract zikula en +``` -The files will automatically be extracted to the `/translations` directory. +Note `zikula` is the name of our configuration. -See the help file for more information: +Examples for a module or a theme: +``` +php bin/console translation:extract -b AcmeFooModule extension +php bin/console translation:extract --bundle AcmeFooModule extension en +php bin/console translation:extract -b AcmeFooModule acmefoomodule +php bin/console translation:extract --bundle AcmeFooModule acmefoomodule en - php bin/console translation:extract -h +# or with more memory: +php -dmemory_limit=2G bin/console translation:extract --bundle AcmeFooModule extension +php -dmemory_limit=2G bin/console translation:extract --bundle AcmeFooModule acmefoomodule en +``` + +You can always check the status of your translation using the `translation:status` command. +Check the available options using `-h` or `--help` like shown above. + +## Translation annotations + +To influence the extraction behaviour you can utilise some annotations from the `Translation\Extractor\Annotation` namespace. +Import them like any other php class: +```php +use Translation\Extractor\Annotation\Desc; +use Translation\Extractor\Annotation\Ignore; +use Translation\Extractor\Annotation\Translate; +``` + +### `@Desc` +The `@Desc` annotation allows specifying a default translation for a key. + +Examples: + +```php +$builder->add('title', 'text', [ + /** @Desc("Title:") */ + 'label' => 'post.form.title', +]); + +/** @Desc("We have changed the permalink because the post '%slug%' already exists.") */ +$errors[] = $this->translator->trans( + 'post.form.permalink.error.exists', ['%slug%' => $slug] +); +``` + +### desc filter in Twig +There is also a `desc` filter for specifying a default translation for a key in Twig. + +Use it like this: + +```twig +{{ 'post.form.title'|trans|desc('Title:') }} +{{ 'welcome.message'|trans({'%userName%': 'John Smith'})|desc('Welcome %userName%!') }} +``` + +### `@Ignore` +The `@Ignore` annotation allows ignoring extracting translation subjects which are not a string, but a variable. +You can use it for example for `trans()` calls, form labels and form choices. + +Examples: + +```php +echo $this->translator->trans(/** @Ignore */$description); + +$builder->add('modulecategory' . $module['name'], ChoiceType::class, [ + /** @Ignore */ + 'label' => $module['displayname'], + 'empty_data' => null, + 'choices' => /** @Ignore */$options['categories'] +]); +``` + +### `@Translate` +With the `/** @Translate */` you can explicitly add phrases to the dictionary. This helps to extract strings +which would have been skipped otherwise. + +Examples: + +```php +$placeholder = /** @Translate */'delivery.user.not_chosen'; +``` + +It can be also used to force specific domain: + +```php +$errorMessage = /** @Translate(domain="validators") */'error.user_email.not_unique'; +``` + +### Combined example + +If you have a form class which uses a help array with multiple help messages strings you need to prepare it like this: + +```php +$builder->add('myField', [ + // ... + /** @Ignore */ + 'help' => [ + /** @Translate */'This is the first help message.', + /** @Translate */'This is the second help message.' + ] +]); +``` diff --git a/src/docs/TranslationAndLanguage/Installation.md b/src/docs/TranslationAndLanguage/Installation.md index 4236da85fa..a8bb8ab760 100644 --- a/src/docs/TranslationAndLanguage/Installation.md +++ b/src/docs/TranslationAndLanguage/Installation.md @@ -12,14 +12,6 @@ e.g. translations/zikula.de.po translations/zikula_javascript.de.po -After the files have been placed, you must 'install' them by going to +After the files have been placed, you must 'install' them by going to _"General Settings > Localisation settings"_. -General Settings > Localization Settings - -and (without changing anything unless you want to), click 'save' - -This will alter the - - src/config/dynamic/generated.yaml - -file in order to indicate to the system that your new locale/translation is available. +This will update the `src/config/dynamic/generated.yaml` file in order to indicate to the system that your new locale/translation is available. diff --git a/src/docs/TranslationAndLanguage/Javascript.md b/src/docs/TranslationAndLanguage/Javascript.md index 5ad2272fd5..3ccf98f083 100644 --- a/src/docs/TranslationAndLanguage/Javascript.md +++ b/src/docs/TranslationAndLanguage/Javascript.md @@ -1,5 +1,4 @@ # Javascript translation - Zikula includes `willdurand/js-translation-bundle` also known as [BazingaJsTranslationBundle](https://github.com/willdurand/BazingaJsTranslationBundle). Bazinga adds native symfony translation support like so: @@ -16,6 +15,8 @@ Translator.trans(key, params, domain, locale); Translator.transChoice(key, count, params, domain, locale); ``` +See [BazingaJsTranslation docs](https://github.com/willdurand/BazingaJsTranslationBundle/blob/master/Resources/doc/index.md#the-js-translator) for further details and examples. + ## Extraction from Javascript files Zikula also provides an Extractor for both native Symfony and Zikula translation functions. This is run automatically diff --git a/src/docs/TranslationAndLanguage/PluralForms.md b/src/docs/TranslationAndLanguage/PluralForms.md new file mode 100644 index 0000000000..cac916cafb --- /dev/null +++ b/src/docs/TranslationAndLanguage/PluralForms.md @@ -0,0 +1,30 @@ +# Plural forms + +Note: before reading this you should have read the [extraction chapter](Extraction.md) first. + +## PHP files +PHP example using plural forms: +```php +// 4. With plural forms and advanced substitution +$this->_fn('User deleted!', '%n users deleted!', count($deletedUsers), ['%n' => count($deletedUsers)]); +/** @Desc("{count, plural,\n one {User deleted!}\n other {# users deleted!}\n}") */ +$this->getTranslator()->trans('plural_n.users.deleted', ['%count%' => count($deletedUsers)]); +``` + +## Twig template files +Here is an example using plural forms, advanced substitution and the `desc` filter: +```twig +Old: {% set amountOfUsers = _fn('%amount% registered user', '%amount% registered users', users|length, {'%amount%': users|length}) %} +New: {% set amountOfUsers = 'plural_n.registered.user'|trans({count: users|length})|desc('{count, plural,\n one {one registered user}\n other {# registered users}\n}') %} +``` + +The `plural_n` portion of the translation key is simply a convention established to note that this key requires plural translation. + +The translation of this would look something like: +```yaml +#messages+intl-icu.en.yaml +plural_n.registered.user: "{count, plural,\n one {one registered user}\n other {# registered users}\n}" +``` + +## Note about ICU +More advanced translation like plurals and other substitutions require using the Symfony ICU MessageFormatter. See [How to Translate Messages using the ICU MessageFormat](https://symfony.com/doc/current/translation/message_format.html). This requires a specific name format on the translation file and other adjustments. diff --git a/src/docs/TranslationAndLanguage/README.md b/src/docs/TranslationAndLanguage/README.md new file mode 100644 index 0000000000..9fe0540c68 --- /dev/null +++ b/src/docs/TranslationAndLanguage/README.md @@ -0,0 +1,15 @@ +# Translations + +## Basic topics +- [Translation terminology](Terminology.md) +- [Installation of translations](Installation.md) +- [Translator usage](Usage.md) +- [Translation extraction](Extraction.md) +- [Plural forms](PluralForms.md) +- [UI-based translations](UserInterface.md) + +## Specific and advanced topics +- [Translation in Zikula](Translation.md) +- [Javascript translation](Javascript.md) +- [Debugging translations](Debugging.md) +- [Using the PHP and Symfony's Intl classes](Intl.md) diff --git a/src/docs/TranslationAndLanguage/Terminology.md b/src/docs/TranslationAndLanguage/Terminology.md index 4ed775092e..24ea506a9b 100644 --- a/src/docs/TranslationAndLanguage/Terminology.md +++ b/src/docs/TranslationAndLanguage/Terminology.md @@ -4,14 +4,15 @@ The technology for translations used in this guide is simple - anywhere in proje These are translated to other language stored in files or database and loaded on demand instead of English strings. ## Terminology - * **Symfony Translator** - Symfony gettext technology used for translations - * **Zikula Symfony Translator** - Extends Symfony Translator to support Zikula translation conventions. - * **message** - in basic it is translation array element example: 'English string' => 'Translated string' - * **translation template** - .pot file for gettext used only in process of creating new translations. Not used in actual translating. - * **domain** - An optional way to organize messages into groups (e.g. Symfony admin, navigation or the default messages - Zikula zikula, theme_themename, module_modulename and bundlename) - * **catalogue** - Gettext way to organize messages into groups (LC_MESSAGES, LC_TYPE, LC_ALL) - * **locale** - The locale that the translations are for (e.g. en_GB, en, etc); - * **loader** - How Symfony/Zikula should load and parse the file (e.g. xlf, php, yml, etc Zikula .po .mo). + +- **Symfony Translator** - Symfony gettext technology used for translations +- **message** - in basic it is an translation array element; for example: 'English string' => 'Translated string' +- **domain** - An optional way to organize messages into groups (e.g. `admin`, `navigation`, `validators`; default value is `messages`) +- **catalogue** - Gettext way to organize messages into groups (LC_MESSAGES, LC_TYPE, LC_ALL) +- **locale** - The locale that the translations are for (e.g. `en_GB`, `en`, etc); +- **loader** - How Symfony/Zikula should load and parse the file (e.g. `xlf`, `php`, `yml`, `po`, `mo`, etc.). For more information please refer to https://symfony.com/doc/current/translation.html + +## Translation domains +Earlier we used the bundle name as translation domain. The new translation system uses different configurations for different bundles though. You are encouraged to use multiple translation domains now. They should cover different semantical topics and act as a context for translators, like for example `mail`, `messages`, `navigation`, `validators` and `admin`). diff --git a/src/docs/TranslationAndLanguage/Translation.md b/src/docs/TranslationAndLanguage/Translation.md index db7828b0e3..9cae554eb3 100644 --- a/src/docs/TranslationAndLanguage/Translation.md +++ b/src/docs/TranslationAndLanguage/Translation.md @@ -1,25 +1,20 @@ -# Zikula translation +# Translation in Zikula -Zikula translation *is* Symfony translation, with some added bonus features. Please refer to -https://symfony.com/doc/current/translation.html for more information about Symfony features. +Zikula uses the native Symfony translation system. Please refer to https://symfony.com/doc/current/translation.html for more information about Symfony features. -**Paths and file names used by the Symfony Translator** +**Paths and file names used by the Symfony Translator - core system** + + `translations/..` - `app/Resources/translations/..` - e.g. - - `app/Resources/translations/zikula.en.po` -Note: BOTH are loaded and the legacy overwrites the symfony/Core-2.0 type values if the keys are the same in the same -domain because it is loaded second. -Using a *partial* overwrite is possible if you only define the keys you wish to overwrite. + `translations/zikula.en.po` **Paths and file names used by Symfony Translator - bundles (modules, themes etc.)** - `.../Resources/translations/..` where domain is `modulebundlename` or `themebundlename` + `/Resources/translations/..` -## Symfony Translator Loaders +## Symfony translator loaders Symfony comes with standard file format loaders: * ArrayLoader - to load catalogs from PHP arrays. @@ -36,12 +31,11 @@ Symfony comes with standard file format loaders: * YamlFileLoader - to load catalogs from Yaml files. ## Important notes - From Symfony translator documentation > Each time you create a new translation resource (or install a bundle that includes a translation resource), be sure to clear your cache so that Symfony can discover the new translation resources. -Translations are cached in `app/cache//translations/catalogue..` +Translations are cached in `var/cache//translations/catalogue..` ### Fallback locale There is something new in Symfony translator that was not available with legacy mode. diff --git a/src/docs/TranslationAndLanguage/Usage.md b/src/docs/TranslationAndLanguage/Usage.md index a3a0121c47..e533438fee 100644 --- a/src/docs/TranslationAndLanguage/Usage.md +++ b/src/docs/TranslationAndLanguage/Usage.md @@ -1,12 +1,11 @@ # Translator usage -## Translator service - -The translator service can be obtained from container. +## PHP files +### Translator service +The translator service can be obtained from container using `translator` or better be injected. Service is pre-configured to automatically detect current locale, domain is by default set to `'messages'`. -## AbstractController - +### AbstractController Zikula Translator is automatically added in AbstractController and you can access it in your module controller using: ```php @@ -25,10 +24,83 @@ When using `\Zikula\Bundle\CoreBundle\Translation\TranslatorTrait` also a shortc $translated = $this->trans('Page'); ``` -## Twig +### Convert from earlier versions +Some examples for how to convert translations in PHP files: + +```php +// import +use Zikula\Common\Translator\TranslatorInterface; // old +use Symfony\Contracts\Translation\TranslatorInterface; // new + +// 1. Simple: +$this->__('Hello') // old +$this->trans('Hello') // new + +// 2. With simple substitution parameters +$this->__f('Hello %userName%', ['%userName%' => 'Mark Smith']) // old +$this->trans('Hello %userName%', ['%userName%' => 'Mark Smith']) // new + +// 3. With explicit domain +$this->__('Hello', 'acmefoomodule') // old +$this->trans('Hello', [], 'acmefoomodule') // new +``` + +You can still use `Zikula\Bundle\CoreBundle\Translation\TranslatorTrait`, but it has only one method left now: +```php +public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string +``` +You can/should remove the `setTranslator` method from your class which uses the trait. It is not needed anymore. + +### Automatic translations +You should remove all translation calls from the following elements: + +- Strings inside form type classes: + - Form field labels + - Choice labels + - Placeholders + - String values for `empty_value` attribute + - Invalid messages + - Single help messages + - Input group addons + - Alert messages +- Flash messages (`$this->addFlash()` as well as `getFlashBag()->add()`); except when substitution parameters are used. +- Knp menu entries: + - Labels (`$menu->addChild('foo')` as well as `$menu['foo']->setLabel('bar')`) + - Link titles (`setLinkAttribute('title', 'my.title')`) +They will be picked up by the extractor nevertheless. + +More information about how translation of form messages work can be found [here](https://symfony.com/blog/new-in-symfony-4-3-improved-form-translation). + +For a help array with multiple strings you need to use annotations guiding the extractor (see next section). + +### Using the extractor +To extract translations and influence the extractor's behaviour please read [this doc](Extraction.md). + +## Twig template files For translations in Twig Zikula uses native Symfony Twig trans functionality ([docs](https://symfony.com/doc/current/translation/templates.html)). ```twig -{% trans %}Error! That cannot be done'.{% endtrans %} +{% trans %}Error! That cannot be done.{% endtrans %} +``` + +### Convert from earlier versions +Some examples for how to convert translations in templates: + +```twig +1. Simple: +Old: {{ __('Hello') }} +New: {% trans %}Hello{% endtrans %} or {{ 'Hello'|trans }} + +2. With simple substitution parameters +Old: {{ __f('Hello %userName%', {'%userName%': 'Mark Smith'}) }} +New: {% trans with {'%userName%': 'Mark Smith'} %}Hello %userName%{% endtrans %} + +3. With explicit domain and locale +Old: {{ __('Hello', 'acmefoomodule', 'fr') }} +New: {% trans with {} from 'acmefoomodule' into 'fr' %}Hello{% endtrans %} or {{ 'Hello'|trans({}, 'acmefoomodule', 'fr' }} ``` + +See [Symfony docs](https://symfony.com/doc/current/translation/templates.html) for further details and examples of simple translation. + +There is also a `desc` filter for specifying a default translation for a key. You can find an example for this in [this doc](Extraction.md). diff --git a/src/docs/TranslationAndLanguage/UserInterface.md b/src/docs/TranslationAndLanguage/UserInterface.md new file mode 100644 index 0000000000..cc8db4a88b --- /dev/null +++ b/src/docs/TranslationAndLanguage/UserInterface.md @@ -0,0 +1,20 @@ +# UI-based translations +Zikula 3 introduces two new abilities for creating and changing translations. + +Both can be accessed in the Settings module at the localisation settings if the environment is set to `dev`. + +## Edit in place functionality +Allows to edit translations directly in the context of a page ([demo](https://php-translation.readthedocs.io/en/latest/_images/edit-in-place-demo.gif)). + +Edit in place has some limitations you should be aware of: + +- It always works for the current locale only; so in order to update translation for multiple languages you need to switch your site's language. +- It can only work with one single configuration. By default this is set to `zikula`, so it works for the core. If you want to use it for a module or a theme, you need to lookup the corresponding configuration name (e.g. `zikulabootstraptheme`) in `/app/config/dynamic/generated.yml` and use this in `/app/config/packages/dev/php_translation.yaml` at `translation.edit_in_place.config_name`. + +You can utilise HTML formatting options when your translation keys end with the `.html` suffix ([screenshot](https://php-translation.readthedocs.io/en/latest/_images/demo-html-editor.png)). + +## Web UI: provides a web interface to add, edit and remove translations + +It features a dashboard page ([screenshot](https://php-translation.readthedocs.io/en/latest/_images/webui-dashboard.png)) for the overall progress. When you dive into a translation domain you can use a form to change the translation messages ([screenshot](https://php-translation.readthedocs.io/en/latest/_images/webui-page.png)). + +The web UI is able to handle multiple configurations and target languages.