Lokaliser webprogrammet ditt for ethvert land med Google Translate API

Hva du skal skape

I min veiledning Lokalisering Med I18n for å bygge opp oppstarten med PHP-serien, opprettet jeg prøve spansk kode ved å kutte og lime inn tekststrenger i Google Translate. Jeg begynte å lure på om jeg kunne integrere Google Translate API med Yii Framework's I18n ressursutvinningsskript for å automatisere oversettelsen for en rekke land. Jeg postet en funksjonsforespørsel på Yii Forum og bestemte meg for å se om jeg selv kunne bygge funksjonen.

I denne opplæringen vil jeg gå gjennom utvidelsene til Yii I18n-utskriftskriptet som gjør akkurat dette. Og jeg demonstrerer at jeg oversetter min oppstartsprogram, møteplanlegger, til en håndfull språk.

Husk, Google Translate er ikke perfekt, og det tar ikke opp problemer relatert til tid og datoformater og valutaer. Men for en rask og rimelig (gratis) måte å bygge standard oversettelser for din webapplikasjon til 50 + språk, er dette en ideell løsning.

For eksempel, men her er en mer merkbar feil jeg kjørte inn i testing-heldigvis er disse sjeldne:

'nFormatted TB' => 'nFormatted tuberkulose', 

Hvis du trenger en mer profesjonell tilnærming, viste en venn meg en betalt tjeneste for å administrere lokalisering innen apps, Transifex. Jeg har ikke sjekket ut det selv, men det ser spennende ut.

Arbeider med Google Translate

Hvilke språk støtter det?

Google Translate tilbyr oversettelsestjenester for 64 språk, inkludert svensk men dessverre ikke svensk kokk:

Her er et utvalg av Googles støttede språk - se hele listen her:

Snakker med Google Translate API

Jeg fant to Composer-biblioteker for å jobbe med Google Translator API i PHP:

  • Levan Velijanashvili's Google Translate-bibliotek
  • Travis Tillotsons Google Oversettelsesklient

Jeg fant Velijanashvili først, så det er det jeg brukte i denne opplæringen. Det utnytter Google Translate via sitt gratis RESTful webgrensesnitt, slik at du ikke trenger en API-nøkkel. Men hvis du har et stort bibliotek med ressurser eller planlegger å oversette mange språk, vil du sannsynligvis ønske å integrere Tillotson, da den er fullt integrert med Google Translates betalte tjeneste via nøkler.

For denne opplæringen bygger jeg på Building Your Startup With PHP-serienes kodebase. For å installere Velijanashvili's Google Translate-bibliotek, skriv bare:

komponist krever stichoza / google-translate-php

Her er noen eksempler for å oversette fra engelsk til spansk:

bruk Stichoza \ Google \ GoogleTranslate; ekko GoogleTranslate :: staticTranslate ("hej verden", "no", "es"). "\ N"; 

Det skal skrive ut:

hola mundo

Utvider Yii2s I18n Message / Extract Script

Hvordan Yii2s I18n-støtte fungerer i dag

På denne tiden vil du kanskje gå gjennom lokaliseringen med I18n-opplæringen som forklarer hvordan du fjerner meldingsstrenger for de nødvendige språkoversettelsene dine. 

Du kan bruke Yi's Gii-kodegenerator til å generere modeller og CRUD-kode som automatisk integrerer I18n-støtte. Hver streng i koden er erstattet av en funksjonsanrop som Yii :: t ('kategori', 'tekststreng å oversette');.

Yii tilbyr en konsollkommando melding / utdrag som finner alle disse funksjonene i applikasjonen din, og lager et katalogtreet av filer etter språk og kategori for oversettelser av alle disse strengene.

Her er et eksempel på strengfil for tysk:

 'Maskinen er startet', 'Overskrift' => 'Überschrift', 'My Yii Application' => 'Meine Yii-Anwendung', 'Yii Dokumentasjon' => 'Yii Dokumentasjon', 'Yii Extensions' => ' Yü -Erweiterungen ',' Yii Forum '=>' Yii Forum ',' Er du sikker på at du vil slette dette elementet? ' => 'Sind Sie sicher, Sie wollen diesen Inhalt löschen?', 'Gratulerer!' => 'Herzlichen Glückwunsch!', 'Create' => 'schaffen', 'Opprett modelClass' => 'schaffen modelClass', 'Created At' => 'Erstellt am', 'Delete' => 'löschen ',' ID '=>' Identifikasjon ',

Her er et eksempel på katalogbanene:

Utvidelse av melding / utdrag for Google Translate

Jeg valgte tilnærmingen til å lage et erstatningsskript kalt melding / google_extract som ville kalle Google Translate når det trengte å oversette en streng.

Forhindre ødelagt kode fra oversettelsestokener

Fordi I18n integrerer parameter tokens i krøllete braces for variable verdier, løp jeg i noen problemer med en gang. For eksempel, her er noen I18n-strenger som inkluderer tokens og nestede tokens:

'Create modelClass "Registrert på 0, dato, MMMM dd, ÅÅÅÅHH: mm fra 1" 0, dato, MMMM dd, ÅÅÅÅHH: mm "nFormatted n, flertall, = 1 gibibyte andre gibibytes '

Google Translate API har ikke en parameter for å ignorere tokens som disse i dette skjemaet. Men vi kan ikke oversette disse fordi de tilsvarer variable navn og formatstrenger i kode.

Det virket ikke for meg at et regulært uttrykk kunne løse dette der oversetterbare strenger og tokens var tilstede sammen. Det er sannsynlig at leserne kan ha en mer effektiv løsning enn jeg fant for å løse dette problemet. Hvis det er klart for deg, vennligst legg det inn i kommentarene.

Jeg valgte å skanne strengene etter tegn og spore hekken på krøllete bånd. Jeg blir den første til å innrømme at det kan være en bedre måte. Her er min funksjon parse_safe_translate ():

/ * * Parser en streng i en matrise * Spalt av noen krøllede braketsegmenter * inkludert nestede krølles parentes * / Offentlig funksjon parse_safe_translate ($ s) $ debug = false; $ result = array (); $ Start = 0; $ nest = 0; $ Ptr_first_curly = 0; $ total_len = strlen ($ s); for ($ i = 0; $ i<$total_len; $i++)  if ($s[$i]=='')  // found left curly if ($nest==0)  // it was the first one, nothing is nested yet $ptr_first_curly=$i;  // increment nesting $nest+=1;  elseif ($s[$i]=='')  // found right curly // reduce nesting $nest-=1; if ($nest==0)  // end of nesting if ($ptr_first_curly-$start>= 0) // push streng som fører opp til første venstre krøll $ prefix = substr ($ s, $ start, $ ptr_first_curly- $ start); if (strlen ($ prefix)> 0) array_push ($ result, $ prefix);  // push (muligens nestet) krøllete streng $ suffix = substr ($ s, $ ptr_first_curly, $ i- $ ptr_first_curly + 1); hvis (strlen ($ suffiks)> 0) array_push ($ resultat, $ suffiks);  hvis ($ debug) echo '|' substr ($ s, $ start, $ ptr_first_curly- $ start-1). "| \ n"; ekko '|' .substr ($ s, $ ptr_first_curly, $ i- $ ptr_first_curly + 1). "| \ n";  $ start = $ i + 1; $ Ptr_first_curly = 0; hvis ($ debug) echo 'neste start:'. $ start. "\ n";  $ suffix = substr ($ s, $ start, $ total_len- $ start); hvis ($ debug) echo 'Start:'. $ start. "\ n"; ekko 'Pfc:'. $ ptr_first_curly. "\ n"; ekko $ suffiks. "\ n";  hvis (strlen ($ suffiks)> 0) array_push ($ resultat, substr ($ s, $ start, $ total_len- $ start));  returnere $ resultat;  

Den konverterer en I18n-streng til en rekke elementer separert i oversettbare og uoverførbare elementer. For eksempel, denne koden:

$ message = 'Bildet "file" er for stort. Høyden kan ikke være større enn grense, tall grense, flertall, en piksel andre piksler. '; print_r ($ dette-> parse_safe_translate ($ melding)); 

Genererer denne utgangen:

Array ([0] => Bildeet [1] => file [2] => "er for stort. Høyden kan ikke være større enn [3] => grense, tall [4] => 5] => grense, flertall, en piksel andre piksler [6] =>.) 

Når uttrekksprosessen identifiserer en ny streng som skal oversettes, bryter den strengen inn i disse delene og kaller Google Translate API for en oversettbar streng, f.eks. en som ikke begynner med en venstre krøllet brace. Deretter konkluderer de oversettelsene med de tokeniserte strengene tilbake til en enkelt streng.

Oversette en Tokenized String med Google Translate

Her er funksjonen getGoogleTranslation () for en streng og et destinationsmål. Kildespråket bestemmes av Yii :: $ app-> språk.

 offentlig funksjon getGoogleTranslation ($ message, $ language) $ arr_parts = $ this-> parse_safe_translate ($ melding); $ transl = "; foreach ($ arr_parts as $ str) hvis (! stristr ($ str, '')) hvis (strlen ($ oversettelse)> 0 og substr ($ translation, -1) == ' ') $ translation. = "; $ translation. = GoogleTranslate :: staticTranslate ($ str, Yii :: $ app-> språk, $ språk);  annet // legg til mellomrom prefiks med mindre det er først hvis (strlen ($ translation)> 0) $ translation. = ". $ str; else $ oversettelse. = $ str; print_r ($ translation); return $ translation;  

Jeg fant at kombinasjonen av disse tilnærmingene fungerte nesten perfekt i testingen min.

Tilpasse Yiis melding / utdrag

Yii's I18n-implementering støtter å laste ressursstrenger fra .PO-filer, .PHP-filer (som jeg bruker) og databasen. For denne opplæringen har jeg tilpasset melding / utdrag for PHP-filgenerasjonen.

Jeg kopierte og utvidet melding / ekstrakt i /console/controllers/TranslateController.php. På grunn av PHP 5.6.x strenge regler endret jeg funksjonsnavnene for saveMessagesToPHP til saveMessagesToPHPEnhanced og saveMessagesCategoryToPHP til saveMessagesCategoryToPHPEnhanced.

Her er saveMessagesToPHPEnhanced () funksjon:

/ ** * Skriver meldinger til PHP-filer * * @param array $ messages * @param string $ dirName navn på katalogen for å skrive til * @param boolean $ overskrive hvis eksisterende fil skal overskrives uten sikkerhetskopiering * @param boolean $ removeUnused if forældede oversettelser bør fjernes * @param boolean $ sort hvis oversettelser skal sorteres * / beskyttet funksjon saveMessagesToPHPEnhanced ($ messages, $ dirName, $ overwrite, $ removeUnused, $ sort, $ language) foreach ($ meldinger som $ kategori => $ msgs) $ file = str_replace ("\\", '/', "$ dirName / $ category.php"); $ path = dirname ($ file); FileHelper :: createDirectory ($ path); $ msgs = array_values ​​(array_unique ($ msgs)); $ coloredFileName = Konsoll :: ansiFormat ($ file, [Console :: FG_CYAN]); $ this-> stdout ("Lagre meldinger til $ coloredFileName ... \ n"); $ this-> saveMessagesCategoryToPHPEnhanced ($ msgs, $ file, $ overwrite, $ removeUnused, $ sort, $ category, $ language);  

Det kaller saveMessagesCategoryToPHP funksjon:

/ ** * Skriver kategorimeldinger i PHP-fil * * @param array $ messages * @param string $ filnavn navn på filen som skal skrives til * @param boolean $ overskrive hvis eksisterende fil skal overskrives uten sikkerhetskopiering * @param boolean $ removeUnused hvis foreldede oversettelser skal fjernes * @param boolean $ sort hvis oversettelser skal sorteres * @param booleansk $ språk språk å oversette til * @param boolean $ force google translate * @param streng $ kategori meldingskategori * / beskyttet funksjon lagreMessagesCategoryToPHPEnhanced ($ meldinger, $ fileName, $ overwrite, $ removeUnused, $ sort, $ kategori, $ språk, $ force = true) if (is_fil ($ fileName)) $ existingMessages = krever ($ fileName); sorterings ($ messages); ksort ($ existingMessages); $ this-> stdout ("Ingen nye i \" $ kategori \ "kategori ... Ingenting å lagre. \ n \ n", Console: : FG_GREEN); komme tilbake;  $ fusjonert = []; $ untranslated = []; foreach ($ meldinger som $ melding) hvis (array_key_exists ($ message, $ existingMessages) && strlen ($ existingMessages [$ message])> 0) $ fusjonert [$ message] = $ existingMessages [$ message];  ellers $ untranslated [] = $ message;  ksort ($ fusjonert); sort ($ uoversatt); $ todo = []; foreach ($ untranslated as $ message) $ todo [$ message] = $ this-> getGoogleTranslation ($ message, $ language);  ksort ($ existingMessages); foreach ($ existingMessages as $ message => $ translation) if (! isset ($ fusjonert [$ melding]) &&! isset ($ todo [$ message]) &&! $ removeUnused) if && strncmp ($ translation, '@@', 2) === 0 && substr_compare ($ oversettelse, '@@', -2, 2) === 0) $ todo [$ message] = $ translation;  ellers $ todo [$ message] = '@@'. $ oversettelse. '@@';  $ fusjonert = array_merge ($ todo, $ fusjonert); hvis ($ sort) ksort ($ fusjonert);  hvis (false === $ overskrive) $ fileName. = '.merged';  $ this-> stdout ("Oversettelse fusjonert. \ n");  ellers $ merged = []; foreach ($ meldinger som $ melding) $ fusjonert [$ message] = "; ksort ($ fusjonert); $ array = VarDumper :: eksport ($ fusjonert); $ content = <<id 'kommando. * Den inneholder lokaliserbare meldinger hentet fra kildekoden. * Du kan endre denne filen ved å oversette utdragne meldinger. * * Hvert arrayelement representerer oversettelsen (verdien) av en melding (nøkkel). * Hvis verdien er tom, anses meldingen som ikke oversatt. * Meldinger som ikke lenger trenger oversettelse, vil ha sine oversettelser * vedlagt mellom et par '@@' -merker. * * Meldingstreng kan brukes med flertallsformat. Kontroller i18n avsnitt * i veilederen for detaljer. * * MERK: denne filen må lagres i UTF-8-koding. * / retur $ array; EOD; file_put_contents ($ fileName, $ content); $ this-> stdout ("Oversettelse lagret. \ n \ n", Konsoll :: FG_GREEN); 

Dessverre kommenteres ikke den opprinnelige meldings- / uttrekkskoden. Selv om det kan være noen ekstra forbedringer som kan gjøres, har jeg bare lagt til et anrop til Google Translate API her:

foreach ($ untranslated as $ message) $ todo [$ message] = $ this-> getGoogleTranslation ($ message, $ language); 

Og jeg la til en parameter ($ Kraft = sant) for å tvinge rekreasjon av meldingsfilene:

$ this-> stdout ("Ingen nye i \" $ kategori \ "kategori ... Ingenting å lagre. \ n \ n", Console: : FG_GREEN); komme tilbake; 

Oversetter meldingsplanlegger

Testen fullført, jeg var spent på å oversette Message Planner til flere språk. Først legger vi til de nye språk oversettelsene til /console/config/i18n.php fil:

 __DIR__. DIRECTORY_SEPARATOR. '...'. DIRECTORY_SEPARATOR. '...'. DIRECTORY_SEPARATOR, // Root-katalog som inneholder meldingsoversettelser. 'messagePath' => __DIR__. DIRECTORY_SEPARATOR. '...'. DIRECTORY_SEPARATOR. 'meldinger', // array, kreves, liste over språkkoder som de utpakkede meldingene // skal oversettes til. For eksempel ['zh-CN', 'de']. 'languages' => ['ar', 'es', 'de', 'it', 'iw', 'ja', 'yi', 'zh-CN'], 

Igjen, hvis du trenger bredere språkstøtte eller har større mengder strenger å oversette, kan du bytte til Travis Tillotsons Google Translation Client og betalte API-tilgang.

Deretter la jeg til oversettelsesstrenger /frontend/views/layouts/main.php og /frontend/views/site/index.php for å demonstrere oversette hjemmesiden. Siden disse sidene ikke genereres av Yiis Gii-kodegenerator, hadde tekststrengene blitt etterlatt i vanlig HTML. Her er et eksempel på hvordan de ser ut som nå:

»

Slik ser hjemmesiden ut på engelsk:

Så løp jeg google_extract:

./ yii translate / google_extract /Users/Jeff/sites/mp/common/config/i18n.php 

Merk: Vær sikker på at når du gjør dette, er applikasjonsspråket satt til standardspråket ditt, f.eks. Engelsk. Denne innstillingen er i /common/config/main.php:

 dirname (dirname (__ DIR__)). '/ vendor', // tilgjengelige språk // 'ar', 'de', 'es', 'it', 'iw', 'ja', 'yi', 'zh-CN' language '=>' no ', // engelsk' komponenter '=> [ 

Jeg fant ut at det var nødvendig å løpe google_extract en gang for å lage den første meldingsfilmalen og en gang til for å starte anropene til Google Translate.

Da kan jeg endre språkinnstillingen i /common/config/main.php for å se hver oversettelse. Resultatene er ganske utrolig for noe som kan genereres så fort.

Her er hjemmesiden på kinesisk:

Her er hjemmesiden på arabisk:

Her er hjemmesiden på japansk:

Her er hjemmesiden på jiddisk:

Her er hjemmesiden på tysk:

Hva blir det neste?

Jeg håper du likte denne opplæringen. Det var morsomt å skrive noe som hadde en så stor innvirkning på den potensielle rekkevidden til min Meeting Planner-applikasjon. Hvis du vil lære mer om Meeting Planner, kan du se etter kommende opplæringsprogrammer i Bygg din oppstart med PHP-serien. Det er mange morsomme funksjoner som kommer opp.

Vær så snill å legge til dine spørsmål og kommentarer nedenfor; Jeg deltar vanligvis i diskusjonene. Du kan også nå meg på Twitter @ reifman eller email meg direkte.

Relaterte linker

  • Bygg oppstart med PHP: Lokalisering med I18n (Tuts +)
  • Programmering med Yii2: Komme i gang (Tuts +)
  • Introduksjon til Yii Framework (Tuts +)
  • Den Yii2 Definitive Guide: Internationalization