February 16th, 2010

Thomas Rabaix: internationalization and Symfony

Hi folks, I'm attending Symfony Live 2010. These are my notes from Thomas Rabaix's talk on internationalization in Symfony, with a few offhand remarks of my own.

Thomas Rabaix talk on internationalization

URL: routingModel: doctrine + propel Form: sfForm

Most of the 18n is based on Prado framework ICU data updated in sf1.3/sf1.4 You need
all:
  .settings:
    i18n: true
    default_culture: en


Culture detection

HTTP request -> culture in URL

If no culture in URL, culture in session

What about culture in the header?

Updates sfRouting, sf18n, executes controller

We're not big on culture in URL in apostrophe since the session can do it but it's nice to be able to bookmark.
sfContext::getInstance()->getUser()->setCulture('fr')
Notify the user.change_culture event (this doesn't do the changing, it just notifies other things that care; why doesn't setCulture do this for us?)
recipe_esarch:
  url: /:sf_culture/recipe/view
Example: /en/recipes/search => sf_culture = en



It's built in, you don't have to pay any mind to the culture yourself.

Or:
/recettes/recherche
/recipes/search
This is not built in, you would need suitable routes. Do we want i18n slugs for Apostrophe?

ysfDimensionPlugin

You can have custom config files per dimension, including a culture dimension
SF_APP_FOLDER/config/en/routing.yml
Con: duplicate route configurations. Pro: no performance hit from trolling through irrelevant routes

Showed a custom subclass of sfPatternRouting, would like to see that fly by again (:

Doctrine is succinct:
Page:
  columns:
    title: string(255)
		content: clob
		enabled: boolean


actAs: i18n: fields: [title, content]
Our friend the clob appears

Default model culture can be accessed through sfDoctrineRecord::getDefaultCulture(), sfDoctrineRecord::setDefaultCulture()

Doctrine:
$page->Translation['fr']->title
$page->getTitle()
$page->title
Propel is a little cleaner
$page->getTitle('fr')
But I suspect you are usually setting the default culture to the user's culture and then going merrily on

ORM never automatically left joins the translation table when building a fancier query. You must do it.

NumberHelper: format_currency
<?php echo format_currency(1000.999, 'EUR', 'en') ?>: Eur1,0001.99
<?php echo format_currency(1000.999, 'EUR', 'fr') ?>: 1 0001,99Eur
format_date and format_datetime helpers are internationalized, we should be using them in preference to date

__() helper translates individual strings in any context
<?php echo __("My name is %name%", array("%name" => "Thomas"), "helpers") ?>
=> My name is Thomas
format_number_choice helper
<?php echo format_number_choice('[0] no file[1] one file[1, Inf]', $n) ?>
Probably didn't copy this quite right but it is a very convenient way to echo one of several possibilities based on a variable, internationalized

sfNumberFormat

sfForm introduced by Alien pic everyone is a little terrified of it at times

sfWidgetFormI18nChoiceCountry, Currency, Language, Timezone, Date, DateTime, Time are all internationalized (although the date and time widgets are very very basic)

Culture is set in the controller, "never use sfContext::getInstance() in your form." It's not clear why not.

Form has a translation callback function through the sfWidgetFormSchemaFormatter class, setTranslationCllable. You can override this to change translation behavior. sf1.3/sf1.4 choice widgets extending sfWidgetFormChoiceBase automatically translate choices provided (so you don't have to call __() yourself, and shouldn't)

Translations can come from a lot of sources... MySQL etc. Generating translations is a bit complicated

So Thomas recommends mgl18nPlugin kindly open sourced by menugourmet.com

Can Apostrophe support culture prefix in URLs out of the box? Probably since it's at the very beginning, a variation on our suggested routes would work fine. And we already automatically fetch the slots for the user's culture.


Check out Apostrophe, our Content Management System for Symfony!
Check out another article
February 11th, 2010
Apostrophe 1.0!
February 10th, 2010
Oh So Close!