Trace: » i18n
Wielojęzyczność w cakephp
statycznie
tworzymy pliki: /app/locale/eng/LC_MESSAGES/deafult.po
msgid "new" msgstr "New"
/app/locale/pol/LC_MESSAGES/deafult.po
msgid "new" msgstr "Nowy"
/app/locale/*lang_code*/LC_MESSAGES/deafult.po
msgid "new" msgstr "Pojakiemus nowy:)"
czyli:
- msgid - to identyfikator taki sam wszedzie
- msgstr - to tekst w danym jezyku
kody języków
Kody jezykow mozna znalezc tutaj.
szblony (VIEW)
Jeżeli chcemy wyswietlic tylko:
<li>__('new')</li>
Jeżeli chcemy zwroci do funkcji:
<li><?php echo $html->link(__('new',true), array('action'=>'add')); ?></li>
Jezeli funkcja nie znajdzie danego msgid w danym jezyku zostanie wyświetlony przekazany msgid. (W naszym wypadku “new” z małej litery)
zmiana języka
Configure::write('Config.language', 'pol');
odmiana
Cakephp wspiera odmiane rzeczowników w liczbie mnogiej (1 jabłko, 2 jabłka, 5 jabłek).
VIEW
Wcelu przetłumaczenia wyrazu na jego poprawna forme w liczbie mnogiej uzywamy fukcji "__n". Funckja ta przyjmuje 3 wymagane parametry [’forma_liczby_pojedynczej’,’forma_liczb mnogiej’,liczba_elementow]. 4 paramtr okresla czy funkcja ma wyswietlic ciag znakow czy zwrocic.
W ponizszym przykladzie jako liczbe pojedyncza podajemy “1 apple” a jako mnoga “%s apples”, ilosc elementow, oraz true aby funckja zrwocila wynik a nie wyswietlila go. Nastepnie gdy liczba jest inna niz 1 w zwroconym ciagu zamieniamy %s na liczbe elementow funkcja sprintf.
for($i=0;$i<120;$i++)
{
echo sprintf( __n('1 apple','%s apples',$i,true), $i); ?></h3>
}
Aby wszystko działało dobrze porzeba nam jeszcze plik .po Ważna rzeczą jest aby pamiętać by w ‘Plural-Forms:’ podać odpowiednia regułę dla naszego języka
msgid "" msgstr "" "Project-Id-Version: CakePHP 1.2.x.x\n" "POT-Creation-Date: \n" "PO-Revision-Date: 2007-04-21 03:28-0600\n" "Last-Translator: Sławomir Wilusz <slawek (at) wilusz (dot) net>\n" "Language-Team: devayd.com\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "X-Poedit-Language: Polish\n" "X-Poedit-Country: POLAND\n" "X-Poedit-SourceCharset: utf-8\n" msgid "1 apple" msgid_plural "%s apples" msgstr[0] "1 jabłko" msgstr[1] "%s jabłka" msgstr[2] "%s jabłek"
w powyższym pliku możemy wyróżnić:
- msgid - identyfikator dla liczby pojedynczej (podajemy go jako 1 paramtre w funckji __n)
- msgid_plural - identyfikator dla liczby mnogiej (podajemy go jako 1 parametr w funckji __n)
- msgstr[0] - tlumaczenie dla liczby pojednczej
- msgstr[1] - tlumaczenie dla liczby mnogiej
- msgstr[2] - 2 tlumaczenie dla liczby mnogiej
To która wersja zostaje zwrocona okresla nam reguła Plural-Forms.
liczba mnoga
przez osoby
TODO ?
dynamicznie
Obsluga wielojezycznosci w cake 1.2 realizowana jest poprzez behaviour “Translate”.
Aby z niego korzystac nalezy najpierw stworzyc tabele, ktorych struktura zawarta jest w pliku APP/config/sql/i18n.sql
nastepenie w modelu dodajemy linijkę
var $actsAs = array('Translate'=>array('field1','field2'));
Pola field1 i field2 nie muszą mieć kolumna w tabeli modelu. Pola te trzymane są dynamicznie w tabelach językowych.
Aby edytować pola filed1 field2 w szablonie dodajemy porostu
echo $form->input("field1");
echo $form->input("field2");
Odczytywanie wykonuje sie następująco:
//odczyt rekordu o id 1 w jezyku polskim $this->MODELNAME->locale= "pol"; $data = $this->MODELNAME->read(null,1);
Jeśli nie podamy ręcznie locale modelu, zostanie ustawione locale automatycznie przez cake lub z sesji (Config.language)
Zapisywanie:
//zapis rekordu w jezyku polskim $this->MODELNAME->locale= "pol"; $this->MODELNAME->save($this->data);
jeżeli chcemy by rekordy językowe byly ze soba powiazna (np artykul o id 1 ma rozne wersje jezykowe) nalezy po dodaniu (add) wykonac nastepujace funkcje:
Dla wersji wcześniejszych niż 1.2.0.5875 pre-beta:
$this->ModelName = MODELNAME;
$langs = $this->Language->findAllByActive(1);
$i=0;
$row_id = $this->{$this->ModelName}->getLastInsertID();
foreach($langs as $lang)
{
if($this->Session->read('Config.language')!=$lang['Language']['code'])
{
$this->{$this->ModelName}->locale = $lang['Language']['code'];
foreach($this->{$this->ModelName}->actsAs['Translate'] as $field)
{
$i++;
$this->{$this->ModelName}->query("INSERT INTO `prefix__i18n_content` (`content`) VALUES ('') ");
$insertID = 'insertID'.$i;
$res = $this->{$this->ModelName}->query("SELECT LAST_INSERT_ID() AS $insertID");
$i18n_content_id = $res[0][0][$insertID];
$this->{$this->ModelName}->query("INSERT INTO `prefix__i18n` (`locale`,`model`,`row_id`,`i18n_content_id`,`field`) VALUES ('".$lang['Language']['code']."','".$this->ModelName."',$row_id,$i18n_content_id,'$field')");
}
}
}
Dla wersji 1.2.0.5875 pre-beta i poźniejszych:
$langs = $this->Language->findAllByActive(1);
$i=0;
$row_id = $this->{$this->modelClass}->getLastInsertID();
foreach($langs as $lang)
{
if($this->Session->read('Config.language')!=$lang['Language']['code'])
{
$this->{$this->modelClass}->locale = $lang['Language']['code'];
foreach($this->{$this->modelClass}->actsAs['Translate'] as $field)
{
$i++;
$this->{$this->modelClass}->query("INSERT INTO `prefix__i18n` (`locale`,`model`,`foreign_key`,`field`,`content`) VALUES ('".$lang['Language']['code']."','".$this->modelClass."','".$row_id."','".$field."','".$this->data[$lang['Language']['code']][$field]."')");
}
}
}
powyzszy kod dodaje puste wartosc dla wszytkich pozostalych jezykow. Jezyki dla tego przykladu sa trzymane w tabeli languages i jest do nich zrobiony osobny model. Prefix jest reczenie ustawiony na “prefix”!
poEdit
Klika uwag które mogą zaoszczędzić Wam czasu podczas pracy z poEdit.
Program poEdit można ściągnąć tutaj
- File→Preferences→Pareser → wybrać np PHP → edit → dopisac roszerzenie “*.ctp;”
- File→New Catalogue (przykładowe dane dla projektu z polskim jezykiem)
- Project Info
- Project name: nazwa prjketu
- Team : nazaw zespolu tlumaczacego
- Team email - email zespolu tlumaczacego
- Language - Polish
- Country - Poland
- Charset - utf-8
- Source code - utf-8
- Plural Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10⇐4 && (n%100<10 || n%100>=20) ? 1 : 2;
- Paths
- Base path - /sciezka_do_cake/app/views (jesli tylko szablony)
- Paths - “comments” (bedzie szukalo w katalogu comments - sciezki sa wzgeldne wobec basepath)
- Paths - “../controllers” - wzgledne sciezki
- Keywords
- _ (standardowa funkcja ale jak podajemy keywords trzeba? ja podac od nowa)
- __ ( funkcja uzywana w cake’u)
- __n (funkcja w cake dla plurals)
- pozostałe których używaliśmy
Po takim skonfigurowaniu poEdit powinnie on wyswietlic komunikat ze rozszerzenie *.ctp jest nie znane i sprobuje uzyc *.c a nastepnie przeparsowac pliki i wyswietlic znalezione ciagi do przetlumaczenia.
Jeśli dodamy na końcu polecenia programu przetwarzającego (w preferencjach) –language=php, nie wyświetli on powyższego komunikatu.
UWAGA - poEdit nie rozpoznaje stringow objetych pojedynczymi cudzysłowami ' dlatego trzeba używać zawsze " ( __("tekst") zamiast __('tekst') )
UWAGA - cake najpierw sprawdza czy znajduje sie plik .mo i czasami zdarza sie ze choc w pliku .po sa juz nowe dane to cake ich nie widzi i najlatwiej wtedy usunac plik .mo sprawdzic czy jest ok i wygenerowac poprzez poEdit nowy plik .mo jesli jest ok (plik .mo generuje sie automatycznie podczas zapisu )