Resource.class.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. require_once(GITPHP_BASEDIR . 'lib/php-gettext/streams.php');
  3. require_once(GITPHP_BASEDIR . 'lib/php-gettext/gettext.php');
  4. /**
  5. * Resource string manager class
  6. *
  7. * @author Christopher Han <xiphux@gmail.com>
  8. * @copyright Copyright (c) 2010 Christopher Han
  9. * @package GitPHP
  10. */
  11. class GitPHP_Resource
  12. {
  13. /**
  14. * Constant of the locale cookie in the user's browser
  15. *
  16. * @var string
  17. */
  18. const LocaleCookie = 'GitPHPLocale';
  19. /**
  20. * Locale cookie lifetime
  21. *
  22. * @var int
  23. */
  24. const LocaleCookieLifetime = 31536000; // 1 year
  25. /**
  26. * Stores the currently instantiated locale identifier
  27. *
  28. * @var string
  29. */
  30. protected $locale = '';
  31. /**
  32. * Stores the current locale reader
  33. *
  34. * @var gettext_reader
  35. */
  36. protected $localeReader;
  37. /**
  38. * Constructor
  39. *
  40. * @param string $locale locale to instantiate
  41. * @param boolean $cache true to cache strings
  42. */
  43. public function __construct($locale, $cache = true)
  44. {
  45. if (!(($locale == 'en_US') || ($locale == 'en'))) {
  46. if (!is_readable(GITPHP_LOCALEDIR . $locale . '/gitphp.mo'))
  47. throw new Exception('Invalid locale');
  48. $reader = new FileReader(GITPHP_LOCALEDIR . $locale . '/gitphp.mo');
  49. if (!$reader) {
  50. throw new Exception('Invalid locale');
  51. }
  52. $this->localeReader = new gettext_reader($reader, $cache);
  53. }
  54. $this->locale = $locale;
  55. }
  56. /**
  57. * Translate a string
  58. *
  59. * @param string $string string
  60. */
  61. public function translate($string)
  62. {
  63. if (!$this->localeReader)
  64. return $string;
  65. return $this->localeReader->translate($string);
  66. }
  67. /**
  68. * Translate a pluralized string
  69. *
  70. * @param string $singular singular form
  71. * @param string $plural plural form
  72. * @param int $count count
  73. */
  74. public function ngettext($singular, $plural, $count)
  75. {
  76. if (!$this->localeReader)
  77. return $count == 1 ? $singular : $plural;
  78. return $this->localeReader->ngettext($singular, $plural, $count);
  79. }
  80. /**
  81. * Gets the currently instantiated locale
  82. *
  83. * @return string locale identifier
  84. */
  85. public function GetLocale()
  86. {
  87. return $this->locale;
  88. }
  89. /**
  90. * Gets the currently instantiated primary locale
  91. *
  92. * @return string primary locale identifier
  93. */
  94. public function GetPrimaryLocale()
  95. {
  96. $locale = $this->locale;
  97. $underscore = strpos($locale, '_');
  98. if ($underscore !== false) {
  99. $locale = substr($locale, 0, $underscore);
  100. }
  101. return $locale;
  102. }
  103. /**
  104. * Gets the current instantiated locale's name
  105. *
  106. * @return string locale name
  107. */
  108. public function GetLocaleName()
  109. {
  110. if (!$this->localeReader)
  111. return 'English';
  112. $localeName = $this->localeReader->translate('English');
  113. if ($localeName == 'English') {
  114. // someone didn't translate the language name - don't mislabel it as english
  115. return '';
  116. }
  117. return $localeName;
  118. }
  119. /**
  120. * Gets the list of supported locales and their languages
  121. *
  122. * @param boolean $includeNames true to include native names of languages
  123. * @return string[] array of locales mapped to languages
  124. */
  125. public static function SupportedLocales($includeNames = true)
  126. {
  127. $locales = array();
  128. if ($includeNames)
  129. $locales['en_US'] = 'English';
  130. else
  131. $locales[] = 'en_US';
  132. if ($dh = opendir(GITPHP_LOCALEDIR)) {
  133. while (($file = readdir($dh)) !== false) {
  134. $fullPath = GITPHP_LOCALEDIR . '/' . $file;
  135. if ((strpos($file, '.') !== 0) && is_dir($fullPath) && is_file($fullPath . '/gitphp.mo')) {
  136. if ($includeNames) {
  137. $resource = new GitPHP_Resource($file, false);
  138. $locales[$file] = $resource->GetLocaleName();
  139. } else {
  140. $locales[] = $file;
  141. }
  142. }
  143. }
  144. }
  145. if ($includeNames)
  146. ksort($locales);
  147. return $locales;
  148. }
  149. /**
  150. * Given a list of preferred locales, try to find a matching supported locale
  151. *
  152. * @param string $httpAcceptLang HTTP Accept-Language string
  153. * @return string matching locale if found
  154. */
  155. public static function FindPreferredLocale($httpAcceptLang)
  156. {
  157. if (empty($httpAcceptLang))
  158. return '';
  159. $locales = explode(',', $httpAcceptLang);
  160. $localePref = array();
  161. foreach ($locales as $locale) {
  162. $quality = '1.0';
  163. $localeData = explode(';', trim($locale));
  164. if (count($localeData) > 1) {
  165. $q = trim($localeData[1]);
  166. if (substr($q, 0, 2) == 'q=') {
  167. $quality = substr($q, 2);
  168. }
  169. }
  170. $localePref[$quality][] = trim($localeData[0]);
  171. }
  172. krsort($localePref);
  173. $supportedLocales = GitPHP_Resource::SupportedLocales(false);
  174. foreach ($localePref as $quality => $qualityArray) {
  175. foreach ($qualityArray as $browserLocale) {
  176. $locale = str_replace('-', '_', $browserLocale);
  177. $loclen = strlen($locale);
  178. foreach ($supportedLocales as $lang) {
  179. /*
  180. * using strncasecmp with length of the preferred
  181. * locale means we can match both full
  182. * language + country preference specifications
  183. * (en_US) as well as just language specifications
  184. * (en)
  185. */
  186. if (strncasecmp($locale, $lang, $loclen) === 0) {
  187. return $lang;
  188. }
  189. }
  190. }
  191. }
  192. return '';
  193. }
  194. }