Language.php 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. <?php
  2. namespace Tools\Utility;
  3. class Language {
  4. public static function parseLanguageList($languageList = null) {
  5. if ($languageList === null) {
  6. if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
  7. return array();
  8. }
  9. $languageList = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
  10. }
  11. $languages = array();
  12. $languageRanges = explode(',', trim($languageList));
  13. foreach ($languageRanges as $languageRange) {
  14. if (preg_match('/(\*|[a-zA-Z0-9]{1,8}(?:-[a-zA-Z0-9]{1,8})*)(?:\s*;\s*q\s*=\s*(0(?:\.\d{0,3})|1(?:\.0{0,3})))?/', trim($languageRange), $match)) {
  15. if (!isset($match[2])) {
  16. $match[2] = '1.0';
  17. } else {
  18. $match[2] = (string)floatval($match[2]);
  19. }
  20. if (!isset($languages[$match[2]])) {
  21. if ($match[2] === '1') {
  22. $match[2] = '1.0';
  23. }
  24. $languages[$match[2]] = array();
  25. }
  26. $languages[$match[2]][] = strtolower($match[1]);
  27. }
  28. }
  29. krsort($languages);
  30. return $languages;
  31. }
  32. /**
  33. * Compares two parsed arrays of language tags and find the matches
  34. *
  35. * @return array
  36. */
  37. public static function findMatches(array $accepted, array $available = []) {
  38. $matches = array();
  39. if (!$available) {
  40. $available = static::parseLanguageList();
  41. }
  42. foreach ($accepted as $acceptedValue) {
  43. foreach ($available as $availableQuality => $availableValues) {
  44. $availableQuality = (float)$availableQuality;
  45. if ($availableQuality === 0.0) {
  46. continue;
  47. }
  48. foreach ($availableValues as $availableValue) {
  49. $matchingGrade = static::_matchLanguage($acceptedValue, $availableValue);
  50. if ($matchingGrade > 0) {
  51. $q = (string)($availableQuality * $matchingGrade);
  52. if ($q === '1') {
  53. $q = '1.0';
  54. }
  55. if (!isset($matches[$q])) {
  56. $matches[$q] = array();
  57. }
  58. if (!in_array($availableValue, $matches[$q])) {
  59. $matches[$q][] = $availableValue;
  60. }
  61. }
  62. }
  63. }
  64. }
  65. krsort($matches);
  66. return $matches;
  67. }
  68. /**
  69. * Compare two language tags and distinguish the degree of matching
  70. *
  71. * @return float
  72. */
  73. protected static function _matchLanguage($a, $b) {
  74. $a = explode('-', $a);
  75. $b = explode('-', $b);
  76. for ($i = 0, $n = min(count($a), count($b)); $i < $n; $i++) {
  77. if ($a[$i] !== $b[$i])
  78. break;
  79. }
  80. return $i === 0 ? 0 : (float)$i / count($a);
  81. }
  82. }