Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [Klasa] Babel 1.3.0, i18n z plików *.mo/*.po
Bastion
post 22.02.2006, 20:35:47
Post #1





Grupa: Zarejestrowani
Postów: 505
Pomógł: 0
Dołączył: 8.01.2005

Ostrzeżenie: (0%)
-----


  1. <?php
  2.  
  3. if (!defined('BABEL_DEBUG'))
  4. {
  5. define('BABEL_DEBUG', 1);
  6. }
  7.  
  8. function _p($string)
  9. {
  10. global ${BABEL};
  11. print (isset(${BABEL})) ? ${BABEL}->translate($string) : $string;
  12. }
  13.  
  14. function _r($string)
  15. {
  16. global ${BABEL};
  17. return (isset(${BABEL})) ? ${BABEL}->translate($string) : $string;
  18. }
  19.  
  20. class Babel
  21. {
  22. const className = 'Babel';
  23. const classVersion = '1.0.0';
  24. const classRelase = 1140634709;
  25. const classVendor = 'Vertis';
  26. const classVendorURL = 'www.vertis.com.pl';
  27.  
  28. var $errno = 0;
  29. var $errstr = null;
  30. var $error = false;
  31. var $mo_dir = 'i18n';
  32.  
  33. private $translations = array();
  34. private $translations_size = 0;
  35.  
  36. private $mo_file = null;
  37. private $mo_position = 0;
  38. private $mo_length = 0;
  39. private $mo_order = 'V';
  40. private $mo_info = null;
  41.  
  42. public function mo($filename)
  43. {
  44. $this->errno = 0;
  45. $this->error = false;
  46. $this->mo_position = 0;
  47.  
  48. $path = $this->mo_dir.DIRECTORY_SEPARATOR.$filename;
  49.  
  50. if (!file_exists($path))
  51. {
  52. $this->_err(1, "class5.Babel : File $path not found");
  53. return false;
  54. }
  55.  
  56. if (!is_readable($path))
  57. {
  58. $this->_err(2, "class5.Babel : File $path is not readable");
  59. return false;
  60. }
  61.  
  62. $this->mo_length = filesize($path);
  63. $handle = fopen($path, 'rb');
  64. $this->mo_file = fread($handle, $this->mo_length);
  65. fclose($handle);
  66.  
  67. if ($this->_fix_endian())
  68. {
  69. $this->mo_info = unpack($this->mo_order.'4',$this->_read(16));
  70. $this->_translate();
  71. return true;
  72. }
  73.  
  74. $this->_err(3, "class5.Babel : $path is not *.mo file");
  75. return false;
  76. }
  77.  
  78. public function translate($string)
  79. {
  80. if ($this->translations_size == 0)
  81. {
  82. return $string;
  83. }
  84.  
  85. if (array_key_exists($string, $this->translations))
  86. {
  87. return $this->translations[$string];
  88. } else
  89. {
  90. return $string;
  91. }
  92. }
  93.  
  94. private function _translate()
  95. {
  96. $count = $this->mo_info[2] * 2;
  97. $this->_seek($this->mo_info[3]);
  98. $this->mo_originals = unpack($this->mo_order.$count, $this->_read(* $count));
  99. $this->_seek($this->mo_info[4]);
  100. $this->mo_translated = unpack($this->mo_order.$count, $this->_read(* $count));
  101. for ($i = 0; $i < $this->mo_info[2]; $i++)
  102. {
  103. $j = $i*+ 1;
  104. $this->_seek($this->mo_originals[$j+1]);
  105. $original = $this->_read($this->mo_originals[$j]);
  106. $this->_seek($this->mo_translated[$j+1]);
  107. $translation = $this->_read($this->mo_translated[$j]);
  108. $this->translations[$original] = $translation;
  109. }
  110. $this->translations_size = count($this->translations);
  111. }
  112.  
  113. private function _fix_endian()
  114. {
  115. $val01 = (int)-569244523;
  116. $val02 = (int)-1794895138;
  117. $unpacked = unpack($this->mo_order, $this->_read(4));
  118. if ($unpacked[1] == $val01)
  119. {
  120. $this->mo_order = 'N';
  121. return true;
  122. }
  123. if ($unpacked[1] == $val02)
  124. {
  125. $this->mo_order = 'V';
  126. return true;
  127. }
  128. return false;
  129. }
  130.  
  131. private function _read($bytes)
  132. {
  133. $data = substr($this->mo_file, $this->mo_position, $bytes);
  134. $this->mo_position += $bytes;
  135. if ($this->mo_length < $this->mo_position)
  136. {
  137. $this->mo_position = $this->mo_length;
  138. }
  139. return $data;
  140. }
  141.  
  142. private function _seek($pos)
  143. {
  144. $this->mo_position = $pos;
  145. if ($this->mo_length < $this->mo_position)
  146. {
  147. $this->mo_position = $this->mo_length;
  148. }
  149. return $this->mo_position;
  150. }
  151.  
  152. private function _err($errno, $errstr)
  153. {
  154. $this->errno = $errno;
  155. $this->errstr = $errstr;
  156. if (BABEL_DEBUG == 1)
  157. {
  158. print 'WARN! '.$errstr.'<br />';
  159. }
  160. }
  161.  
  162. public function __construct()
  163. {
  164. global $_inited_modules;
  165.  
  166. if (empty($_inited_modules[self::className]))
  167. {
  168. $_inited_modules[self::className] = array('version' => self::classVersion,
  169. 'relase' => self::classRelase,
  170. 'vendor' => self::classVendor,
  171. 'vendorURL' => self::classVendorURL,
  172. 'copies' => 1);
  173. } else
  174. {
  175. $_inited_modules[self::className]['copies']++;
  176. }
  177. }
  178. }
  179.  
  180. ?>

Klasa PHP5

  1. <?php
  2.  
  3. require_once('libs/class5.babel.php');
  4.  
  5. $lang = new Babel;
  6. $lang -> mo_dir = 'i18n';
  7. $lang -> mo('pl.mo');
  8. // $lang -> mo('pl2.mo'); mozna dolaczyc nastepny
  9.  
  10. print $lang->translate('Welcome on EclipseX').'<br />'; // odwolanie obiektowe
  11.  
  12. define('BABEL', 'lang');
  13.  
  14. _p('Welcome on EclipseX');
  15. print '<br />';
  16. print _r('Please login')
  17.  
  18. ?>

Przyklad zastosowania

Kod
Witamy w EclipseX
Witamy w EclipseX
Please login

Wynik


Pliki mo/po : http://www.vertis.com.pl/i18n/
Klasa do pobrania : http://www.vertis.com.pl/

-------- added

aha, w sposob banalny mozna wygenerowac plik *.mo z pliku php, uzywamy w skrypcie _r() i _p() potem :
xgettext -L php php.php -o lang.po --keyword=_p --keyword=_r

i wuala smile.gif

Ten post edytował Bastion 27.06.2006, 14:54:34


--------------------
Go to the top of the page
+Quote Post
Fuzja
post 22.02.2006, 20:50:52
Post #2





Grupa: Zarejestrowani
Postów: 216
Pomógł: 0
Dołączył: 6.11.2005

Ostrzeżenie: (0%)
-----


btw : nudzi Ci się w domu ? smile.gif
Go to the top of the page
+Quote Post
Bastion
post 22.02.2006, 20:53:59
Post #3





Grupa: Zarejestrowani
Postów: 505
Pomógł: 0
Dołączył: 8.01.2005

Ostrzeżenie: (0%)
-----


Nie smile.gif kompletuje mechanizmy skladajace sie na EclipseX aarambo.gif


--------------------
Go to the top of the page
+Quote Post
Neotion
post 22.02.2006, 21:10:46
Post #4





Grupa: Zarejestrowani
Postów: 67
Pomógł: 0
Dołączył: 13.09.2004

Ostrzeżenie: (0%)
-----


Mam klasę działającą na identycznej zasadzie w moim FW smile.gif

Tylko u mnie plik z tłumaczeniem wygląda tak:

Kod
cośtamcośtam<-ISNOW->tłumacznenie<-END->


I mam jescze obsługę czegoś takiego jak wielokrotności tzn dobieranie odpowiedniego wyrazu do liczby (1 znak, 50 znaków).

Zastanawiam się jak rozwiązać problem wielu języków: w obecnym systemie jest jeden język referencyjny (np angielkski) i pliki z tłumaczeniami do niego, co powoduje że w każdym pliku musimy mieć tą samą część referencyjną. Problem tkwi w strukturze pliku i jego późniejszym zastosowaniu, po prostu nie wiem jak optymalnie to zrobić smile.gif

Ten post edytował Neotion 22.02.2006, 21:11:21


--------------------
current: nexcite cms (0.2.5) running on top of netsource framework (0.5.3)

workbench: nsapi | php 5.1.2 | mysql 5.0.18 | phpmyadmin 2.9 rc1 | zend studio 5.2.0 | apache/2.2.0 (linux/suse)
Go to the top of the page
+Quote Post
Bastion
post 22.02.2006, 21:14:30
Post #5





Grupa: Zarejestrowani
Postów: 505
Pomógł: 0
Dołączył: 8.01.2005

Ostrzeżenie: (0%)
-----


Neotion - na tym polega zaleta plikow gettexta mo. W skrypcie piszesz referencyjnym, na koniec generujesz szybko plik po, tlumaczysz, generujesz binarny plik jezykowy mo i funga


--------------------
Go to the top of the page
+Quote Post
NuLL
post 22.02.2006, 21:38:33
Post #6





Grupa: Zarejestrowani
Postów: 2 262
Pomógł: 21
Dołączył: 3.05.2004
Skąd: Sopot, Krakow, W-wa

Ostrzeżenie: (0%)
-----


OT: A jak mozna takie pliki generowac questionmark.gif Bo o tym ze .mo sa szybkie to wiem smile.gif

Bastion: No Linux aviable tongue.gif


--------------------
Javascript, Coffeescript, Node.js, Mongo, CouchDb, chmury, workery & inne bajery - zycie jest zbyt krotkie aby miec nudna prace :)
Go to the top of the page
+Quote Post
Bastion
post 24.02.2006, 09:53:57
Post #7





Grupa: Zarejestrowani
Postów: 505
Pomógł: 0
Dołączył: 8.01.2005

Ostrzeżenie: (0%)
-----


najpierw z pliku php tworzysz plik *.po :

xgettext plik.php -L php -o plik.po --keyword=_r --keyword=_p

i wszystkie stringi w funkcjach _p() i _r() wrzuci do plik.po. Edytujesz go dowolnym programem , lub specjalnym do tlumaczenia i na koniec wydajesz polecenie :

msgfmt -o plik.mo plik.po

---- ciachu ciachu

Babel 1.1.0
# pobieranie meta tagów pliku tłumaczeń
# możliwość przekodowania tłumaczeń na inną stronę kodową

  1. <?php
  2.  
  3. require_once('../libs/class5.babel.php');
  4.  
  5. $lang = new Babel;
  6. $lang -> set_charset('UTF-8');
  7. $lang -> mo_dir = 'i18n';
  8. $lang -> mo('pl_PL.mo');
  9.  
  10. define('BABEL', 'lang');
  11.  
  12. print 'Metainfo : ';
  13. print '<pre>';
  14. print_r($lang->get_mo_meta());
  15. print '</pre>';
  16.  
  17. print 'Plik .mo zakodowany w : '.$lang->get_mo_charset();
  18. print '<br />';
  19. print _r('Introduction to class5.Babel');
  20.  
  21. ?>


Demo : http://www.vertis.com.pl/demo/babel/examples/example02.php
Inne pliczki : http://www.vertis.com.pl/demo/babel/
Pobrać można z : http://www.vertis.com.pl/


--------------------
Go to the top of the page
+Quote Post
Vomit
post 10.03.2006, 15:47:23
Post #8





Grupa: Zarejestrowani
Postów: 122
Pomógł: 0
Dołączył: 23.01.2006

Ostrzeżenie: (0%)
-----


Przejrzałem kod, ale do czego on słuzy? Obsługa jezyków w stylu i18n czy jak? Do czego te pliki mo?
Go to the top of the page
+Quote Post
Bastion
post 27.06.2006, 14:53:48
Post #9





Grupa: Zarejestrowani
Postów: 505
Pomógł: 0
Dołączył: 8.01.2005

Ostrzeżenie: (0%)
-----


Klasa w wersji 1.3.0 wydana smile.gif

Teraz radzi sobie tekze z gettextowymi odmianami rzeczownikow, dowolna kolejnoscia parametrow
oraz komentarzami w plikach *.po

  1. <?php
  2.  
  3. define('CLASS5_CHARSET', 'iso-8859-2');
  4.  
  5. require_once('../libs/class5.babel.php');
  6.  
  7. $lang = new Babel('lang');
  8. $lang -> mo_dir = 'i18n';
  9.  
  10. // --------------------------------------------------------------------------
  11. $lang -> mo('en_US_2.mo');
  12. _p('Do you want to move file %1 to directory %2?', 'Babel.tgz', 'Respsitory'); print '<br />';
  13. _p('Edit'); print '<br />';
  14. _p('Deleted %n file.', 1);  print '<br />';
  15. _p('Deleted %n file.', 22); print '<br />';
  16. _p('Deleted %n file.', 50); print '<br />';
  17. // --------------------------------------------------------------------------
  18. print '<hr />';
  19. // --------------------------------------------------------------------------
  20. $lang -> mo('pl_PL_2.mo');
  21. _p('Do you want to move file %1 to directory %2?', 'Babel.tgz', 'Respsitory'); print '<br />';
  22. _p('Edit'); print '<br />';
  23. _p('Deleted %n file.', 1);  print '<br />';
  24. _p('Deleted %n file.', 22); print '<br />';
  25. _p('Deleted %n file.', 50); print '<br />';
  26.  
  27. ?>


Wynik : http://www.vertis.com.pl/demo/babel/examples/example05.php
Wykorzyatny plik PO : http://www.vertis.com.pl/demo/babel/exampl...text/pl_PL_2.po

Pobranko tradycyjnie : http://dl.vertis.com.pl/


--------------------
Go to the top of the page
+Quote Post
elnino.pl
post 27.06.2006, 21:10:52
Post #10





Grupa: Zarejestrowani
Postów: 125
Pomógł: 0
Dołączył: 17.06.2006

Ostrzeżenie: (0%)
-----


Świetna sprawa - gratuluję wiedzy i determinacji autorowi, ale jak to "przyjemnie" wpleść w smarty?


--------------------
Go to the top of the page
+Quote Post
DeyV
post 27.06.2006, 21:44:49
Post #11





Grupa: Zarząd
Postów: 2 277
Pomógł: 6
Dołączył: 27.12.2002
Skąd: Wołów/Wrocław




Co prawda Babel nie testowałem, ale - translacje wpleść do smarty bardzo łatwo:
  1. <?php
  2. $Smarty->register_block("t", "do_translation");
  3.  
  4. /**
  5.  * funckcja dla {t} dla smarty
  6.  */
  7. function do_translation ($aParams, $sContent )
  8. {
  9. return _r( $sContent , $aParams['param1'] );
  10. }
  11. ?>

a w smarty
  1. {t}tekst do tłumaczenia{/t}
  2. {t param1=22}Deleted %n file.{/t}

Pisane cześciowo z palca, więc mogą być jakieś błędy.

ps. Niestety, nie wiem, jak z takiego pliku smarty wygenerować plik .po


--------------------
"Niezależnie od tego, jakie masz osiągnięcia, ktoś Ci pomaga..."
Go to the top of the page
+Quote Post
elnino.pl
post 30.06.2006, 17:05:20
Post #12





Grupa: Zarejestrowani
Postów: 125
Pomógł: 0
Dołączył: 17.06.2006

Ostrzeżenie: (0%)
-----


@DeyV: Dzięki bardzo, gdy tylko przywrócę synchronizację FTP pod Eclipse spróbuję.

[EDIT]

Udało mi się odnaleźć plugin pobierający ze znaczników smartów wyrażenia ( klik ). Skrypt ten generuje pliki postaci:
Kod
/* ../tpl/BlueEye/footer.tpl */
gettext("Kategorie produktów");

/* ../tpl/BlueEye/footer.tpl */
gettext("Bestsellery %1");


Te pliki poleceniem xgettext pięknie tłumaczę do plików *.po - niestety na serwerze nie mam xgettext i generalnie mogą z tym być problemy - czy tłumaczenia w/w kodu do plików *.po mogę dokonać w inny sposób? Nie mogę odnaleźć odpowiedniej klasy php/skryptu. Jest PHPgettext, ale na otwartej licencji - potrzebuję czegoś na GNU L. Czy PHPowy gettext mógłby w jakiś sposób wygenerować pliki *.po?

Ten post edytował elnino.pl 30.06.2006, 17:06:00


--------------------
Go to the top of the page
+Quote Post
Bastion
post 2.07.2006, 09:27:03
Post #13





Grupa: Zarejestrowani
Postów: 505
Pomógł: 0
Dołączył: 8.01.2005

Ostrzeżenie: (0%)
-----


Soft wspomagający edycję mo <=> po :

Windows/Linux : http://www.poedit.org/
Linux: http://kbabel.kde.org/


--------------------
Go to the top of the page
+Quote Post
elnino.pl
post 2.07.2006, 12:19:08
Post #14





Grupa: Zarejestrowani
Postów: 125
Pomógł: 0
Dołączył: 17.06.2006

Ostrzeżenie: (0%)
-----


Cytat(Bastion @ 2.07.2006, 10:27 ) *
Soft wspomagający edycję mo <=> po :

Windows/Linux : http://www.poedit.org/
Linux: http://kbabel.kde.org/

Dzięki, ale chciałbym w panelu administracyjnym aplikacji dodać moduł pobierający z szablonu smarty elementy do tłumaczenia (ten skrypt już mam) i automatycznie generujący pliki *.po i *.mo. Problem w tym, że z pliku, którego treść wrzuciłem wyżej nie mogę automatycznie stworzyć pliku *.po... (robi to program xgettext, ale nie mam go na serwerze)

Ten post edytował elnino.pl 2.07.2006, 12:20:19


--------------------
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 25.04.2024 - 15:44