language.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. module.exports = preferredLanguages;
  2. preferredLanguages.preferredLanguages = preferredLanguages;
  3. function parseAcceptLanguage(accept) {
  4. return accept.split(',').map(function(e) {
  5. return parseLanguage(e.trim());
  6. }).filter(function(e) {
  7. return e && e.q > 0;
  8. });
  9. }
  10. function parseLanguage(s) {
  11. var match = s.match(/^\s*(\S+?)(?:-(\S+?))?\s*(?:;(.*))?$/);
  12. if (!match) return null;
  13. var prefix = match[1],
  14. suffix = match[2],
  15. full = prefix;
  16. if (suffix) full += "-" + suffix;
  17. var q = 1;
  18. if (match[3]) {
  19. var params = match[3].split(';')
  20. for (var i = 0; i < params.length; i ++) {
  21. var p = params[i].split('=');
  22. if (p[0] === 'q') q = parseFloat(p[1]);
  23. }
  24. }
  25. return {
  26. prefix: prefix,
  27. suffix: suffix,
  28. q: q,
  29. full: full
  30. };
  31. }
  32. function getLanguagePriority(language, accepted) {
  33. var match = getClosestMatch(language, accepted);
  34. return match ? match.q : 0;
  35. }
  36. function getClosestMatch(language, accepted) {
  37. var parsed = parseLanguage(language);
  38. var matches = accepted.filter(function(a) {
  39. return a.full === parsed.full;
  40. });
  41. if (matches.length) return matches[0];
  42. matches = accepted.filter(function(a) {
  43. return a.prefix === parsed.prefix && !a.suffix;
  44. });
  45. if (matches.length) return matches[0];
  46. matches = accepted.filter(function(a) {
  47. return a.prefix === parsed.prefix;
  48. });
  49. if (matches.length) return matches[0];
  50. matches = accepted.filter(function(a) {
  51. return a.prefix === '*';
  52. });
  53. return matches[0];
  54. }
  55. function preferredLanguages(accept, provided) {
  56. accept = parseAcceptLanguage(accept || '');
  57. if (provided) {
  58. var ret = provided.map(function(type) {
  59. return [type, getLanguagePriority(type, accept)];
  60. }).filter(function(pair) {
  61. return pair[1] > 0;
  62. }).sort(function(a, b) {
  63. // revsort
  64. return a[1] === b[1] ? 0 : a[1] > b[1] ? -1 : 1;
  65. }).map(function(pair) {
  66. return pair[0];
  67. });
  68. return ret;
  69. } else {
  70. return accept.sort(function (a, b) {
  71. // revsort
  72. return a.q < b.q ? 1 : -1;
  73. }).map(function(type) {
  74. return type.full;
  75. });
  76. }
  77. }