avris/micrus-localizator

Localizator for the Micrus Framework

v3.1.0 2017-07-19 10:20 UTC

README

This is a module for Micrus framework that handles localization of your app.

To install this module, open the file app/Config/modules.yml and add:

  - Avris\Micrus\Localizator\LocalizatorModule

Then run:

composer require avris/micrus-localizator

Defining locales

Locale is a set of data that lets you deliver your website adjusted to a given localization. It includes mainly the translations, but also currency, data format and so on.

Locale's identifier is: the ISO 639-1 language code, then an underscore (_), then the ISO 3166-1 alpha-2 country code. Or it might be the language code alone.

Locales are placed in app/Locale directory in form of YAML files, for instance:

- app
	- Locale
		- en.yml
		- en_UK.yml
		- en_UK.yml
		- pl.yml

en.yml would contain words and phrases shared by both British and American English, while en_UK could look like this:

color: Colour
dateFormat: d/m/Y
currency:
  before: £

and en_US like this:

color: Color
dateFormat: m/d/Y
currency:
  before: $

pl should of course all the data in one file, since it has no "children".

In the app/Config/config.yml file you should to set the list of allowed locales and a fallback:

locales:
  en_GB: English (GB)
  en_US: English (USA)
  pl: Polski
  de: Deutsch
fallbackLocale: pl

Now, when a word is to be translated by Micrus' Localizator, and current user's locale is set to en_UK, this is what happens:

  1. Word is looked up in en_UK.yml and returned if found,
  2. Otherwise it's looked up in "parent" locale, en.yml, and returned if found,
  3. Otherwise -- in the fallback, pl.yml, and returned if found,
  4. If translation still not found, the original word is returned untranslated.

If user's current locale were pl, then only pl.yml would be checked.

If no locale is set in the session, Micrus will try to guess the best one, based on browser's headers and the list of available locales.

Translating

Localization is a thing that's really widely used. Virtually every part of the application might want to translate some strings. And rightfully injecting the Localizator service everywhere would be really annoying... That's why localization, exceptionally, has it's global function, l($word, $replacements = [], $set = null, $locale = null). It creates a LocalizedString object, which gets translated when casted to simple string.

$this->addFlash('success', l('entity.Post.create.success', ['title' => $post->getTitle()]));

If your locale contains this entry:

entity:
  Post:
    create:
      success: Post "%title%" has been successfully created!

And your post has a title "Lorem ipsum", then the displayed flash message will say:

Post "Lorem ipsum" has been successfully created!

The localizator can also be used directly:

$this->get('localizator')->get('entity.Post.create.success', ['title' => $post->getTitle()]);

And in the view (in case of Twig):

{{ 'entity.Post.create.success'|l({title: post.title}) }}

Locale sets, conventions

Your app/Locale directory doesn't have to be the only one. External libraries might offer their own. Micrus Forms provides one itself (for the validators). Keeping the locales organized in tree structures helps avoiding conflicts between them. Entries in app/Locale will always overwrite any other locale set.

In order for the translations to be reused amid modules, please stick to the convention regarding all the model-related translations, as shown in the example:

entity:
  User:
    singular: User
    plural: Users
    fields:
      username: Login
      password: Password
      passwordRepeat: Repeat password
      email: Email
      posts: Posts
      postsCount: Posts count
      role: Role
      roleName: Role
      rememberMe: Remember me
    sections:
      access: Access
      activity: Activity

Handlers

This module defines a translationOrder service, which tries to figure out which locale to use, based on:

  • variable _locale in session,
  • tag _locale in URL,
  • HTTP Accept-Language header,
  • the defined fallback.

When a user specifically selects a locale other than what's in their HTTP headers, that locale is saved to session/url thanks to one of the two available handlers.

By default it's SessionLocaleHandler. To use it, just generate a route to changeLocale:

<a href="{{ route('changeLocale', { locale: 'en_UK' }) }}">

If you'd rather pass the locale in the URL, please use UrlLocaleHandler by overwriting the service in services.php:

localizatorHandler:
  class: Avris\Micrus\Localizator\Handler\UrlLocaleHandler
  params: ['@']
  events: ['addRoute', 'generateRoute']
  tags: ['automatcherSpecialTags']
  clear: true

In this case generating a route to switch locale look like this:

{% set newRouteMatch = app.request.routeMatch.withTag('_locale', key) %}
{{ route(newRouteMatch.route.name, newRouteMatch.tags) }}

Copyright