--=REKLAMA=--
To jest poradnik prezentujący sposób tworzenia paczek plików językowych dla Joomla! 1.6
Jako przykład posłuży nam przedrostek językowy fr-FR
Paczka tworzona jest z trzech plików. Paczki nazywamy w sposób następujący:
fr-FR_joomla_lang_full_1.6.0v1.zip
fr-FR_joomla_lang_site_1.6.0v1.zip, jeśli paczka zawiera pliki językowe części frontowej
1. Plik fr-FR.install.xml
<?xml version="1.0" encoding="UTF-8" ?> <extension type="package" version="1.6"> <name>French Language Pack</name> <packagename>fr-FR</packagename> <version>1.6</version> <url></url> <packager></packager> <packagerurl></packagerurl> <description>1.6 Joomla French Language Package</description> <files> <file type="language" client="site" id="fr-FR">site_fr-FR.zip</file> <file type="language" client="admin" id="fr-FR">admin_fr-FR.zip</file> </files> </extension>
2. Osobne paczki dla witryny i zaplecza (na przykład site i admin)
site_fr-FR.zip
admin_fr-FR.zip
Zawartość paczki na przykładzie części administracyjnej.
a) install.xml
<?xml version="1.0" encoding="utf-8" ?> <install version="1.6" client="administrator" type="language" method="upgrade"> <name>French (Fr)</name> <tag>fr-FR</tag> <version>1.6</version> <creationDate>2010-08-01</creationDate> <author>French translation team : Joomla!fr</author> <authorEmail>traduction@joomla.fr</authorEmail> <authorUrl>www.joomla.fr</authorUrl> <copyright>Copyright (C) 2005 - 2010 Joomla.fr et Open Source Matters. Tous droits réservés</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <description>French language pack for Joomla! 1.6</description> <files> <filename>index.html</filename> <filename>install.xml</filename> '''//Mandatory! This file lets uninstall a language.''' <filename>fr-FR.com_admin.ini</filename> <filename>fr-FR.com_admin.sys.ini</filename> <filename> .....ini</filename> [...] <filename>fr-FR.ini</filename> <filename file="meta">fr-FR.xml</filename> <filename>fr-FR.localise.php</filename> // in the site pack </files> <media destination="fr-FR"> //if one needs to add a specific calendar <filename>index.html</filename> <filename>js/index.html</filename> <filename>js/calendar-setup.js</filename> <filename>js/calendar.js</filename> </media> </install>
b. Uwaga! Nowe formatowanie w plikach .ini Cudzysłów należy zastąpić poprzez "_QQ_" lub "
c. fr-FR.xml
<?xml version="1.0" encoding="utf-8"?> <metafile version="1.6" client="administrator" method="upgrade" > <tag>fr-FR</tag> <name>French (FR)</name> <description>French administrator language for Joomla 1.6</description> <version>1.6</version> <creationDate>2010-08-01</creationDate> <author>French translation team : Joomla!fr</author> <authorEmail>traduction@joomla.fr</authorEmail> <authorUrl>www.joomla.fr</authorUrl> <copyright>Copyright (C) 2005 - 2010 Open Source Matters & Joomla.fr. All rights reserved.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <metadata> <name>French (FR)</name> <tag>fr-FR</tag> <rtl>0</rtl> </metadata> </params> </metafile>
d. fr-FR.localise.php (znajdujący się w paczce ze stroną)
Kilka słów wyjaśnienia:
Plik zastępuje fr-FR.ignore.php i może być dostosowywany w zależności od języka
Przykład podstawowego pliku fr-FR.localise.php (gdzie nie jest zaimplementowana transliteracja)
<?php /** * @version $Id: fr-FR.localise.php 15628 2010-03-27 05:20:29Z infograf768 $ * @copyright Copyright (C) 2005 - 2010 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ /** * fr-FR localise class * * @package Joomla.Site * @since 1.6 */ abstract class fr_FRLocalise { //// !!!! NOTE the use of fr_FR for the class !!!// do the same for your language prefix. /** * Returns the potential suffixes for a specific number of items * * @param int $count The number of items. * @return array An array of potential suffixes. * @since 1.6 */ public static function getPluralSuffixes($count) { if ($count == 0) { $return = array('0'); } elseif($count == 1) { $return = array('1'); } else { $return = array('MORE'); } return $return; } /** * Returns the ignored search words * * @return array An array of ignored search words. * @since 1.6 */ public static function getIgnoredSearchWords() { $search_ignore = array(); $search_ignore[] = "et"; $search_ignore[] = "si"; $search_ignore[] = "ou"; return $search_ignore; } /** * Returns the lower length limit of search words * * @return integer The lower length limit of search words. * @since 1.6 */ public static function getLowerLimitSearchWord() { return 3; } /** * Returns the upper length limit of search words * * @return integer The upper length limit of search words. * @since 1.6 */ public static function getUpperLimitSearchWord() { return 20; } /** * Returns the number of chars to display when searching * * @return integer The number of chars to display when searching. * @since 1.6 */ public static function getSearchDisplayedCharactersNumber() { return 200; } }
Przykład funkcji dodawanej, gdy własna transliteracja jest pożądana
/** * This method processes a string and replaces all accented UTF-8 characters by unaccented * ASCII-7 "equivalents" * * @param string $string The string to transliterate * @return string The transliteration of the string * @since 1.6 */ public static function transliterate($string) { $str = JString::strtolower($string); //Specific language transliteration. //This one is for latin 1, latin supplement , extended A, Cyrillic, Greek $glyph_array = array( 'a' => 'à,á,â,ã,ä,å,ā,ă,ą,ḁ,α,ά', 'ae' => 'æ', 'b' => 'β,б', 'c' => 'ç,ć,ĉ,ċ,č,ч,ћ,ц', 'ch' => 'ч', 'd' => 'ď,đ,Ð,д,ђ,δ,ð', 'dz' => 'џ', 'e' => 'è,é,ê,ë,ē,ĕ,ė,ę,ě,э,ε,έ', 'f' => 'ƒ,ф', 'g' => 'ğ,ĝ,ğ,ġ,ģ,г,γ', 'h' => 'ĥ,ħ,Ħ,х', 'i' => 'ì,í,î,ï,ı,ĩ,ī,ĭ,į,и,й,ъ,ы,ь,η,ή', 'ij' => 'ij', 'j' => 'ĵ', 'ja' => 'я', 'ju' => 'яю', 'k' => 'ķ,ĸ,κ', 'l' => 'ĺ,ļ,ľ,ŀ,ł,л,λ', 'lj' => 'љ', 'm' => 'μ', 'n' => 'ñ,ņ,ň,ʼn,ŋ,н,ν', 'nj' => 'њ', 'o' => 'ò,ó,ô,õ,ø,ō,ŏ,ő,ο,ό,ω,ώ', 'oe' => 'œ,ö', 'p' => 'п,π', 'ph' => 'φ', 'ps' => 'ψ', 'r' => 'ŕ,ŗ,ř,р,ρ,σ,ς', 's' => 'ş,ś,ŝ,ş,š,с', 'ss' => 'ß,ſ', 'sh' => 'ш', 'shch' => 'щ', 't' => 'ţ,ť,ŧ,τ', 'th' => 'θ', 'u' => 'ù,ú,û,ü,ũ,ū,ŭ,ů,ű,ų,у', 'v' => 'в', 'w' => 'ŵ', 'x' => 'χ,ξ', 'y' => 'ý,þ,ÿ,ŷ', 'z' => 'ź,ż,ž,з,ж,ζ' ); foreach( $glyph_array as $letter => $glyphs ) { $glyphs = explode( ',', $glyphs ); $str = str_replace( $glyphs, $letter, $str ); } return $str; }
Poniżej mamy przykład funkcji, która dodana do pliku fr-FR.localise.php pozwoli na implementację własnego kalendarza w języku perskim ( fa-IR)
/** * fa-IR Date class * * @package Joomla.Site * @since 1.6 */ jimport('joomla.utilities.date'); class fa_IRDate extends JDate { const DAY_NUMBER = "\x027\x03"; const DAY_NUMBER2 = "\x030\x03"; const DAY_YEAR = "\x032\x03"; const MONTH_ABBR = "\x033\x03"; const MONTH_NAME = "\x034\x03"; const MONTH_NUMBER = "\x035\x03"; const MONTH_NUMBER2 = "\x036\x03"; const MONTH_LENGTH = "\x037\x03"; const YEAR_ABBR = "\x040\x03"; const YEAR_NAME = "\x041\x03"; const AM_LOWER = "\x042\x03"; const AM_UPPER = "\x043\x03"; const PERSIAN_EPOCH = 1948320.5; protected static $month_names = array("فروردين","ارديبهشت","خرداد","تیر","مرداد","شهریور","مهر","آبان","آذر","دی","بهمن","اسفند"); /** * Gets the date as a formatted string. * * @param string The date format specification string (see {@link PHP_MANUAL#date}) * @param boolean True to return the date string in the local time zone, false to return it in GMT. * @return string The date string in the french republican calendar (see @link{http://en.wikipedia.org/wiki/French_Republican_Calendar}). * @since 1.6 */ public function calendar($format, $local = false) { // Do string replacements for date format options that can be translated. $format = preg_replace('/(^|[^\\\])d/', "\\1".self::DAY_NUMBER2, $format); $format = preg_replace('/(^|[^\\\])j/', "\\1".self::DAY_NUMBER, $format); $format = preg_replace('/(^|[^\\\])z/', "\\1".self::DAY_YEAR, $format); $format = preg_replace('/(^|[^\\\])M/', "\\1".self::MONTH_ABBR, $format); $format = preg_replace('/(^|[^\\\])F/', "\\1".self::MONTH_NAME, $format); $format = preg_replace('/(^|[^\\\])n/', "\\1".self::MONTH_NUMBER, $format); $format = preg_replace('/(^|[^\\\])m/', "\\1".self::MONTH_NUMBER2, $format); $format = preg_replace('/(^|[^\\\])t/', "\\1".self::MONTH_LENGTH, $format); $format = preg_replace('/(^|[^\\\])y/', "\\1".self::YEAR_ABBR, $format); $format = preg_replace('/(^|[^\\\])Y/', "\\1".self::YEAR_NAME, $format); $format = preg_replace('/(^|[^\\\])a/', "\\1".self::AM_LOWER, $format); $format = preg_replace('/(^|[^\\\])A/', "\\1".self::AM_UPPER, $format); // Format the date. $return = parent::calendar($format, $local); $jd = gregoriantojd($this->month, $this->day, $this->year); $jalaliDate = self::jd_to_persian($jd); $m = $jalaliDate['mon']; $d = $jalaliDate['day']; $y = $jalaliDate['year']; // Manually modify the strings in the formated time. if (strpos($return, self::DAY_NUMBER) !== false) { $return = str_replace(self::DAY_NUMBER, $d , $return); } if (strpos($return, self::DAY_NUMBER2) !== false) { $return = str_replace(self::DAY_NUMBER2, sprintf("%02d",$d), $return); } if (strpos($return, self::DAY_YEAR) !== false) { $return = str_replace(self::DAY_YEAR, $jd - self::persian_to_jd(1,1,$y)+1, $return); } if (strpos($return, self::MONTH_ABBR) !== false) { $return = str_replace(self::MONTH_ABBR, self::$month_names[$m-1] , $return); } if (strpos($return, self::MONTH_NAME) !== false) { $return = str_replace(self::MONTH_NAME, self::$month_names[$m-1] , $return); } if (strpos($return, self::MONTH_NUMBER) !== false) { $return = str_replace(self::MONTH_NUMBER, $m , $return); } if (strpos($return, self::MONTH_NUMBER2) !== false) { $return = str_replace(self::MONTH_NUMBER2, sprintf("%02d", $m) , $return); } if (strpos($return, self::MONTH_LENGTH) !== false) { $return = str_replace(self::MONTH_LENGTH, $m < 7 ? 31 : $m < 12 ? 30 : self::leap_persian($y) ? 30 : 29 , $return); } if (strpos($return, self::YEAR_ABBR) !== false) { $return = str_replace(self::YEAR_ABBR, sprintf("%02d",$y % 100), $return); } if (strpos($return, self::YEAR_NAME) !== false) { $return = str_replace(self::YEAR_NAME, $y, $return); } if (strpos($return, self::AM_LOWER) !== false) { $return = str_replace(self::AM_LOWER, $this->format('a',$local)=='pm' ? 'ب ظ' : 'ق ظ', $return); } if (strpos($return, self::AM_UPPER) !== false) { $return = str_replace(self::AM_UPPER, $this->format('a',$local)=='pm' ? 'ب ظ' : 'ق ظ', $return); } return $return; } public static function jd_to_persian($jd) { //var $year, $month, $day, $depoch, $cycle, $cyear, $ycycle, // $aux1, $aux2, $yday; $jd = floor($jd) + 0.5; $depoch = $jd - self::persian_to_jd(1, 1, 475); $cycle = floor($depoch / 1029983); $cyear = $depoch % 1029983; if ($cyear == 1029982) { $ycycle = 2820; } else { $aux1 = floor($cyear / 366); $aux2 = $cyear % 366; $ycycle = floor(((2134 * $aux1) + (2816 * $aux2) + 2815) / 1028522) + $aux1 + 1; } $year = $ycycle + (2820 * $cycle) + 474; if ($year <= 0) { $year--; } $yday = ($jd - self::persian_to_jd(1, 1, $year)) + 1; $month = ($yday <= 186) ? ceil($yday / 31) : ceil(($yday - 6) / 30); $day = ($jd - self::persian_to_jd($month, 1, $year)) + 1; return array('year'=>$year, 'mon'=>$month,'day'=> $day); } public static function persian_to_jd($month, $day, $year) { //var $epbase, $epyear; $epbase = $year - (($year >= 0) ? 474 : 473); $epyear = 474 + $epbase % 2820; return $day + (($month <= 7) ? (($month - 1) * 31) : ((($month - 1) * 30) + 6) ) + floor((($epyear * 682) - 110) / 2816) + ($epyear - 1) * 365 + floor($epbase / 2820) * 1029983 + self::PERSIAN_EPOCH; } public static function leap_persian($year) { return (((((($year - (($year > 0) ? 474 : 473)) % 2820) + 474) + 38) * 682) % 2816) < 682; } }
Oczywiście, do paczki należy dodać właściwe pliki kalendarza.