[IMAGE: Technick.com S.r.l. - Open Source Software]
Localizzazione in PHP tramite lo standard TMX
Nicola Asuni, 2004-10-21 / 2006-06-04
Introduzione
TMX - Translation Memory eXchange
TM - Translation Memory
LISA - Localization Industry Standards Association
Bridge PHP per TMX
La classe TMXResourceBundle.php
Classe d\'esempio
Riferimenti
Introduzione
Uno degli aspetti fondamentali dell'internazionalizzazione consiste nel separare dal nucleo del codice sorgente i testi, le etichette, i messaggi ed altre informazioni sensibili alla localizzazione. Questo consente di mantenere la stessa base di codice sorgente per tutte le versioni del prodotto nelle diverse lingue e facilita il processo di traduzione perchè tutte le risorse sensibili al contesto locale sono ben identificate ed isolate.
Quando il nostro mercato di riferimento è quello globale, i costi di traduzione e manutenzione dei testi (che comprendono le etichette, i messaggi, gli elementi di menù, ...) possono assumere dimensioni consistenti. In quest'ottica, l'adozione dello standard TMX consente di introdurre nella gestione dei testi e delle traduzioni i concetti di riuso, aumento della consistenza, riduzione della durata del ciclo produttivo e riduzione dei costi.
TMX - Translation Memory eXchange
http://www.lisa.org/tmx/
TMX è un open standard che utilizza l'XML per l'archiviazione e l'interscambio di memorie di traduzione (TM - Translation Memory) create attraverso l'ausilio di strumenti software di traduzione e localizzazione (CAT - Computer Aided Translation).
TMX è il risultato di un'iniziativa presa da uno degli Special Interest Group di LISA conosciuto come OSCAR (Open Standards for Container/Content Allowing Re-use).
Lo scopo del TMX è quello di offrire un sistema neutrale per lo scambio di dati tra diversi sistemi di traduzione che minimizzi o elimini la perdita di dati critici.
Il formato TMX è supportato dalla maggior parte dei software di traduzione.
Le specifiche dello standard TMX sono liberamente disponibili nel sito http://www.lisa.org/tmx/ dove potrete trovare numerosi riferimenti, documenti, articoli e strumenti software.
Esempio di codice TMX
sample_tmx.xml
hello ciao world mondo dove:
tu: translation unit, unità padre di ogni elemento da tradurre, può contenere un identificatore univoco (tuid).
tuv: translation unit variant, unità contenente il codice di lingua della traduzione (xml:lang).
seg: segment, contiene la traduzione.
TM - Translation Memory
http://www.opentag.com/tm.htm
Translation Memories (TM), conosciute anche come Translation Databases, sono essenzialmente costituite da un database (archivio) dove le frasi del testo di riferimento sono associate alle corrispondenti traduzioni in una o più lingue.
L'insieme della frase di riferimento con le sue traduzioni è detto translation memory unit.
Le applicazioni che fanno uso delle TM, sono strumenti di ausilio alla traduzione linguistica, progettate per migliorare la qualità e l'efficenza del processo di traduzione umana e non per sostituirlo.
Ogni nuova frase inserita attraverso l'applicazione TM verrà cercata tra le frasi di riferimento nel database e ne verrà calcolato un valore di corrispondenza.
Quando il valore di corrispondenza sarà del 100% (exact match) la traduzione presente nel database verrà direttamente inserita nel testo da tradurre. Quando il valore di corrispondenza sarà inferiore al 100% ma superiore ad una certa soglia (fuzzy match), la frase tradotta verrà inserita come traduzione proposta che dovrà essere verificata ed eventualmente corretta da traduttore umano. Le frasi con un margine di corrispondenza sotto il margine di soglia andranno tradotte manualmente per intero. Le nuove frasi inserite verranno registrate nel database per esser utilizzate per future traduzioni.
Diverse aziende offrono complessi prodotti commerciali in questo settore.
LISA - Localization Industry Standards Association
http://www.lisa.org
Fondata nel 1990, LISA è la principale organizzazione mondiale no-profit per il GILT (Globalizzazione, Internazionalizzazione, Localizzazione e Traduzione). LISA si rivolge ad individui, aziende, associazioni ed organizzazioni per gli standard, che si occupano di lingue e tecnologie per le lingue.
Oltre 400 aziende leader nel settore IT, service providers e professionisti che rappresentano le grandi aziende con mercati internazionali, hanno contribuito a stabilire le linee guida di LISA basate sul best practice e gli standard tecnologici per le lingue a supporto della globalizzazione.
LISA mette in contatto fra loro numerosi soggetti che contribuiscono al processo di internazionalizzazione delle aziende e che comprendono: consumatori, governi, organizzazioni per gli standard, istituti di ricerca e consulenza, fornitori di servizi e di tecnologie per la taduzione e localizzazione.
LISA offre servizi sotto forma di iniziative per la standardizzazione, Special Interest Groups, conferenze e programmi di apprendimento di supporto GILT alle imprese.
I soci ed i gruppi affiliati a LISA comprendono l'International Organization for Standardization (ISO Liaison Category A Members of TC 37 and TC 46), World Bank, OASIS, IDEAlliance, AIIM, Advisory Council (TAC), Fort-Ross, €TTEC, Japan Technical Communicators Association, Society of Automotive Engineers (SAE), European Union, Canadian Translation Bureau, TermNet, American Translators Association (ATA), IWIPS, Fédération Internationale des Traducteurs (FIT), Termium, JETRO, Institute of Translating and Interpreting (ITI), Unicode Consortium, OpenI18N, professionisti ed organizzazioni per il commercio.
Tra i membri ed i co-fondatori di LISA spiccano alcune tra le aziende più grandi e conosciute a livello mondiale: Adobe, Avaya, Cisco Systems, CLS Communication, EMC, Hewlett Packard, IBM, Innodata Isogen, Fuji Xerox, Microsoft, Oracle, Nokia, Logitech, SAP, Siebel Systems, Standard Chartered Bank, FileNet, LionBridge Technologies, Lucent, Sun Microsystems, WH&P, PeopleSoft, Philips Medical Systems, Rockwell Automation, The RWS Group, Xerox Corporation and Canon Research.
Bridge PHP per TMX
Attraverso gli array, PHP dispone di una soluzione pratica per la localizzazione. È infatti possibile estrarre gli elementi testuali dal codice sorgente originale ed isolarli come elementi di un array. Gli array PHP sono in realtà delle mappe ordinate, ovvero dei tipi di dato che mettono in relazione valori e chiavi. Questo tipo di dato è otimizzato in diversi modi così da poter essere utilizzato come un array reale, una lista (vector), una hashtable (che è l'implementazione di una map), un dizionario, una collezione, una pila, una coda o altro.
Questa soluzione offre dei sicuri vantaggi al programmatore ma può risultare piuttosto complessa dal punto di vista del traduttore, sopratutto in termini di riusabilità della traduzione.
Un eccellente alternativa consiste nell'archiviazione delle risorse testuali nel formato di interscambio TMX (file XML) che consente ai traduttori di importare ed esportare le traduzioni da o verso i loro strumenti di traduzione (ne esistono diversi in commercio compatibili con TMX) in maniera totalmente indipendente dal linguaggio di programmazione utilizzato.
La soluzione ottimale per implementare lo standard TMX nelle applicazioni PHP, consiste nel creare un bridge in grado di leggere direttamente i dati da file XML conformi allo standard TMX e di caricarli in un array PHP (array PHP ==> file TMX <== programma di traduzione).
Cio consente di sfruttare tutti i vantaggi offerti dagli array PHP e di rendere più semplice il porting verso TMX delle applicazioni esistenti.
Gli svantaggi offerti da questa tecnica sono principalmente dovuti al tempo ed alla memoria necessaria per il caricamento dell'intero file TMX.
Al fine di semplificare l'esposizione, prenderemo in considerazione solo quegli elementi TMX necessari a tradurre un testo semplice (vedi sample_tmx.xml):
tu: translation unit, unità padre di ogni elemento da tradurre, può contenere un identificatore univoco (tuid).
tuv: translation unit variant, unità contenente il codice di lingua della traduzione (xml:lang).
seg: segment, contiene la traduzione.per esempio:
hello ciao
La classe TMXResourceBundle.php
Attraverso il costruttore specifichiamo il nome ed il percorso del file in formato TMX dove sono contenute le traduzioni ed il codice ISO della lingua di cui vogliamo estrarre le traduzioni.
All'interno del costruttore della classe definiamo il nostro parser TMX utilizzando le funzioni XML Parser di PHP che fanno uso delle librerie expat, abilitate in maniera predefinita. Queste funzioni permettono di creare dei parser XML non-validanti e di definire degli handlers per la gestione dei diversi eventi XML. Ogni parser XML dispone anche di alcuni parametri regolabili.
I metodi startElementHandler e endElementHandler provvedono rispettivamente ad impostare il valore di alcune variabili di stato quando incontrano l'apertura di un elemento TMX e ad annullarne il valore in corrispondenza degli elementi di chiusura. Le variabili di stato mantengono le informazioni relative all'elemento TMX che stiamo processando.
Il metodo segContentHandler provvede a processare le stringhe di caratteri presenti tra gli elementi XML. Se ci troviamo all'interno di un nodo seg ed il valore dell'attributo xml:lang del nodo padre tuv è uguale a quello specificato come parametro del costruttore, allora il metodo segContentHandler provvede ad associare la stringa trovata ad un'elemento dell'array resource che avrà come indice il valore dell'attributo tuid del nodo padre tu.
Al termine del parsing, l'array resource conterrà tutte le traduzioni nella lingua richiesta indicizzate secondo i rispettivi identificatori (tuid).
Codice Sorgente
(scarica l'intero progetto da Sourceforge).
value). * * @name TMXResourceBundle * @package com.tecnick.tmxphpbridge * @abstract TMX-PHP Bridge Class * @link http://tmxphpbridge.sourceforge.net * @license http://www.gnu.org/copyleft/lesser.html LGPL * @author Nicola Asuni [www.tecnick.com] * @copyright Copyright (c) 2004-2006 - Tecnick.com S.r.l (www.tecnick.com) - Via Ugo Foscolo n.19 - 09045 Quartu Sant'Elena (CA) - ITALY - www.tecnick.com - info@tecnick.com * @version 1.1.004 */class TMXResourceBundle { /** * @var array Array used to contain key-translation couples. * @access private */ private $resource = array(); /** * @var string Current tu -> tuid value. * @access private */ private $current_key = ""; /** * @var string Current data value. * @access private */ private $current_data = ""; /** * @var string Current tuv -> xml:lang value. * @access private */ private $current_language = ""; /** * @var boolean Is TRUE when we are inside a seg element * @access private */ private $segdata = false; /** * @var string ISO language identifier (a two- or three-letter code) * @access private */ private $language = ""; /** * @var string filename for cache * @access private */ private $cachefile = ""; /** * Class constructor. * @param string $tmxfile TMX (XML) file name * @param string $language ISO language identifier (a two- or three-letter code) * @param string $cachefile set filename for cache (leave blank to exclude cache) */ public function __construct($tmxfile, $language, $cachefile="") { // reset array $this->resource = array(); // set selecteed language $this->language = strtoupper($language); // set filename for cache $this->cachefile = $cachefile; if (file_exists($this->cachefile)) { // read data from cache require_once($this->cachefile); $this->resource = $tmx; } else { if (!empty($this->cachefile)) { // open cache file file_put_contents($this->cachefile, "<"."?phpn". "// CACHE FILE FOR LANGUAGE: ".$language."n". "// DATE: ".date("Y-m-d H:i:s")."n". "// *** DELETE THIS FILE TO RELOAD DATA FROM TMX FILE ***n", FILE_APPEND); } // creates a new XML parser to be used by the other XML functions $this->parser = xml_parser_create(); // the following function allows to use parser inside object xml_set_object($this->parser, $this); // disable case-folding for this XML parser xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); // sets the element handler functions for the XML parser xml_set_element_handler($this->parser, "startElementHandler", "endElementHandler"); // sets the character data handler function for the XML parser xml_set_character_data_handler($this->parser, "segContentHandler"); // start parsing an XML document if(!xml_parse($this->parser, file_get_contents($tmxfile))) { die(sprintf("ERROR TMXResourceBundle :: XML error: %s at line %d", xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser))); } // free this XML parser xml_parser_free($this->parser); if (!empty($this->cachefile)) { // close cache file file_put_contents($this->cachefile, "nn// EOF ----------"."n?".">", FILE_APPEND); } } } /** * Class destructor; resets $resource array. */ public function __destruct() { $resource = array(); // reset resource array } /** * Sets the start element handler function for the XML parser parser.start_element_handler. * @param resource $parser The first parameter, parser, is a reference to the XML parser calling the handler. * @param string $name The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. * @param array $attribs The third parameter, attribs, contains an associative array with the element's attributes (if any). The keys of this array are the attribute names, the values are the attribute values. Attribute names are case-folded on the same criteria as element names. Attribute values are not case-folded. The original order of the attributes can be retrieved by walking through attribs the normal way, using each(). The first key in the array was the first attribute, and so on. * @access private */ private function startElementHandler($parser, $name, $attribs) { switch(strtolower($name)) { case 'tu': { // translation unit element, unit father of every element to be translated. It can contain a unique identifier (tuid). if (array_key_exists('tuid', $attribs)) { $this->current_key = $attribs['tuid']; } break; } case 'tuv': { // translation unit variant, unit that contains the language code of the translation (xml:lang) if (array_key_exists('xml:lang', $attribs)) { $this->current_language = strtoupper($attribs['xml:lang']); } break; } case 'seg': { // segment, it contains the translated text $this->segdata = true; $this->current_data = ""; break; } default: { break; } } } /** * Sets the end element handler function for the XML parser parser.end_element_handler. * @param resource $parser The first parameter, parser, is a reference to the XML parser calling the handler. * @param string $name The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. * @access private */ private function endElementHandler($parser, $name) { switch(strtolower($name)) { case 'tu': { // translation unit element, unit father of every element to be translated. It can contain a unique identifier (tuid). $this->current_key = ""; break; } case 'tuv': { // translation unit variant, unit that contains the language code of the translation (xml:lang) $this->current_language = ""; break; } case 'seg': { // segment, it contains the translated text $this->segdata = false; if (!empty($this->current_data) OR !array_key_exists($this->current_key, $this->resource)) { $this->resource[$this->current_key] = $this->current_data; // set new array element if (!empty($this->cachefile) AND ($this->current_language == $this->language)) { // write element to cache file file_put_contents($this->cachefile, "n$"."tmx['".$this->current_key."']="".str_replace(""", "\"", $this->current_data)."";", FILE_APPEND); } } break; } default: { break; } } } /** * Sets the character data handler function for the XML parser parser.handler. * @param resource $parser The first parameter, parser, is a reference to the XML parser calling the handler. * @param string $data The second parameter, data, contains the character data as a string. * @access private */ private function segContentHandler($parser, $data) { if ($this->segdata AND (strlen($this->current_key)>0) AND (strlen($this->current_language)>0)) { // we are inside a seg element if (strcasecmp($this->current_language, $this->language) == 0) { // we have reached the requested language translation $this->current_data .= $data; } } } /** * Returns the resource array containing the translated word/sentences. * @return Array. */ public function getResource() { return $this->resource; } } // END OF CLASS//============================================================+// END OF FILE //============================================================+?>
La classe di test tmxtest.php
Questa classe mostra come istanziare la classe TMXResourceBundle con il file di esempio sample_tmx.xml.
Nell'esempio il codice della lingua (it = italiano) viene specificato in maniera esplicita ma può essere anche ricavato dall'ambiente locale.
Codice Sorgente
getResource(); // language array for english$l_it = $tmx_it->getResource(); // language array for italianecho "<"."?"."xml version="1.0" encoding="UTF-8""."?".">n";echo "n";echo "n";echo "
n";echo "XMLConfigReader Examplen";echo "n";echo "n";echo "n";echo "TMXResourceBundle Example
n";echo "English:
n";// list keys and valuesecho "n";while (list($key, $val) = each($l_en)) { echo "- $tmx->resource['".$key."'] = ".$val."
n";}echo "
n";echo "Italian:
n";// list keys and valuesecho "";while (list($key, $val) = each($l_it)) { echo "- $tmx->resource['".$key."'] = ".$val."
n";}echo "
n";echo "";//============================================================+// END OF FILE //============================================================+?>
Riferimenti
ASUNI N, "PHP Localization with TMX standard", PHP Solutions Nr 3/2006, pl/en/it/fr/es/de
Asuni N, "TMXResourceBundle - TMX PHP Bridge" [online] 2005-01-08, http://tmxphpbridge.sourceforge.net.
Asuni N, "TMXResourceBundle - TMX Java Bridge" [online] 2005-01-08, http://tmxjavabridge.sourceforge.net.
Itagaki M, "Use XML as a Java Localization Solution" [online] 2000-11-10, http://www.ftponline.com/javapro/archives/mi0011/default.asp.
O'Conner J, "Java Internationalization: Localization with ResourceBundles" [online] 1998-10-01, http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles/.
OSCAR - LISA, "TMX - Translation Memory eXchange" [online] 2004-10-01, http://www.lisa.org/standards/tmx.
OSCAR - LISA, "TMX 1.4b Specification" [online] 2005-03-26, http://www.lisa.org/standards/tmx/tmx.html.
W3C, "Extensible Markup Language (XML)" [online] 2005-08-02, http://www.w3.org/XML/.
nome:password:[registrati]
Home
Azienda
Servizi - Prodotti
Utente
Utilità
News
Newsletter
Links
Contatti
| TXT | TXT+ |
Il contenuto di questo sito è protetto da copyright © Tecnick.com s.r.l. Tutti i diritti riservati.
Tecnick.com s.r.l. - Sede Legale: Via Della Pace, 11 – 09044 – Quartucciu (CA) – ITALY - Capitale Sociale € 10.000,00 i.v. - P. IVA e C.F.: 02574420929 - C.C.I.A.A.: CA-2000-19195 - R.E.A.: 208980
[IMAGE: Powered by Tecnick.com AIOCP (All In One Control Panel)][IMAGE: Tecnick.com is Java.net Silver Partner]
[IMAGE: Valid XHTML 1.0!][IMAGE: Valid CSS1!][IMAGE: Level Double-A conformance icon, W3C-WAI Web Content Accessibility Guidelines 1.0]
Home
Azienda
Informazioni
Privacy
Netiquette
Impostazione Browser
Riconoscimenti
Vendita
Servizi - Prodotti
SUPPORTO
Open Source
TCPDF
TCExam
GASoffice.net
AIOCP
JADC
Impostazione
Esempi
JDDM
Impostazione
Esempi
JWTM
Impostazione
Esempi
JUnitConv
Impostazione
Esempio
JXHTMLEDIT
Impostazione
Demo
JRelaxTimer
Impostazione
Galleria Lavori
Galleria Loghi
Utente
login
logout
On-Line
Registrazione
Utilità
Codice Fiscale
News
Cerca
Newsletter
Cerca
Registrazione
Links
Cerca
Ring
Contatti
lingua
English
Italian
newsletter
[IMAGE: Bookmark and Share]
EnglishItalian[IMAGE: English] [IMAGE: Italian]