Language localization plugin
1Presentation
This plugin allows two things:
- Manage URLs that are prefixed by language. The plugin will therefore automatically redirect the user to the requested page with /en/ (for example) at the beginning of the URL.
- Automatically load the translations corresponding to the language used, to make the translated strings available to the templates.
2Configuration
In the etc/temma.php file, add the pre-plugin and configure it:
-
Lines 5 to 9: Plugins configuration.
- Line 7: Activation of the pre-plugin that supports language management.
-
Lines 11 to 29: Plugin configuration.
- Line 13: List of languages supported on the site.
- Line 16: Definition of the default language (used if the browser is not compatible with any of the languages listed.
- Lines 22 to 25: Definition of the list of URLs for which language management is disabled.
- Line 28: Disable translation file loading.
-
Lines 31 to 33: Configuration of the Smarty view.
- Line 32: Addition of the directory containing the Smarty plugins provided by Temma, so that the Smarty interpreter is able to find the extension (see below).
3How it works
In the example of the configuration above, we indicate that the site has translations in French, English and German.
When a browser requests a page, two cases can occur:
- The requested URL does not start with /fr/, /en/ nor /de/. In this case, the plugin will redirect the user to the requested URL, adding the language prefix. The language chosen will be the first one supported by the browser which is also supported by the site (if none is suitable, the default language of the site will be used).
- The requested URL begins with a language prefix. In this case, the plugin will check that the requested language is well supported by the site (if this is not the case, we are back in the previous case). If the language is well supported, the plugin will extract the language, and modify all the information relating to the controller, the action and the parameters, to pretend that this prefix did not exist in the URL. Beside that, the plugin loads the corresponding translation file, and adds a prefix to the path leading to the template files.
For example, if the user requests page /page/list/date/5, with a browser that supports French, the plugin will redirect her to /fr/page/list/date/5.
When arriving on /fr/page/list/date/5, the plugin will extract the language (fr), will load the translation file in French. Then it will modify several things:
- The requested controller becomes page (and no longer fr).
- The requested action becomes list (and no longer page).
- The list of parameters becomes
['date', '5']
(and no longer['list', 'date', '5']
).
The template variables $CONTROLLER, $ACTION and $URL are also modified accordingly.
4Management of query methods
If the requested URL begins with language information (and this language is authorized by the configuration), the processing explained above will always be carried out.
On the other hand, if the language information is absent, the redirection (to the same URL to which the language prefix is added) is not carried out if the request had a POST or PUT method. In this case, the plugin does nothing and the processing continues normally.
5Protected URLs
It is possible to define a list of URLs which will not be managed by the language plugin. This is useful if, for example, you have controllers that automatically generate the content of robots.txt or sitemap.xml files.
Please note that URLs must begin with the '/' character.
6Prefix to templates path
Unless the templatePrefix configuration variable has been set to false, the plugin will modify the path leading to the template files, prepending a directory corresponding to the requested language.
Thus, if the URL is /fr/article/list, the template used will be (by default) the file templates/fr/article/list.tpl
If the controller uses another file, the prefix will be added anyway.
For example, if the controller contains the following line:
Temma will use the file templates/fr/cms/content/article_list.tpl
7Translation files
7.1Basic format
The plugin loads files containing the translations. These files must be placed in the project's etc/lang/ directory. As with the configuration file, these files can be in PHP, JSON, INI, YAML or NEON format.
The PHP format is recommended, as it benefits from OPCode caching (the file is not reread each time it is accessed). But you can choose a different format, such as INI, for simplicity's sake.
File names depend on the language of the translations they contain: fr.php, en.ini, es.json, etc.
Here's an example of an fr.php file:
The same thing in INI format (fr.ini file):
In JSON format (fr.json file):
In YAML (file fr.yaml) or NEON (file fr.neon) format:
As you can see, the translated strings are sorted by sections (here default, header and footer). These sections correspond to translation domains.
Here again, the basic strings are in English, and each one provides their translation into French.
Important: If you try to translate a string, but it cannot be found in the translation file, it will be used as is.
In the example above, we can see that the base strings are in English, and that a French translation has been provided.
It will therefore not be necessary to provide an English translation file.
7.2Context management
It's possible to create several versions of a character string. Each of these versions depends on a customizable context. These contexts are used, for example, to manage masculine/feminine versions of a text.
The default context is the one defined first.
To define contexts, simply associate an associative array with the translation key.
Example file fr.php:
And the corresponding en.php file:
7.3Count management (singular/plural)
Translation files can also include different variations of the same character string, depending on the number of elements. This goes further than the simple singular/plural: it can be used when there are no elements, or a variable number of elements.
As with contexts, you need to define an associative array, whose keys are the number of elements corresponding to the declension. It is possible to have keys starting with < or <= to define intervals.
The default value is defined with the * key. If not supplied, the first value in the list will be used.
Example translation file fr.php:
And its en.php version:
7.4Context + count
Contexts and counts can be used together. To do so, each context must contain a countdown.
Here is an example:
8Use in templates
In Smarty templates, two additional variables are created by the plugin:
- $lang: Contains the current language (fr, en, etc.).
- $l10n: Contains the table of translations. Must not be used.
You can use the $lang variable directly in your templates:
Displayed in French, this will look like this:
In English:
You can also use the |l10n modifier and the {l10n}...{/l10n} block tag.
9Templates: modifier
To translate strings, you can use the l10n modifier. It looks for the translation of the string it receives as input, and returns it after escaping any special characters.
Displayed in French:
In English:
- Lines 1 and 2: The strings listed in the default section of the translation file can be used directly.
- Line 4: If the string is not found in the translation file, it is used as is. The special < character is escaped as <.
9.1Modifier: domain
To specify a domain, add it before the translation string, using the hash character (#) to separate the domain from the string.
Displayed in French, this would give:
In english:
9.2Modifier: context and count
The context and count can be supplied after the domain, separated by commas.
If the context is not supplied, the first one listed in the translation file is used. If the count is not supplied, the default count (*) will be used; if it doesn't exist, the first count defined will be used.
Example template:
The result in French:
- Line 1: The default domain is used, the female context, and the count is set to 1.
- Line 2: The domain is not specified, so the default context is used. The context is not specified, so the first one defined is used. The count is 3.
- Line 3: Default domain and female context are used. The count is not specified, so the default count (*) is used.
9.3Modifier: parameters
Parameters can be supplied to the modifier, which will be used to replace portions of text. Each parameter will take the place of a marker of the type %1%, %2%, %3% and so on.
If the translation file contains the following definitions:
Your template may contain:
Displayed in French:
Parameters can of course be used at the same time as domain, context and count.
The domain is available with the %domain% tag.
Context is available with the %ctx% tag.
The count is available with the %count% tag.
For example, with the following translation file:
If your template contains this:
The result will be:
- Line 1: The domain is not specified, so the default domain will be used. The context is not specified, so the first one defined (any) will be used. And we take the value 3 for the countdown.
- Line 2: The default domain is specified. The boys context is specified. The count is set to 0.
- Line 3: Domain not specified. The girls context is specified. The count is 1.
10Templates: block tag
You can also use the Smarty {l10n} block tag.
Displayed in French:
Unlike modifiers, translation blocks do not escape special characters.
10.1Block tag: domain
The default domain is always default. Another domain can be specified using the _ attribute (the underscore character) or the domain attribute on the opening tag.
Displayed in French:
10.2Block tag: context and count
It is possible to specify context and count in two different ways.
The first is to add the ctx and count
attributes to the opening tag.
The second is to use the _ attribute (underscore character),
adding the context and count after the domain, separated by commas.
If the context is not supplied, the first one listed in the translation file will be used. If the count is not supplied, the default count (*) will be used; if it doesn't exist, the first count defined will be used.
Template example:
Displayed in French:
- Line 1: The default domain, the female context, and the count set to 1 are used.
- Line 2: The domain is not specified, so the default context is used. The context is not specified, so the first one defined is used. The count is 3.
- Line 3: Default domain and female context are used. The count is not specified, so the default count (*) is used.
The count attribute can be either a number or an array. If it's an array, its number of elements will be used for the count.
Template example:
Displayed in French:
10.3Block tag: parameters
As with modifiers, translation blocks can receive parameters. These parameters are passed as attributes to the opening {l10n} tag, and used in strings in the form %name_parameter%.
Thus, it's possible to use parameters like name="Luke" in the tag (with the %name% marker in the template). But to be compatible with the parameters used with the modifier (see above), it is recommended to name the parameters using numbers starting at 1. For example, parameter 1="Luke" in the tag, and marker %1% in the template.
If the translation file contains the following definitions:
Your template may contain:
Display in French:
Parameters can of course be used at the same time as domain, context and count.
The domain is available with the %domain% tag.
Context is available with the %ctx% tag.
The count is available with the %count% marker.
For example, with the following translation file:
If your template contains:
It would be exactly the same as this:
The result will be:
- Lines 1 to 3: The domain is not specified, so the default domain is used. The context is not specified, so the first one defined (any) will be used. And we take the value 1 for the count.
- Lines 4 to 6: The default domain is specified. The girlss context is specified. The count is set to 0.
- Lines 7 to 9: The domain is not specified. The boys context is specified. An array is provided for the count, containing 3 elements.
9Prefix to error files
When this plugin is used, it is necessary to translate the error files defined in the errorPages section of the etc/temma.php file (see the documentation).
The paths defined in the configuration then take a prefix consisting of an error-pages directory, followed by a directory corresponding to the language used.
For example, for the following configuration file:
If we ask for a page that does not exist in French (for example the URL /fr/sdsjnzeoizoueh), Temma will look for the file
www/error-pages/fr/error404.html
If we ask for the same page in English (for example the URL /en/sdsjnzeoizoueh), Temma will look for the file
www/error-pages/en/error404.html