bbc/rmp-translate

Name: rmp-translate

Owner: BBC

Description: A small composer library for translations in /programmes and Amen

Created: 2015-05-28 13:43:17.0

Updated: 2018-05-08 12:55:31.0

Pushed: 2018-05-08 12:56:11.0

Homepage: null

Size: 1406

Language: PHP

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

RMP\Translate

A small composer library to load .po (GetText) translation files and provide a simple API for translations in /programmes and Amen.

This is essentially a wrapper that simplifies the use of Symfony\Translation.

Why?

/programmes is currently being translated into a wide variety of languages for BBC World Service. This requires a translation file format that non-technical users can safely handle. GetText is about the only widely supported format with fully featured editors (including a web based one).

GetText is based around feeding strings in a source language to a translation layer, and having those translated into a target language. BBC localisation generally uses placeholder strings which are replaced with a localised string at run time.

RMP\Translate simplifies the usage of this translation format with Symfony translate, provides a script to convert existing msgformat (BBC_Localisation) files to .po files, and works around some of the bugs that crop up using Symfony translate.

Basic Usage
Installation

First you'll need to include the library in your composer.json like so:

 "repositories": [
        {
            "type": "vcs",
            "url": "git@github.com:bbc/rmp-translate.git"
        }
    ],
    "require": {
        "bbc-rmp/translate": "dev-master"
    }
Instantiation

You then need to set up the configuration and instantiate the translate class. A basic example follows. More details on the configuration options and recommended usage are included below

RMP\Translate\TranslateFactory;
RMP\Translate\Translate;
et to any supported language
ale = 'en_GB';
ions = array();
tory = new TranslateFactory();
nslate = $factory->create($locale, $options);
Translation

Gettext input files and PHP code for some basic examples.

Simple translation:

d "all_episodes_iplayer"
tr "All episodes available on BBC iPlayer"
ceholder = 'all_episodes_iplayer';
lishText = $translate->translate($placeholder);
englishText now contains  "All episodes available on BBC iPlayer"

With substition:

d "category_title"
tr "Programmes categorised as %1"
ceholder = 'category_title';
lishText = $translate->translate($placeholder, array('%1' => 'Factual');
englishText now contains  "Programmes categorised as Factual"

With pluralisation:

d "available_count"
d_plural "available_count %count%"
tr[0] "There are currently no available episodes"
tr[1] "There is currently %count% available episode"
tr[2] "There are currently %count% available episodes"
ceholder = 'available_count';
temsText = $translate->translate($placeholder, array('%count%' => 0), 0);
noItemsText = 'There are currently no available episodes'
eItemsText = $translate->translate($placeholder, array('%count%' => 3), 3);
someItemsText = 'There are currently 3 available episodes'
Updating translation files with new placeholders

This is a two step process. You need to update both the programmes.pot template and the English translation file. Sorry, but that's the way GetText expects you to work.

To add an entry

Open src/RMP/Translate/lang/programmes/programmes.pot and add your new entry.

e English translation
d "my_shiny_new_entry"
tr ""

The comment should contain the full english translation and is needed as guidance for translators in other languages.

msgid can only contain the characters [A-Za-z0-9_:-]. This is a limitation of our translate-tool app and not the PO file format itself.

Entries in the template file should be in alphabetical order. This is so that we can reduce the potential for merge noise, allowing us to focus on specific changes rather than automatic re-ordering. You must either add your entries in the correct order, or add them all at the bottom, then run scripts/alphabetiseAllTranslations.sh programmes to move them into the correct ordering.

After saving the template file, run scripts/updateTranslationsFromTemplate.sh programmes to add the new entries to all translation files. Then edit the en.po file and Add your english translation

e English translation
d "my_shiny_new_entry"
tr "The English translation"

Finally commit and run a composer update in your target application.

To remove an entry:

Remove the entry from the programmes.pot template and run scripts/updateTranslationsFromTemplate.sh programmes

Updating translation files with new translations (supplied by a translator in .po format)

There's a script that does most of this for you “updateLanguageFromSuppliedPO.sh”. For example, to update the Welsh translation file (language code “cy”) from a new file supplied by a translator, you would run

ripts/updateLanguageFromSuppliedPO.sh ~/Downloads/new-translations-cy_GB.po programmes cy

Once you've done that, you'll probably want to run a diff to check everything's OK and remove any superfluous headers added by the .po editor by hand. But the script should take care of any changes in ordering or new/wrong entires that may have been added by the translator's .po editor. It uses msgmerge from the command line internally.

Technical Detail
Features

We support

Configuration options

RMP\Translate provides extensive configuration options, which are supplied to TranslateFactory as an associative array. E.g.

tory = new TranslateFactory();
ions = array('fallback_locale' => 'en_GB', 'cachepath' => '/var/cache/bbc-pal-programmes/translate');
nslate = $factory->create('cy_GB', $options);

Supported options:

Instantiation

It's best to only instantiate RMP\Translate once and store the resulting object somewhere for reuse (we use a singleton in /progs). Instantiation is relatively expensive, while translation is extremely cheap.

Note that TranslateFactory->construct() will throw a TranslationFilesNotFoundException if none of your supplied domains/languages/fallback languages actually exists. It will not complain as long as something valid is actually found, so make sure your language files are actually being loaded during testing.

Logging

You can get logging data from RMP\Translate by attaching an Observer. E.g.

tory = new TranslateFactory();
nslate = $factory->create($locale, $options);
ger = new Logger(); // Logger can be anything that Implements our TranslateObserverInterface
nslate->attach($logger);

The logger will recieve TranslateEvent objects which should be trivial to log using your existing logging infrastructure.

Currently the logger will be notified in the event of missing translations or fallback translations.

Unit Tests

There is a full suite of unit tests. Simply run PHPUnit in the project root.

PO File Format

(this needs tiding up) In order to allow the use of the custom rmp-translate-tool PO file editor, we have created certain extenstions to the PO file format. Basically, we whack in some specially formatted comments (#. “extracted comments” to be precise). These are perfectly valid standard .po comments, but have a special meaning to our app.

You can safely ignore this if you do not plan to use rmp-translate-tool

Current comments that have special meaning and are highlighted to the user with specific presentation are shown below:

For singular form:

nglish: "{The singular form of the English translation of placeholder_string}".
xample URL: {http://your-link-here} .
ype: {Body text|Heading}
d "placeholder_string"
tr "Foreign Language Translation here"

Plural form:

nglish (no items): "{English translation with 0 items}".
nglish (one item): "{English translation with 1 item}".
nglish (2+ items): "{English translation with 2+ items}".
d "available_items_count"
d_plural "available_items_count %count%"
tr[0] "Relevant foreign language translation..."
tr[1] "Relevant foreign language translation..."
tr[2] "Relevant foreign language translation..."

Substitutions:

1 is a variable, which may contain the value: "{example value from /progs}".
d "something_with_substitutions"
tr "blah blah blah"

Priority (filtering)

Replace the curly braces and their contents with some (hopefully relevant and informative) text and you're good to go. Any other comments will be displayed as plain text above the language entry somewhere.

riority: {name of priority type, e.g. "schedules pages"}
d "something to prioritise"
tr "blah"

Replace the curly braces and their contents with some (hopefully relevant and informative) text and you're good to go. Any other comments will be displayed as plain text above the language entry somewhere.

License

This repository is available under the terms of the Apache 2.0 license. View the LICENSE file for more information.

Copyright (c) 2017 BBC


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.