﻿/*
 * StackExchange Localizer
 *
 * Copyright (c) 2010 Marek Stój, Rafał Legiędź
 * All rights reserved.
 * Wszelkie prawa zastrzeżone.
 */

// constants
var g_SiteName = 'devPytania';
var g_SiteDoman = 'devpytania.pl';
var g_NodeType_Text = 3;

// global variables
var g_supportsTextContent = null;
var g_supportsInnerText = null;

var g_currentUserName = null;
var g_currentUserId = null;
var g_isCurrentUserModerator = false;
var g_isCurrentUserAdministrator = false;

// utility functions
function getChildNodes(selector, nodeType) {
  return $(selector).contents().filter(function() { return this.nodeType == nodeType; });
}

function getChildTextNodes(selector) {
  return getChildNodes(selector, g_NodeType_Text);
}

function getNodeTextContent(node) {
  if (g_supportsTextContent) {
    return node.textContent;
  }
  else if (typeof(node.nodeValue) != 'undefined' && node.nodeValue != null) {
    return node.nodeValue;
  }
  else if (g_supportsInnerText) {
    return node.innerText;
  }
  else {
    return node.innerHTML;
  }
}

function getProperNumberForm(number, singular, plural1, plural2) {
  switch (getNumberClass(number)) {
    case g_NumberClass_Singular: return singular;
    case g_NumberClass_Plural_1: return plural1;
    case g_NumberClass_Plural_2: return plural2;
    default: break;
  }
  
  return null;
}

function getProperViewsNumberForm(viewsCount) {
  return getProperNumberForm(viewsCount, 'odsłona', 'odsłon', 'odsłony');
}

function getProperVotesNumberForm(votesCount) {
  return getProperNumberForm(votesCount, "głos", "głosów", "głosy");
}

function getProperQuestionsNumberForm(questionsCount) {
  return getProperNumberForm(questionsCount, "pytanie", "pytań", "pytania");
}

function getProperTaggedQuestionsNumberForm(taggedQuestionsCount) {
  return getProperNumberForm(taggedQuestionsCount, "pytanie otagowane ", "pytań otagowanych", "pytania otagowane");
}

function getProperAnswersNumberForm(answersCount) {
  return getProperNumberForm(answersCount, "odpowiedź", "odpowiedzi", "odpowiedzi");
}

function getProperCommentsNumberForm(commentsCount) {
  return getProperNumberForm(commentsCount, "komentarz", "komentarzy", "komentarze");
}

function getProperTagsNumberForm(tagsCount) {
  return getProperNumberForm(tagsCount, "tag", "tagów", "tagi");
}

function getProperBadgesNumberForm(badgesCount) {
  return getProperNumberForm(badgesCount, "odznaka", "odznak", "odznaki");
}

function getProperThousandNumberForm(count) {
  return getProperNumberForm(count, 'tysiąc', 'tysięcy', 'tysiące');
}

function getProperTimesNumberForm(number) {
  return getProperNumberForm(number, 'raz', 'razy', 'razy');
}

function getProperCharsNumberForm(number) {
  return getProperNumberForm(number, 'znak', 'znaków', 'znaki');
}

function getProperSecondsNumberForm(secondsCount) {
  return getProperNumberForm(secondsCount, 'sekunda', 'sekund', 'sekundy');
}

function getProperElementsNumberForm(itemsCount) {
  return getProperNumberForm(itemsCount, 'element', 'elementów', 'elementy');
}

function filterByTextRegex(query, regex) {
  return query.filter(function() {
    return $(this).text().match(regex) != null;
  });
}

function filterByAttrRegex(query, attrName, regex) {
  return query.filter(function() {
    var attrValue = $(this).attr(attrName);

    if (attrValue == undefined || attrValue == null) {
      return false;
    }

    attrValue = attrValue.toString();

    return attrValue.match(regex) != null;
  });
}

function capitalizeFirstLetter(text) {
  return text.charAt(0).toUpperCase() + text.substr(1);
}

var g_NumberClass_Singular = 0; // eg.: 1 odznaka
var g_NumberClass_Plural_1 = 1; // eg.: 5 odznak, 6 odznak, 13 odznak, 28 odznak
var g_NumberClass_Plural_2 = 2; // eg.: 3 odznaki, 4 odznaki, 24 odznaki, 193 odznaki

function getNumberClass(number) {
  number = Math.abs(number);

  if (number == 1) {
    return g_NumberClass_Singular;
  }

  if (number % 10 == 0) {
    return g_NumberClass_Plural_1;
  }

  var lastDigit = number % 10;
  var secondToLastDigit = Math.floor(number / 10) % 10;

  if (secondToLastDigit != 1 && lastDigit > 1 && lastDigit < 5) {
    return g_NumberClass_Plural_2;
  }

  return g_NumberClass_Plural_1;
}

function isUpperCase(s) {
  return s.toUpperCase() == s;
}

// localizes strings such as eg.:
// 6 mins ago
// 1d ago
// 4 hours ago
// 4h ago
// 29 secs ago
// dec 8 at 13:05
// ...
function localizeRelativeTime(text) {
  var textLower = trim(text.toLowerCase());
  var match = null;

  if ((match = textLower.match(/yesterday/i)) != null) {
    var result = 'wczoraj';

    if (isUpperCase(trim(text).charAt(0))) {
      result = capitalizeFirstLetter(result);
    }

    return result;
  }
  else if ((match = textLower.match(/today/i)) != null) {
    var result = 'dzisiaj';

    if (isUpperCase(trim(text).charAt(0))) {
      result = capitalizeFirstLetter(result);
    }

    return result;
  }
  else if ((match = textLower.match(/^([0-9]+)(\s*)(s|sec|secs|m|min|mins|h|hour|hours|d|day|days|month|months|y|year|years)(\s*)(ago)?\s*$/i)) != null) {
    var index = 1;
    var num = match[index++];
    var firstSpace = match[index++];
    var unit = match[index++];
    var secondSpace = match[index++];
    var agoSuffix = (match.length > index && match[index] != undefined) ? match[index] : null;

    return num
         + firstSpace
         + localizeRelativeTimeUnit(unit, num)
         + secondSpace
         + (agoSuffix != null ? 'temu' : '');
  }
  else if ((match = textLower.match(/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|january|february|march|april|may|june|july|august|september|october|november|december)\s*([0-9]+)\s*at\s*([0-9]+):([0-9]+)\s*$/i)) != null) {
    var index = 1;
    var month = match[index++];
    var day = match[index++];
    var hour = match[index++];
    var minute = match[index++];
    var localizedMonth = localizeMonth(month);

    if (isUpperCase(trim(text).charAt(0))) {
      localizedMonth = capitalizeFirstLetter(localizedMonth);
    }

    return localizedMonth
         + ' '
         + day
         + ' o '
         + hour
         + ':'
         + minute;
  }
  else if ((match = textLower.match(/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|january|february|march|april|may|june|july|august|september|october|november|december)\s*([0-9]+)\s*$/i)) != null) {
    var index = 1;
    var month = match[index++];
    var day = match[index++];
    var localizedMonth = localizeMonth(month);

    if (isUpperCase(trim(text).charAt(0))) {
      localizedMonth = capitalizeFirstLetter(localizedMonth);
    }

    return localizedMonth
         + ' '
         + day;
  }

  return text;
}

function localizeRelativeTimeUnit(unit, number) {
  switch (unit) {
    case 'sec':
      return 'sekunda';
    case 'secs':
      switch (getNumberClass(number)) {
        case g_NumberClass_Singular:
          return "sekunda";
        case g_NumberClass_Plural_1:
          return "sekund";
        case g_NumberClass_Plural_2:
          return "sekundy";
        default:
          break;
      }
      break;
    case 'min':
      return 'minuta';
    case 'mins':
      switch (getNumberClass(number)) {
        case g_NumberClass_Singular:
          return "minuta";
        case g_NumberClass_Plural_1:
          return "minut";
        case g_NumberClass_Plural_2:
          return "minuty";
        default:
          break;
      }
      break;
    case 'hour':
      return 'godzina';
    case 'hours':
      switch (getNumberClass(number)) {
        case g_NumberClass_Singular:
          return "godzina";
        case g_NumberClass_Plural_1:
          return "godzin";
        case g_NumberClass_Plural_2:
          return "godziny";
        default:
          break;
      }
      break;
    case 'day':
      return 'dzień';
    case 'days':
      switch (getNumberClass(number)) {
        case g_NumberClass_Singular:
          return "dzień";
        case g_NumberClass_Plural_1:
        case g_NumberClass_Plural_2:
          return "dni";
        default:
          break;
      }
      break;
    case 'month':
      return 'miesiąc';
    case 'months':
      switch (getNumberClass(number)) {
        case g_NumberClass_Singular:
          return "miesiąc";
        case g_NumberClass_Plural_1:
          return "miesięcy";
        case g_NumberClass_Plural_2:
          return "miesiące";
        default:
          break;
      }
      break;
    case 'year':
      return 'rok';
    case 'years':
      switch (getNumberClass(number)) {
        case g_NumberClass_Singular:
          return "rok";
        case g_NumberClass_Plural_1:
          return "lat";
        case g_NumberClass_Plural_2:
          return "lata";
        default:
          break;
      }
      break;
    case 'y':
      switch (getNumberClass(number)) {
        case g_NumberClass_Singular:
          return "r";
        case g_NumberClass_Plural_1:
        case g_NumberClass_Plural_2:
          return "l";
        default:
          break;
      }
      break;
    default:
      break;
  }

  return unit;
}

function localizeMonth(month) {
  var monthLower = trim(month.toLowerCase());
  var result = null;

  switch (month) {
    case 'jan': return 'sty';
    case 'feb': return 'lut';
    case 'mar': return 'mar';
    case 'apr': return 'kwi';
    case 'may': return 'maj';
    case 'jun': return 'cze';
    case 'jul': return 'lip';
    case 'aug': return 'sie';
    case 'sep': return 'wrz';
    case 'oct': return 'paź';
    case 'nov': return 'lis';
    case 'dec': return 'gru';
    default: break;
  }

  switch (month) {
    case 'january': return 'styczeń';
    case 'february': return 'luty';
    case 'march': return 'marzec';
    case 'april': return 'kwiecień';
    case 'may': return 'maj';
    case 'june': return 'czerwiec';
    case 'july': return 'lipiec';
    case 'august': return 'sierpień';
    case 'september': return 'wrzesień';
    case 'october': return 'październik';
    case 'november': return 'listopad';
    case 'december': return 'grudzień';
    default: break;
  }

  return month;
}

// localizes format of date/time
// if time is in UTC it will be converted to PL time zone
// recognized patterns are:
//   2009-03-23
//   2009-03-23 18:23:59
//   2009-03-23 18:23:59 UTC
function localizeDateTimeFormat(text) {
  var match = text.match(/([0-9]+)-([0-9]+)-([0-9]+)( ([0-9]+):([0-9]+):([0-9]+)( UTC)?)?/i);
  var year = match[1];
  var month = match[2];
  var day = match[3];
  var hour = null;
  var minute = null;
  var second = null;
  var isUTC = false;
  
  if (match.length > 7
   && match[4] != undefined
   && match[5] != undefined
   && match[6] != undefined
   && match[7] != undefined) {
    hour = match[5];
    minute = match[6];
    second = match[7];
  }
  
  if (match.length > 8 && match[8] != undefined) {
    isUTC = (match[8].match(/UTC/i) != null);
  }
  
  if (hour == null) {
    // change date format
    return day + '-' + month + '-' + year;
  }
  else if (!isUTC) {
    // change date format + display time
    return day + '-' + month + '-' + year + ' ' + hour + ':' + minute + ':' + second;
  }
  else {
    // convert from UTC to local, change date format + display time
    var date = new Date(Date.UTC(parseInt(year), parseInt(month, 10) - 1, parseInt(day, 10), parseInt(hour, 10), parseInt(minute, 10), parseInt(second, 10)));
    var padWithZero = function(num) {
      var s = num + '';
      
      return s.length < 2 ? '0' + s : s;
    };
      
    return padWithZero(date.getDate()) + '-' + padWithZero(date.getMonth() + 1) + '-' + date.getFullYear() + ' ' + padWithZero(date.getHours()) + ':' + padWithZero(date.getMinutes()) + ':' + padWithZero(date.getSeconds());
  }
}

// localizes strings such as: 4 times, 1 time
function localizeNumberTimes(text) {
  var match = text.match(/([0-9]+)\s+times?/i);

  if (match == null) {
    return text;
  }

  var number = parseInt(match[1]);

  return number
       + ' '
       + getProperTimesNumberForm(number);
}

function getPageTitle() {
  return document.title;
}

function setPageTitle(title) {
  if (title != null && title != '') {
    document.title = title + ' - ' + g_SiteName;
  }
  else {
    document.title = g_SiteName;
  }
}

function localizeEmailNotification(parentSelector) {
  var notifyEmailCheckboxElem = parentSelector.find('input#notify-email[type="checkbox"]');

  $(getChildTextNodes(notifyEmailCheckboxElem.parent())).replaceWith('');
  notifyEmailCheckboxElem.after(' Codziennie powiadamiaj ');
  parentSelector.find('input#notify-email-address[type="text"]').after(' o odpowiedziach');
}

function localizeUserCategoryElem(userCategoryElem) {
  var userCategory = trim(userCategoryElem.text().toLowerCase());
  var match = null;

  if ((match = userCategory.match(/^registered user(.*)$/i)) != null) {
    userCategoryElem.html('Użytkownik' + match[1]);
  }
  else if ((match = userCategory.match(/^administrator(.*)$/i)) != null) {
    userCategoryElem.html('Administrator' + match[1]);
  }
  else if ((match = userCategory.match(/^moderator(.*)$/i)) != null) {
    userCategoryElem.html('Moderator' + match[1]);
  }
}

// replaces first non-empty text node inside a label
// used to localize eg.: <label for="title">Title<span class="form-error" /></label>
// returns labelSelector
function replaceLabelText(labelSelector, newHtml) {
  var childTextNodes = getChildTextNodes(labelSelector);
  
  for (var i = 0; i < childTextNodes.length; i++) {
    var textNode = childTextNodes[i];
    
    if (trim(getNodeTextContent(textNode)) != '') {
      $(textNode).replaceWith(newHtml);
    
      break;
    }
  }
  
  return labelSelector;
}

// localizes post menus which are descendants of parentSelector
function localizePostMenus(parentSelector) {
  $.each(parentSelector.find('div.post-menu a'), function() {
    var aElem = $(this);

    if (aElem.text().match(/mod/i)) {
      aElem.html('mod');
    }
    else if (aElem.text().match(/link/i)) {
      aElem.html('link').attr('title', 'permalink do tego wpisu');
    }
    else if (aElem.text().match(/edit/i)) {
      aElem.html('edytuj').attr('title', 'edytuj ten wpis albo przywróć poprzednią rewizję');
    }
    else if (aElem.text().match(/close/i)) {
      aElem.html('zamknij').attr('title', 'zamyka/otwiera pytanie; na zamknięte pytania nie można udzielać nowych odpowiedzi');
    }
    else if (aElem.text().match(/open/i)) {
      aElem.html('otwórz').attr('title', 'zamyka/otwiera pytanie; na zamknięte pytania nie można udzielać nowych odpowiedzi');
    }
    else if (aElem.text().match(/delete/i)) {
      aElem.html('usuń').attr('title', 'głosuj za usunięciem tego wpisu');
    }
    else if (aElem.text().match(/flag/i)) {
      aElem.html('oznacz').attr('title', 'oznacz ten wpis jako problematyczny');
    }
  });
}

function localizeSidebarFormattingReference() {
  var formattingRefContainerElem = filterByTextRegex($('#sidebar div.module h4'), /formatting reference/i).parent();

  formattingRefContainerElem.html('<h4>Formatowanie tekstu</h4><p>&bull; <code>code</code> wcinamy 4 spacjami.</p><p>&bull; Nie chcesz kolorowania? Użyj &lt;pre&gt;.</p><p>&bull; Daj 2 spacje na końcu, by złamać wiersz.</p><p>&bull; Użyj &gt; do cytowania.</p><p>&bull; Odwrócony apostrof enkoduje <code>`właśnie _tak_`</code>.</p><p>&bull; URLe: &lt;http://foo.com&gt;<br>[foo](http://foo.com)<br>&lt;a href="http://foo.com"&gt;foo&lt;/a&gt;</p><p>&bull; <a href="/basic-html" target="_blank">Prosty HTML</a> również dozwolony.</p><p style="text-align:right;"><a href="/editing-help" target="_edithelp">pełny opis &raquo;</a></p>');
}

function localizeSidebarGoodEdits() {
  var goodEditsContainerElem = filterByTextRegex($('#sidebar div.module h4'), /good edits/i).parent();

  goodEditsContainerElem.html('<h4>Jak edytować?</h4><p>Popraw błędy ortograficzne, gramatyczne i stylistyczne.</p><p>Przeformułuj treść, by stała się bardziej zrozumiala.</p><p>Popraw drobne pomyłki.</p><p>Dodaj odnośniki do powiązanych zasobów.</p><p><i>Zawsze</i> szanuj pierwotnego autora.</p>');
}

function localizeSidebarRevisionEditWarning() {
  var revisionWarningContainerElem = filterByTextRegex($('#sidebar div.module.module-warning h4'), /warning/i).parent();

  revisionWarningContainerElem.html('<h4>Ostrzeżenie</h4><p>Edytujesz poprzednią rewizję. Jej zapisanie automatycznie spowoduje przywrócenie tej wersji wpisu.</p>');
}

function localizeQuestionSuggestions(postFormSelector) {
  var questionSuggestionsElem = postFormSelector.find('div#question-suggestions');
  var questionSuggestionsText = questionSuggestionsElem.text();
  var match = null;
  
  if ((match = questionSuggestionsText.match(/what's your question/i)) != null) {
    questionSuggestionsElem.html('Jakie jest Twoje pytanie?');
  }
  else if ((match = questionSuggestionsText.match(/that's not a very good title/i)) != null) {
    questionSuggestionsElem.html('To nie jest za dobry tytuł. Czy możesz go zmienić tak, żeby zawierał więcej unikatowych słów?');
  }
  else if ((match = questionSuggestionsText.match(/no questions found with related title/i)) != null) {
    questionSuggestionsElem.html('Nie znaleziono żadnych powiązanych pytań.');
  }
  
  // localize related questions (NOTE: not using else here is on purpose)
  questionSuggestionsElem.find('label').eq(0).html('Powiązane pytania:');
  
  $.each(questionSuggestionsElem.find('div.answer-summary div.answer-votes'), function() {
    var answerVotesElem = $(this);
    var answerVotesParent = answerVotesElem.closest('a');
    var answerVotesParentTitle = answerVotesParent.attr('title');
    var votesRegex = new RegExp("([0-9]+) votes?", "i");
    var answerVotesParentTitleMatch = answerVotesParentTitle.match(votesRegex);
    
    if (answerVotesParentTitleMatch == null) {
      return;
    }
    
    var votesCount = parseInt(answerVotesParentTitleMatch[1]);
    var newAnswerVotesParentTitle =
      answerVotesParentTitle
        .replace(votesRegex, '$1 ' + getProperVotesNumberForm(votesCount))
        .replace(/, with an accepted answer/i, ', z zaakceptowaną odpowiedzią');
    
    answerVotesParent.attr('title', newAnswerVotesParentTitle);
  });
}

function localizePostFormTitle(postFormSelector) {
  replaceLabelText(postFormSelector.find('label[for="title"]').eq(0), 'Tytuł');
  
  if (typeof(QuestionSuggestions) != 'undefined') {
    localizeQuestionSuggestions(postFormSelector);

    // bind to ajaxComplete global event, so that the question suggestions can be localized
    postFormSelector.bind('ajaxComplete', function(e, xhr, ajaxOptions) {
      var url = ajaxOptions.url;
      
      if (url.match(/^\/search\/titles/i) != null) {
        localizeQuestionSuggestions(postFormSelector);
      }
    });
  }
}

function localizePostFormTags(postFormSelector) {
  var tagnamesTextBoxElem = postFormSelector.find('input#tagnames').eq(0);

  replaceLabelText(tagnamesTextBoxElem.prevAll('label').eq(0), 'Tagi');
  tagnamesTextBoxElem.nextAll('div.form-item-info').eq(0).html('Podaj maksymalnie 5 tagów oddzielonych spacjami. We frazach używaj myślników do oddzielania poszczególnych słów. Przykład: tag inny-tag jeszcze-inny-tag.');
}

function localizePostFormEditSummary(postFormSelector) {
  var editCommentTextBoxElem = postFormSelector.find('input#edit-comment').eq(0);

  replaceLabelText(editCommentTextBoxElem.prevAll('label').eq(0), 'Podsumowanie zmian');
  editCommentTextBoxElem.nextAll('div.form-item-info').eq(0).html('Opisz krótko, jakich zmian dokonałeś (np.: poprawienie błędów, ulepszenie formatowania).');
}

// localizes comments which are descendants of parentSelector
function localizeComments(parentSelector) {
  $.each(parentSelector.find('td.comment-text'), function() {
    var commentCellElem = $(this);

    // time
    var timeElem = commentCellElem.find('span.comment-date span').eq(0);

    timeElem.html(localizeRelativeTime(timeElem.text()));

    // delete button
    commentCellElem.find('img.comment-delete').attr('title', 'usuń ten komentarz');
  });
}

// we must define our own trim because jQuery's trim doesn't trim non-breaking spaces (which are used by IE)
function trim(text) {
  return (text || '').replace(/^(\s|\u00A0)+|(\s|\u00A0)+$/g, '');
}

// logs message to console (firefox + firebug only)
function clog(msg) {
  if (typeof (console) != 'undefined') {
    console.log(msg);
  }
}

// stats container
function localizeStatsContainer() {
  $('#questions > .question-summary > .statscontainer > .stats > .vote > .votes').each(function() {
    var votesCount = $('.vote-count-post > strong', $(this)).text();
    
    $('div.viewcount', $(this)).html(getProperVotesNumberForm(votesCount));
  });

  $('#questions > .question-summary > .statscontainer > .stats > .status').each(function() {
    var number = $('strong', $(this)).text();
    var innerHtml = $(this).html();

    innerHtml = innerHtml.replace(/answers?/i, 'odpow.');

    $(this).html(innerHtml);
  });
  
  $('#questions > .question-summary > .statscontainer > .views').each(function() {
    var viewsCountElem = $(this);
    var viewsCountText = viewsCountElem.text();
    var viewsCount = parseInt(viewsCountText.split(' ')[0]);
    
    viewsCountElem.html(viewsCount + ' ' + getProperViewsNumberForm(viewsCount));
  });
}

function localizeTagsPage() {
  // header
  $('#mainbar-full #subheader h2').eq(0).html('Tagi');

  // tabs
  var tabsElems = $('#mainbar-full #subheader #tabs a');

  tabsElems.eq(0).html('popularne').attr('title', 'Najpopularniejsze tagi');
  tabsElems.eq(1).html('nazwa').attr('title', 'Tagi w kolejności alfabetycznej');

  $('div.page-description > p').eq(0).html("Pytania są pogrupowane tagami. Używanie poprawnych tagów, czyni łatwiejszym odnalezienie i odpowiedzenie na Twoje pytanie.");

  // tags filter label
  $('div.page-description input#tagfilter[type="text"]').closest('tr')
    .children('td').eq(0).html('Zacznij pisać, aby znaleźć tagi:');
}

// page titles
function localizePageTitle() {
  var urlPath = window.location.pathname;
  var queryString = window.location.search;
  var urlPathMatch = null;
  var queryStringMatch = null;
  var pageTitleMatch = null;
  var pageTitle = getPageTitle();

  if ((urlPathMatch = urlPath.match(/^\/questions\/ask/i)) != null) {
    setPageTitle('Zadaj pytanie');
  }
  else if ((urlPathMatch = urlPath.match(/^\/users\/-?[0-9]+/i)) != null) {
    pageTitleMatch = pageTitle.match(new RegExp("^User\\s*(.+)\\s*-\\s*" + g_SiteName + "$", "i"));
    
    if (pageTitleMatch != null) {
      setPageTitle('Użytkownik ' + pageTitleMatch[1]);
    }
  }
  else if ((match = urlPath.match(/^\/users\/recent\/-?[0-9]+/i)) != null) {
    pageTitleMatch = pageTitle.match(new RegExp("^User\\s*(.+)\\s*-\\s*recent\\s*-\\s*" + g_SiteName + "$", "i"));
    
    if (pageTitleMatch != null) {
      setPageTitle('Użytkownik ' + pageTitleMatch[1] + ' - Ostatnia aktywność');
    }
  }
  else if ((urlPathMatch = urlPath.match(/^\/captcha/i)) != null) {
    setPageTitle('Weryfikacja człowieczeństwa');
  }
  else if ((match = urlPath.match(/^\/posts\/[0-9]+\/edit/i)) != null) {
    setPageTitle('Edycja');
  }
  else if ((match = urlPath.match(/^\/revisions\/[0-9]+\/list/i)) != null) {
    setPageTitle('Rewizje');
  }
  /* TODO:
  else if ((urlPathMatch = urlPath.match(/^\/users\/edit\/-?[0-9]+/i)) != null) {
  }
  else if ((urlPathMatch = urlPath.match(/^\/users/i)) != null) {
  }
  else if ((urlPathMatch = urlPath.match(/^\/badges\/[0-9]+\/([^\/]+)/i)) != null) {
  }
  else if ((urlPathMatch = urlPath.match(/^\/badges/i)) != null) {
  }
  */
}

// bootstrap mode
function localizeBootstrapModule() {
  var $boostrapModule = $('#bootstrap-module');
  $('h4', $boostrapModule).html('Tryb rozruchowy');
  $('p', $boostrapModule).eq(0).html('Wymagania co do reputacji są mniej restrykcyjne podczas okresu rozwoju strony.');
  $('p', $boostrapModule).eq(1).html('Wszyscy użytkownicy mogą:');
  var $listItems = $('ul li', $boostrapModule);
  $listItems.eq(0).html('Zadawać pytania');
  $listItems.eq(1).html('Odpowiadać');
  $listItems.eq(2).html('Komentować');
  $listItems.eq(3).html('Tworzyć tagi');
  $listItems.eq(4).html('Zmieniać tagi pytań');
  $listItems.eq(5).html('Głosować');
  $('p a', $boostrapModule).html('Zobacz jak możesz pomóc »');
}

// common elements
function localizeCommonElements() {
  // reputations
  $('span.reputation-score').attr('title', 'reputacja');

  // badges
  localizeBadgeCounts('1');
  localizeBadgeCounts('2');
  localizeBadgeCounts('3');

  // flairs
  $.each($('span.mod-flair'), function() {
    var title = $(this).attr('title');

    if (title == 'administrator') {
      $(this).attr('title', 'administrator');
    }
    else if (title == 'moderator') {
      $(this).attr('title', 'moderator');
    }
  });

  // user action time elements
  $.each($('div.user-action-time'), function() {
    var textNodes = getChildTextNodes($(this));

    if (textNodes.length == 0) {
      return;
    }

    var firstTextNode = textNodes[0];
    var firstTextNodeValueLower = trim(getNodeTextContent(firstTextNode).toLowerCase());

    switch (firstTextNodeValueLower) {
      case 'asked': $(firstTextNode).replaceWith('zadane '); break;
      case 'answered': $(firstTextNode).replaceWith('odpowiedziane '); break;
      case 'edited': $(firstTextNode).replaceWith('edytowane '); break;
      case 'modified': $(firstTextNode).replaceWith('edytowane '); break;
      case 'occurred': $(firstTextNode).replaceWith('nastąpiło '); break;
      default: break;
    }
  });

  // relativetime elements
  $.each($('span.relativetime'), function() {
    $(this).html(localizeRelativeTime($(this).text()));
  });
  
  // votes and mini-votes
  $.each($('div.votes'), function() {
    var votesElem = $(this);
    var miniVotesElem = votesElem.children('div.mini-counts');

    if (miniVotesElem.length == 0) {
      var votesCountElem = votesElem.children('span.vote-count-post').eq(0).find('strong');
      
      if (votesCountElem.length == 0) {
        return;
      }
      
      var votesCount = parseInt(votesCountElem.text());
      
      votesElem.children('div.viewcount').html(getProperVotesNumberForm(votesCount));
    }
    else {
      var votesCount = parseInt(miniVotesElem.eq(0).text());
      var votesText = getProperVotesNumberForm(votesCount);
      var votesCountWrapper = miniVotesElem.eq(0).find('span[title="thousand"]');

      if (votesCountWrapper.length > 0) {
        votesText = 'k' + votesText;
        votesCountWrapper.attr('title', getProperThousandNumberForm(votesCount));
      }

      miniVotesElem.next('div').html(votesText);
    }
  });

  // answers and mini-answers
  var localizeMiniAnswersFunc = function() {
    var answersElem = $(this);
    var miniAnswersElem = answersElem.children('div.mini-counts');

    if (miniAnswersElem.length == 0) {
      var answersChildNodes = getChildTextNodes(answersElem);
      
      if (answersChildNodes.length > 0) {
        if (getNodeTextContent(answersChildNodes[answersChildNodes.length - 1]).match(/answers?/i) != null) {
          $(answersChildNodes[answersChildNodes.length - 1]).replaceWith('odpow.');
        }
      }
    }
    else {
      var answersCount = parseInt(miniAnswersElem.eq(0).text());
      var answersText = 'odpow.';
      var answersCountWrapper = miniAnswersElem.eq(0).find('span[title="thousand"]');

      if (answersCountWrapper.length > 0) {
        answersText = 'k' + answersText;
        answersCountWrapper.attr('title', getProperThousandNumberForm(answersCount));
      }

      miniAnswersElem.next('div').html(answersText);
    }
  };

  $.each($('div.answered'), localizeMiniAnswersFunc);
  $.each($('div.answered-accepted'), localizeMiniAnswersFunc);
  $.each($('div.unanswered'), localizeMiniAnswersFunc);

  // views and mini-views
  $.each($('div.views'), function() {
    var miniViewsElem = $(this).children('div.mini-counts');

    if (miniViewsElem.length == 0) {
      var viewsElem = $(this);
      var viewsText = viewsElem.text();
      var viewsMatch = null;
      var viewsRegex = new RegExp("([0-9]+) views?", "i");
      
      if ((viewsMatch = viewsText.match(viewsRegex)) != null) {
        var viewsCount = parseInt(viewsMatch[1]);
        
        viewsElem.html(viewsText.replace(viewsRegex, viewsCount + ' ' + getProperViewsNumberForm(viewsCount)));
      }
    }
    else {
      var viewsCount = parseInt(miniViewsElem.eq(0).text());
      var viewsText = getProperViewsNumberForm(viewsCount);
      var viewsCountWrapper = miniViewsElem.eq(0).find('span[title="thousand"]');

      if (viewsCountWrapper.length > 0) {
        viewsText = 'kodsł.';
        viewsCountWrapper.attr('title', getProperThousandNumberForm(viewsCount));
      }

      miniViewsElem.next('div').html(viewsText);
    }
  });
  
  // answer votes
  $('div.answer-votes').each(function() {
    var answerVotesElem = $(this);
    var answerVotesParentElem = answerVotesElem.parent('a');
    var answerVotesMatch = null;
    var currentAnswerVotesTitle = null;
    var newAnswerVotesTitle = null;

    if (answerVotesParentElem.length == 0 || answerVotesElem.hasClass('answered-accepted')) {
      currentAnswerVotesTitle = answerVotesElem.attr('title');
      
      if ((answerVotesMatch = currentAnswerVotesTitle.match(/total number of votes for this answer, which was accepted as the correct answer by the question owner/i)) != null) {
        newAnswerVotesTitle = 'Całkowita liczba głosów dla tej odpowiedzi, która została zaakceptowana przez autora pytania.';
      }
      else if ((answerVotesMatch = currentAnswerVotesTitle.match(/total number of votes for ([0-9]+) answers?; one of which was accepted as the correct answer by the question owner/i)) != null) {
        var answersCount = parseInt(answerVotesMatch[1]);
        
        newAnswerVotesTitle = 'Całkowita liczba głosów dla ' + answersCount + ' odpowiedzi, z których jedna została zaakceptowana przez autora pytania.';
      }
      
      if (newAnswerVotesTitle != null) {
        answerVotesElem.attr('title', newAnswerVotesTitle);
      }
    }
    else {
      currentAnswerVotesTitle = answerVotesParentElem.attr('title');
      
      if ((answerVotesMatch = currentAnswerVotesTitle.match(/total number of votes for this answer/i)) != null) {
        newAnswerVotesTitle = 'Całkowita liczba głosów dla tej odpowiedzi.';
      }
      else if ((answerVotesMatch = currentAnswerVotesTitle.match(/total number of votes for ([0-9]+) answers?/i)) != null) {
        var answersCount = parseInt(answerVotesMatch[1]);
        
        newAnswerVotesTitle = 'Całkowita liczba głosów dla ' + answersCount + ' odpowiedzi.';
      }
      
      if (newAnswerVotesTitle != null) {
        answerVotesParentElem.attr('title', newAnswerVotesTitle);
      }
    }
  });

  // post-tags
  $.each($('a.post-tag'), function() {
    $(this).attr('title', $(this).attr('title').replace(/^show questions tagged (.*)$/i, 'pokaż pytania z tagiem $1'));
  });

  // feeds
  $.each($('div#feed-link-text a'), function() {
    var aElem = $(this);
    var aElemHref = aElem.attr('href');

    if (aElemHref == undefined || aElemHref == null) {
      return;
    }

    if (aElemHref.match(/^\/feeds\/user\/-?[0-9]+/i) != null) {
      aElem
        .html('RSS użytkownika')
        .attr('title', '30 najnowszych pytań i odpowiedzi tego użytkownika');
    }
    else if (aElemHref.match(/^\/feeds/i) != null) {
      aElem
        .html('RSS: najnowsze pytania')
        .attr('title', '30 najnowszych pytań');
    }
  });

  // favorites
  $('img.vote-favorite')
    .attr('alt', 'gwiazdka')
    .hover(function() {
      $(this).attr('title', 'Dodaj to pytanie do ulubionych (kliknij ponownie, aby usunąć z ulubionych).');
    });

  // vote up images
  $.each($('div.vote img.vote-up'), function() {
    var imgElem = $(this);
    var imgTitle = imgElem.attr('title');

    if (imgTitle == undefined || imgTitle == null) {
      return;
    }

    if (imgTitle.match(/this question/i) != null) {
      imgElem.attr('title', 'To pytanie jest użyteczne i precyzyjnie sformułowane (kliknij ponownie, aby cofnąć głos).');
    }
    else if (imgTitle.match(/this answer/i) != null) {
      imgElem.attr('title', 'Ta odpowiedź jest pomocna (kliknij ponownie, aby cofnąć głos).');
    }
  });

  // vote down images
  $.each($('div.vote img.vote-down'), function() {
    var imgElem = $(this);
    var imgTitle = imgElem.attr('title');

    if (imgTitle == undefined || imgTitle == null) {
      return;
    }

    if (imgTitle.match(/this question/i) != null) {
      imgElem.attr('title', 'To pytanie nie jest użyteczne lub nie jest precyzyjnie sformułowane (kliknij ponownie, aby cofnąć głos).');
    }
    else if (imgTitle.match(/this answer/i) != null) {
      imgElem.attr('title', 'Ta odpowiedź nie jest pomocna (kliknij ponownie, aby cofnąć głos).');
    }
  });

  // accept answer images
  $.each($('div.vote img.vote-accepted'), function() {
    var imgElem = $(this);
    var imgTitle = imgElem.attr('title');

    if (imgTitle == undefined || imgTitle == null) {
      return;
    }

    var newTitle = 'Kliknij, aby zaakceptować tę odpowiedź (kliknij ponownie, jeśli zmienisz zdanie).';
    var acceptedMatch = imgTitle.match(/accepted\s+([^\.]+\s*ago)$/i);

    if (acceptedMatch != null) {
      newTitle += ' Zaakceptowano ' + localizeRelativeTime(acceptedMatch[1]) + '.';
    }

    imgElem.attr('title', newTitle);
  });
  
  // revision-comments
  $('span.revision-comment').each(function() {
    var revisionCommentElem = $(this);
    var revisionCommentText = trim(revisionCommentElem.text());
    
    revisionCommentElem.html(localizeRevisionComment(revisionCommentText));
  });
  
  // 'show revision history' elements in signatures
  localizeShowRevHistoryElemsInSignatures();
  
  // bind to ajaxComplete global event, so that community wiki history summary can be localized after refresh
  $('body').eq(0)
    .bind('ajaxComplete', function(e, xhr, ajaxOptions) {
      var url = ajaxOptions.url;
      
      if (url.match(/^\/revisions\/[0-9]+\/generate-history-summary/i) != null) {
        localizeShowRevHistoryElemsInSignatures();
      }
    });
  
  // comment context buttons
  $('img.comment-up').attr('title', 'ten komentarz jest znakomity');
  $('img.comment-flag').attr('title', 'ten komentarz to spam lub jest obraźliwy');
  
  // pager
  $('div.pager a').each(function() {
    var aElem = $(this);
    var pageNumbersElem = aElem.children('span.page-numbers').eq(0);
    
    if (pageNumbersElem.length > 0) {
      var pageNumbersTextLower = trim(pageNumbersElem.text().toLowerCase());
      
      switch (pageNumbersTextLower) {
        case 'next': pageNumbersElem.html('dalej'); break;
        case 'prev': pageNumbersElem.html('wstecz'); break;
        default: break;
      }
    }

    var aTitle = aElem.attr('title');
    var titleMatch = null;
    
    if ((titleMatch = aTitle.match(/go to page ([0-9]+)/i)) != null) {
      aElem.attr('title', 'przejdź do strony nr ' + titleMatch[1]);
    }
  });
  
  // page-sizer
  $('div.page-sizer a.page-numbers').each(function() {
    var aElem = $(this);
    var aTitle = aElem.attr('title');
    var titleMatch = null;
    
    if ((titleMatch = aTitle.match(/show ([0-9]+) items per page/i)) != null) {
      var itemsCount = parseInt(titleMatch[1]);
      
      aElem.attr('title', 'pokaż ' + itemsCount + ' ' + getProperElementsNumberForm(itemsCount) + ' na stronie');
    }
  });
  
  $('div.page-sizer span.page-numbers.desc').html('na stronie');
}

function localizeRevisionComment(revisionComment) {
  var result =
    revisionComment
      .replace(/edited body/gi, 'edytowano treść')
      .replace(/edited tags/gi, 'edytowano tagi')
      .replace(/edited title/gi, 'edytowano tytuł')
      .replace(/added ([0-9]+) characters? in body/gi, function(s, p1) { return 'dodano ' + p1 + ' ' + getProperCharsNumberForm(parseInt(p1)) + ' do treści'; })
      .replace(/deleted ([0-9]+) characters? in body/gi, function(s, p1) { return 'usunięto ' + p1 + ' ' + getProperCharsNumberForm(parseInt(p1)) + ' z treści'; });
  
  return result;
}

function localizeShowRevHistoryElemsInSignatures() {
  $('td.post-signature > div.user-info > div.user-details > a[id^="history"][href^="/revisions"]').each(function() {
    var showRevHistoryElem = $(this);
    
    showRevHistoryElem.attr('title', 'pokaż historię rewizji tego wpisu');
    
    var revHistoryTextNodes = getChildTextNodes(showRevHistoryElem);
    var revHistoryMatch = null;
    
    for (var revHistoryTextNodeIndex = 0; revHistoryTextNodeIndex < revHistoryTextNodes.length; revHistoryTextNodeIndex++) {
      var revHistoryTextNode = revHistoryTextNodes[revHistoryTextNodeIndex];
      var revHistoryTextNodeText = getNodeTextContent(revHistoryTextNode);
      var newRevHistoryTextNodeText = revHistoryTextNodeText;
    
      if (revHistoryTextNodeText.match(/[0-9]+ revisions?/i) != null || revHistoryTextNodeText.match(/[0-9]+ users?/i) != null) {
        newRevHistoryTextNodeText = newRevHistoryTextNodeText.replace(/([0-9])+ revisions?/i, function(s, p1) {
            return p1 + ' ' + getProperNumberForm(parseInt(p1), 'rewizja', 'rewizji', 'rewizje');
          });

        newRevHistoryTextNodeText = newRevHistoryTextNodeText.replace(/([0-9])+ users?/i, function(s, p1) {
            return p1 + ' użytk.';
          });
          
        $(revHistoryTextNode).replaceWith(newRevHistoryTextNodeText);
      
        break;
      }
    }
  });
}

// flagging
if (typeof (vote) != 'undefined') {
  var old_vote_flag = vote.flag;

  vote.flag = function(jClicked) {
    old_vote_flag(jClicked);

    var postId = jClicked.attr("id").substring("flag-post-".length);

    $('div.flag-menu h2').html("Prosimy, oznaczaj uważnie:");
    $('label[for="flag-radio' + postId + '-4"]').html("Obraźliwy, niewłaściwy bądź nienawistny");
    // spam -12 does not need to be translated
    $('label[for="flag-radio' + postId + '--1"]').html("Wymaga uwagi moderatora");
    $('div.flag-menu .flag-cancel').html("Anuluj");
    $('div.flag-menu .flag-submit').html("Oznacz wpis");

    var flag_comment = getChildTextNodes($('div.flag-comment'))[0];
    $(flag_comment).replaceWith("Dlaczego chcesz oznaczyć ten wpis?");
  };

  var old_vote_close_renderForm = vote.close_renderForm;

  vote.close_renderForm = function(jClicked) {
    old_vote_close_renderForm(jClicked);

    var postId = jClicked.attr("id").substring("close-question-".length);

    var $close_popup = $('#close-popup-' + postId);
    $('h2', $close_popup).html("Dlaczego ten wpis powinien zostać zamknięty?");
    $('li a', $close_popup).each(function() {
      var original_text = $(this).html();
      $(this).html(getLocalizedCloseReason(original_text));
    });
    $('a.close-cancel', $close_popup).html("Anuluj");
  };
}

// notifications
if (typeof (notify) != 'undefined') {
  var old_notify_showFirstTime = notify.showFirstTime;

  notify.showFirstTime = function() {
    old_notify_showFirstTime();
    $('#notify-container #notify--1 .notify').html('Pierwszy raz tutaj? Poczytaj <a onclick="notify.closeFirstTime()">FAQ</a>!');
  };

  var old_notify_showMessages = notify.showMessages;

  notify.showMessages = function(jsonMsgArray) {
    old_notify_showMessages(jsonMsgArray);
    localizeNotifications(jsonMsgArray);
  };
}

function localizeNotifications(jsonMsgArray) {
  if (jsonMsgArray == null || jsonMsgArray.length == 0) {
    return;
  }

  var notifyContainer = $('#notify-container');

  for (var i = 0; i < jsonMsgArray.length; i++) {
    localizeNotification(notifyContainer, jsonMsgArray[i], i);
  }
}

function localizeNotification(notifyContainer, notificationJson, rowIndex) {
  var msgTypeId = notificationJson.messageTypeId;
  var msgText = notificationJson.text;
  var msgTextLower = msgText.toLowerCase();
  var newMsgText = null;
  var msgMatch = null;

  switch (msgTypeId) {
    case 1:
      if (msgTextLower.indexOf('welcome to') != -1 && msgTextLower.indexOf('visit your') != -1) {
        newMsgText = 'Witaj w serwisie devPytania! Odwiedź <a href="/users/edit/' + notificationJson.userId + '">stronę profilu</a>, aby podać swoje dane.';
      }

      break;
    case 2:
      if (msgTextLower.indexOf('congratulations') != -1 && msgTextLower.indexOf('administrator') != -1) {
        newMsgText = 'Gratulacje, jesteś teraz administratorem. Zobacz fajne narzędzia, których możesz teraz używać: <a href="/manage">admin</a>, <a href="/admin">mod</a> i <a href="/tools">narzędzia</a>.';
      }
      else if (msgTextLower.indexOf('grant') != -1 && msgTextLower.indexOf('moderator') != -1) {
        newMsgText = 'Uzyskałeś uprawnienia moderatora. Zobacz fajne narzędzia, których możesz teraz używać: <a href="/admin">mod</a> i <a href="/tools">narzędzia</a>.';
      }
      else if (msgTextLower.indexOf('revoke') != -1 && msgTextLower.indexOf('administrator') != -1) {
        newMsgText = 'Utraciłeś uprawnienia administratora.';
      }
      else if (msgTextLower.indexOf('revoke') != -1 && msgTextLower.indexOf('moderator') != -1) {
        newMsgText = 'Utraciłeś uprawnienia moderatora.';
      }
      else if ((msgMatch = msgTextLower.match(/^you have ([0-9]+) new answers?\./i)) != null) {
        var answersCount = parseInt(msgMatch[1]);

        newMsgText = 'Masz ' + answersCount + ' ' + getProperNumberForm(answersCount, 'nową', 'nowych', 'nowe') + ' ' + getProperAnswersNumberForm(answersCount);
        newMsgText += msgText.substr(msgText.indexOf('.')).replace(/^\. see your/i, '. Zobacz').replace(/\>responses\</i, '>odpowiedzi<');
      }
      else if ((msgMatch = msgTextLower.match(/^you have ([0-9]+) new comments?\./i)) != null) {
        var commentsCount = parseInt(msgMatch[1]);

        newMsgText = 'Masz ' + commentsCount + ' ' + getProperNumberForm(commentsCount, 'nowy', 'nowych', 'nowe') + ' ' + getProperCommentsNumberForm(commentsCount);
        newMsgText += msgText.substr(msgText.indexOf('.')).replace(/^\. see your/i, '. Zobacz').replace(/\>responses\</i, '>odpowiedzi<');
      }
      else if ((msgMatch = msgTextLower.match(/^you have ([0-9]+) new answers? and ([0-9]+) new comments?\./i)) != null) {
        var answersCount = parseInt(msgMatch[1]);
        var commentsCount = parseInt(msgMatch[2]);

        newMsgText = 'Masz ' + answersCount + ' ' + getProperNumberForm(answersCount, 'nową', 'nowych', 'nowe') + ' ' + getProperAnswersNumberForm(answersCount);
        newMsgText += ' i ' + commentsCount + ' ' + getProperNumberForm(commentsCount, 'nowy', 'nowych', 'nowe') + ' ' + getProperCommentsNumberForm(commentsCount);
        newMsgText += msgText.substr(msgText.indexOf('.')).replace(/^\. see your/i, '. Zobacz').replace(/\>responses\</i, '>odpowiedzi<');
      }

      break;

    case 5:
      var badgeRegex = /"([^"]+)"\s*(and\s*([0-9]+)\s*other)?\s*badges?/;
      var matches = msgTextLower.match(badgeRegex);
      
      if (matches == null || matches.length < 2) {
        break;
      }
      
      var badgeName = matches[1];
      
      newMsgText = 'Zdobyłeś odznakę \'' + getLocalizedBadgeName(badgeName) + '\'';
      
      if (matches.length > 3 && matches[2] != null && matches[3] != null && matches[2] != undefined && matches[3] != undefined) {
        var otherBadgesCount = parseInt(matches[3]);
        
        newMsgText += ' i ' + otherBadgesCount + ' ' + getProperNumberForm(otherBadgesCount, 'inną', 'innych', 'inne') + ' ' + getProperNumberForm(otherBadgesCount, 'odznakę', 'odznak', 'odznaki');
      }
      
      newMsgText += '.';

      if (notificationJson.showProfile) {
        var userUrl = escape("/users/" + notificationJson.userId);

        newMsgText += ' Zobacz swój <a href="/messages/mark-as-read?messagetypeid=' + notificationJson.messageTypeId + '&returnurl=' + userUrl + '">profil</a>.';
      }

      break;
    default:
      break;
  }

  if (newMsgText != null) {
    notifyContainer.find('tr:eq(' + rowIndex + ') .notify').html(newMsgText);
  }
}

// intercept utility functions
if (typeof (enableSubmitButton) != 'undefined') {
  var old_enableSubmitButton = enableSubmitButton;

  enableSubmitButton = function(formSelector) {
    old_enableSubmitButton(formSelector);

    var formId = $(formSelector).attr('id');

    if (formId != undefined && formId != null && formId.match(/form-comments-[0-9]+/)) {
      // user has added a new comment, so we have to localize comments again
      localizeComments($(formSelector).closest('div.post-comments').find('div.comments'));
    }
  };
}

if (typeof (showAjaxError) != 'undefined') {
  var old_showAjaxError = showAjaxError;

  showAjaxError = function(insertionSelector, msg) {
    old_showAjaxError(insertionSelector, msg);

    // localize error message
    var errorNotifElem = $(insertionSelector).children('div.error-notification');
    var msgMatch = null;
    var newMsg = null;

    if ((msgMatch = msg.match(/you may only submit a comment every ([0-9]+) seconds/i)) != null) {
      var secondsCount = parseInt(msgMatch[1]);

      newMsg = 'Nie możesz dodawać komentarzy częściej niż co ' + secondsCount + ' ' + getProperSecondsNumberForm(secondsCount) + '.';
    }

    if (newMsg != null) {
      errorNotifElem.children('h2').eq(0).html(newMsg);
    }

    // localize dismiss information
    var textNodes = getChildTextNodes(errorNotifElem);

    if (textNodes.length > 0) {
      $(textNodes[textNodes.length - 1]).replaceWith('(kliknij ten komunikat, aby go zamknąć)');
    }
  };
}

// comments
if (typeof (comments) != 'undefined') {
  var old_comments_updateTextCounter = comments.updateTextCounter;

  comments.updateTextCounter = function(textarea, maxLength, minLength) {
    old_comments_updateTextCounter(textarea, maxLength, minLength);

    var textCounterElem = $(textarea).closest('form').find('span.text-counter');
    var textCounterText = textCounterElem.text();
    var match = null;
    var number = null;

    if ((match = textCounterText.match(/enter at least (-?[0-9]+) characters?/i)) != null) {
      number = parseInt(match[1]);
      textCounterElem.html('Wprowadź przynajmniej ' + number + ' ' + getProperCharsNumberForm(number) + '.');
    }
    else if ((match = textCounterText.match(/(-?[0-9]+) more to go/i)) != null) {
      number = parseInt(match[1]);
      textCounterElem.html('Jeszcze tylko ' + number + ' ' + getProperCharsNumberForm(number) + '...');
    }
    else if ((match = textCounterText.match(/(-?[0-9]+) characters? left/i)) != null) {
      number = parseInt(match[1]);
      textCounterElem.html('P' + getProperNumberForm(number, 'ozostał', 'ozostało', 'ozostały') + ' ' + number + ' ' + getProperCharsNumberForm(number) + '.');
    }
  };
}

// ask question
function localizeAskQuestionPage() {
  // header
  $('#content #subheader h2').eq(0).html('Zadaj pytanie');

  // post form
  var postFormElem = $('#content form#post-form');
  
  localizePostFormTitle(postFormElem);
  localizePostFormTags(postFormElem);

  localizeEmailNotification(postFormElem);

  // form items for anonymous users
  var anonUserTableRowElem = replaceLabelText($('#content div.form-item table td label[for="openid_identifier"]'), 'Login OpenID')
    .closest('td').find('div.form-item-info')
    .html(' Spraw sobie <a target="_blank" href="http://openid.net/get/">OpenID</a>.')
    .closest('tr');

  var anonUserTableRowCells = anonUserTableRowElem.find('td');

  anonUserTableRowCells.eq(1).children('div').eq(0).html('lub');

  var anonUserTableRowCell3 = anonUserTableRowCells.eq(2);

  replaceLabelText(anonUserTableRowCell3.find('label[for="display-name"]'), 'Nazwa');

  var emailLabelElem = anonUserTableRowCell3.find('label[for="email"]');

  replaceLabelText(emailLabelElem, 'E-mail ');
  emailLabelElem.find('span.greyed').eq(0).html('nie będzie pokazywany');

  replaceLabelText(anonUserTableRowCell3.find('label[for="home-page"]'), 'Strona WWW');

  // submit button
  postFormElem.find('input[type="submit"]').eq(0).val('Zadaj pytanie');

  // post editor
  localizePostEditor();

  // formatting reference
  localizeSidebarFormattingReference();
}

// post editor
function localizePostEditor() {
  var postEditorElem = $('#content #post-editor');

  replaceLabelText(postEditorElem.find('label[for="communitymode"]'), 'społecznościowe wiki')
    .attr('title', 'Treści będące częścią społecznościowego wiki nie generują reputacji dla właściciela, mają mniejsze progi reputacji wymaganej do ich edycji oraz nie wyświetlamy przy nich sygnatury autora, a jedynie historię rewizji.');
}

// question
function localizeQuestionPage() {
  // question header
  var questionHeaderLinkElem = $('#content #question-header a.question-hyperlink');

  questionHeaderLinkElem.html(questionHeaderLinkElem.text().replace(/\[closed\]/i, '[zamknięte]'));

  // answers header
  var answersSubheaderElem = $('#answers-header #subheader');
  var answersHeaderTitleElem = answersSubheaderElem.find('h2').eq(0);
  var answersCountMatch = answersHeaderTitleElem.text().match(/([0-9]+)\s+answers?/i);

  if (answersCountMatch != null) {
    var answersCount = parseInt(answersCountMatch[1]);

    answersHeaderTitleElem.html(answersCount + ' ' + getProperAnswersNumberForm(answersCount));
  }

  // new answer section
  var showEditorSubmitButtonElem = $('#show-editor-button input[type="button"]').eq(0);
  
  if (showEditorSubmitButtonElem.length > 0) {
    var showEditorSubmitButtonText = showEditorSubmitButtonElem.val();

    if (showEditorSubmitButtonText.match(/add another answer/i) != null) {
      showEditorSubmitButtonElem.val('Dodaj kolejną odpowiedź');
      
      if (typeof(showEditorConfirmPrompt) != 'undefined') {
        showEditorConfirmPrompt = 'Czy jesteś pewien, że chcesz dodać kolejną odpowiedź?\n\nZamiast tego mógłbyś użyć opcji edycji, aby poprawić bądź ulepszyć swoją istniejącą odpowiedź.';
      }
      
      // TODO: click event?
    }
    else if (showEditorSubmitButtonText.match(/answer your question/i) != null) {
      showEditorSubmitButtonElem.val('Odpowiedz na swoje pytanie');
      
      if (typeof(showEditorConfirmPrompt) != 'undefined') {
        showEditorConfirmPrompt = 'Czy jesteś pewien, że chcesz odpowiedzieć na swoje pytanie?\n\nJeśli chcesz odpowiedzieć na inną odpowiedź, użyj systemu komentarzy dostępnego pod każdą odpowiedzią.';
      }
      
      // TODO: click event?
    }
  }

  // post editor
  localizePostEditor();
  
  // post form
  var postFormElem = $('#content form#post-form');
  
  postFormElem.children('h2').eq(0).html('Twoja odpowiedź');
  postFormElem.find('input[type="submit"]').eq(0).val('Odpowiedz')
  
  // add comment links
  $.each($('#mainbar a.comments-link'), function() {
    var addCommentLinkElem = $(this);
    var addCommentLinkId = addCommentLinkElem.attr('id');

    if (addCommentLinkId == undefined || addCommentLinkId == null) {
      return;
    }

    var idMatch = addCommentLinkId.match(/comments-link-([0-9]+)/);

    if (idMatch == null) {
      return;
    }

    var addShowMatch = addCommentLinkElem.text().match(/show ([0-9]+) more comment/i);

    if (addShowMatch != null) {
      var moreCommentsCount = parseInt(addShowMatch[1]);
      addCommentLinkElem.html('dodaj / pokaż ' + moreCommentsCount + ' ' + getProperCommentsNumberForm(moreCommentsCount) + '<span style="display: none;">more comment</span>').attr('title', 'rozwiń, aby zobaczyć wszystkie komentarze lub dodaj własny');
    }
    else {
      addCommentLinkElem.html('dodaj komentarz').attr('title', 'Skomentuj ten wpis');
    }

    var idNum = parseInt(idMatch[1]);
    var commentEditContainerElem = $('#comments-' + idNum);

    addCommentLinkElem.click(function() {
      commentEditContainerElem.find('span.text-counter').html('Wprowadź przynajmniej 15 znaków.');
      commentEditContainerElem.find('input[type="submit"]').val('Dodaj komentarz');
    });
  });

  // post menus
  localizePostMenus($('#content #question'));
  localizePostMenus($('#content #answers'));

  // comments
  localizeComments($('#content div.post-comments div.comments'));

  // tabs  
  var tabsElems = answersSubheaderElem.find('#tabs a');

  tabsElems.eq(0).html('najstarsze').attr('title', 'Odpowiedzi uporządkowane od najstarszej');
  tabsElems.eq(1).html('najnowsze').attr('title', 'Odpowiedzi uporządkowane od najnowszej');
  tabsElems.eq(2).html('głosy').attr('title', 'Odpowiedzi uporządkowane według liczby pozytywnych głosów');

  // question info
  var questionInfoContainerElem = $('#sidebar div.module').eq(0);

  filterByTextRegex(questionInfoContainerElem.find('p.label-key'), /tagged/i)
    .html('tagi');

  var askedLabelValueElem = filterByTextRegex(questionInfoContainerElem.find('p.label-key'), /asked/i)
    .html('zadane')
    .next('p.label-value');

  askedLabelValueElem.html(localizeRelativeTime(askedLabelValueElem.text()));

  var viewedLabelValueElem = filterByTextRegex(questionInfoContainerElem.find('p.label-key'), /viewed/i)
    .html('wyświetlane')
    .next('p.label-value');

  viewedLabelValueElem.html(localizeNumberTimes(viewedLabelValueElem.text()));
  
  var latestActivityLabelValueElem = filterByTextRegex(questionInfoContainerElem.find('p.label-key'), /latest activity/i)
    .html('ostatnia aktywność')
    .next('p.label-value');

  latestActivityLabelValueElem.html(localizeRelativeTime(latestActivityLabelValueElem.text()));

  // related
  var relatedContainerElem = $('#sidebar div.module').eq(1);

  relatedContainerElem.children('h4').eq(0).html('Powiązane');

  // footer
  localizeEmailNotification($('#content input#notify-email[type="checkbox"]').closest('div'));

  var notTheAnswerElem = filterByTextRegex($('#content #answers').children('h2'), /^\s*(not the answer you're looking for)|(browse other questions)/i);
  var notTheAnswerRawTextNodes = getChildTextNodes(notTheAnswerElem);
  var notTheAnswerTextNodes = $(notTheAnswerRawTextNodes);

  var notTheAnswerElemFirstTextNode = notTheAnswerTextNodes.eq(0);
  
  if (getNodeTextContent(notTheAnswerRawTextNodes[0]).match(/^\s*not the answer/i)) {
    notTheAnswerElemFirstTextNode.replaceWith('Nie znalazłeś odpowiedzi? Przeglądnij inne pytania otagowane ');
  }
  else if (getNodeTextContent(notTheAnswerRawTextNodes[0]).match(/^\s*browse other questions/i)) {
    notTheAnswerElemFirstTextNode.replaceWith('Przeglądnij inne pytania otagowane ');
  }
  
  $.each(notTheAnswerRawTextNodes, function() {
    var notTheAnswerRawTextNode = this;
    
    if (getNodeTextContent(notTheAnswerRawTextNode).match(/^\s*or\s*$/i) != null) {
      $(notTheAnswerRawTextNode).replaceWith(' lub ');
    }
  });

  filterByAttrRegex(notTheAnswerElem.children('a'), 'href', /^\/questions\/ask/i).eq(0).html('zadaj własne pytanie');

  // bounty notification
  var bountyNotificationMessageElem = $('#question #bounty-notification .question-status h2').eq(0);

  if (bountyNotificationMessageElem.length > 0) {
    var bountyNotificationMessageHtml = bountyNotificationMessageElem.html();
    var bountyMatch;
    var bountyPrize = null;
    var bountyDaysLeft = null;
    var bountyDeadline = null;

    if ((bountyMatch = bountyNotificationMessageHtml.match(/<strong>([1-9][0-9]+)<\/strong>/i)) != null) {
      bountyPrize = bountyMatch[1];
    }

    if ((bountyMatch = bountyNotificationMessageHtml.match(/in ([0-9]+) days?/i)) != null) {
      bountyDaysLeft = bountyMatch[1];
    }

    if ((bountyMatch = bountyNotificationMessageHtml.match(/in ([0-9]+) days?/i)) != null) {
      bountyDaysLeft = parseInt(bountyMatch[1]);
    }

    if ((bountyMatch = bountyNotificationMessageHtml.match(/title="([^"]+)"/i)) != null) {
      bountyDeadline = bountyMatch[1];
    }

    if (bountyPrize != null && bountyDaysLeft != null && bountyDeadline != null) {
      var bountyDaysLeftString = getProperNumberForm(bountyDaysLeft, "został", "zostało", "zostały") + ' ' + bountyDaysLeft + ' ' + getProperNumberForm(bountyDaysLeft, "dzień", "dni", "dni");

      bountyNotificationMessageElem.html('Za udzielenie odpowiedzi na to pytanie wyznaczono <a href="/faq#bounty">nagrodę</a> w wysokości <strong>' + bountyPrize + '</strong> punktów reputacji, na której zdobycie ' + bountyDaysLeftString + '.');
    }
  }
}

function localizeDatesInHistoryTable(historyTable) {
  $.each($('td div.date', historyTable), function() {
    var elem = $(this);
    var dateBrickElem = elem.children('div.date_brick');

    if (dateBrickElem != null && dateBrickElem.length > 0) {
      var dateText = dateBrickElem.html().replace(/\<br\s*\>/, ' ');

      dateBrickElem.html(localizeRelativeTime(dateText).replace(/\s+/, '<br />'));
    }
    else {
      elem.html(localizeRelativeTime(elem.text()));
    }
  });
}

function localizeAccInHistoryTable(tableSelector) {
  $.each(tableSelector.find('td > div.accept'), function() {
    var acceptElem = $(this);
    var acceptChildren = getChildTextNodes(acceptElem);
    
    if (acceptChildren.length > 0 && trim(getNodeTextContent(acceptChildren[0]).toLowerCase()) == 'acc') {
      $(acceptChildren[0]).replaceWith('akc');
    }
  });
}

function localizeEventTypesInHistoryTable(tableSelector) {
  $.each(tableSelector.find('tr'), function() {
    var thirdCellElem = $(this).children('td').eq(2);
    var acceptAnswerLinkElem = thirdCellElem.children('span.accept-answer-link').eq(0);
    
    if (acceptAnswerLinkElem.length > 0) {
      var acceptAnswerLinkText = trim(acceptAnswerLinkElem.text().toLowerCase());
      
      switch (acceptAnswerLinkText) {
        case 'answered': acceptAnswerLinkElem.replaceWith('<span class="event-type">odpowiedź na: </span>'); break;
        default: break;
      }
    }
    else {
      var boldActionElem = thirdCellElem.children('b').eq(0);
      
      if (boldActionElem.length > 0) {
        var boldActionText = trim(boldActionElem.text().toLowerCase());
        
        switch (boldActionText) {
          case 'commented on': boldActionElem.replaceWith('<span class="event-type">komentarz do: </span>');
          default: break;
        }
      }
    }
  });
}

function localizeUserTabs(tabsSelector) {
  tabsSelector.children('a').each(function() {
    var aElem = $(this);
    var aText = aElem.text();
    
    switch (trim(aText.toLowerCase())) {
      case 'votes': aElem.html('głosy'); aElem.attr('title', 'sortuj według liczby głosów'); break;
      case 'newest': aElem.html('najnowsze'); aElem.attr('title', 'sortuj według daty'); break;
      case 'views': aElem.html('odsłony'); aElem.attr('title', 'sortuj według liczby odsłon'); break;
      case 'recent': aElem.html('ostatnie'); aElem.attr('title', 'sortuj według ostatniej aktywności'); break;
      default: break;
    }
  });
}

// user
function localizeUserPage() {
  var userDetailTableElem = $('table.user-detail');

  // reputation
  var userDetailTableRows = userDetailTableElem.find('table').eq(0).find('tr');

  userDetailTableRows.eq(1).children('td.summaryinfo').children('div.summarycount').next().html('Reputacja');

  // views count
  var viewsCountCell = userDetailTableRows.eq(2).children('td.summaryinfo');
  var viewsCount = parseInt(viewsCountCell.text());

  viewsCountCell.html(viewsCount + ' ' + getProperViewsNumberForm(viewsCount))

  // got flair?
  userDetailTableRows.eq(3).children('td.summaryinfo').children('a').eq(0)
    .attr('href', '/user-flair')
    .html('Masz już plakietkę?');

  // user menu
  // TODO: kurwa, nie pamietam o co tu chodzilo :/
  userDetailTableElem.find('td > div > a.toggle-admin').html('admin');
  userDetailTableElem.find('td > div > a#moderator-actions-link').html('mod')
  filterByAttrRegex(userDetailTableElem.find('td > div > a'), 'href', /^\/users\/edit\/-?[0-9]+$/i).html('edytuj');
  filterByAttrRegex(userDetailTableElem.find('td > div > a'), 'href', /^\/users\/login/i).html('nowy login');

  var adminMenuElem = userDetailTableElem.find('div#admin-menu');

  adminMenuElem.find('li a.grant-admin').html('Przyznaj uprawnienia administratora');
  adminMenuElem.find('li a.revoke-admin').html('Odbierz uprawnienia administratora');
  filterByTextRegex(adminMenuElem.find('li span.disabled'), /revoke administrator/i).html('Odbierz uprawnienia administratora').attr('title', 'Nie możesz sam sobie odebrać uprawnień administratora.');
  adminMenuElem.find('li a.grant-mod').html('Przyznaj uprawnienia moderatora');
  filterByTextRegex(adminMenuElem.find('li span.disabled'), /grant moderator/i).html('Przyznaj uprawnienia moderatora').attr('title', 'Ten użytkownik jest administratorem.');
  adminMenuElem.find('li a.revoke-mod').html('Odbierz uprawnienia moderatora');
  adminMenuElem.find('li a.toggle-admin').html('Anuluj');

  var moderatorActionsElem = userDetailTableElem.find('div#moderator-actions');

  moderatorActionsElem.find('th').eq(0).html('Informacje');
  moderatorActionsElem.find('th').eq(1).html('Akcje');

  var moderatorActionsLinksElems = moderatorActionsElem.find('td a');

  // info side
  filterByTextRegex(moderatorActionsLinksElems, /cancel/i).html('Anuluj');
  filterByAttrRegex(moderatorActionsLinksElems, 'href', /^\/users\/history/i).html('Historia');
  filterByAttrRegex(moderatorActionsLinksElems, 'href', /^\/admin\/show-user-ips/i).html('Numery IP');
  filterByAttrRegex(moderatorActionsLinksElems, 'href', /^\/admin\/xref-user-ips/i).html('Numery IP - xref');
  filterByAttrRegex(moderatorActionsLinksElems, 'href', /^\/admin\/show-user-votes/i).html('Głosy');

  // actions side
  filterByAttrRegex(moderatorActionsLinksElems, 'onclick', /annotateUser/i).html('Dodaj adnotację')
    .click(function() {
      moderatorActionsElem.find('div h2').eq(0).html('Wpisz adnotację do tego użytkownika');
      moderatorActionsElem.find('div a.flag-cancel').eq(0).html('Anuluj');

      var localizeTextUnderTextAreaFunc = function() {
        // TODO: shouldn't we intercept a call to updateTextCounter() here?
        moderatorActionsElem.find('div span.text-counter').eq(0).html('Wprowadź przynajmniej 10 znaków');
      };

      localizeTextUnderTextAreaFunc();

      moderatorActionsElem.find('div textarea').eq(0)
        .bind('focus', localizeTextUnderTextAreaFunc)
        .bind('blur', localizeTextUnderTextAreaFunc);
    });
  filterByTextRegex(moderatorActionsElem.find('li span'), /delete/i).html('Usuń').attr('title', 'Nie możesz usuwać administratorów i moderatorów. Najpierw odbierz im uprawnienia.');
  filterByTextRegex(moderatorActionsElem.find('li span'), /destroy/i).html('Zniszcz').attr('title', 'Nie możesz usuwać administratorów i moderatorów. Najpierw odbierz im uprawnienia.');
  filterByAttrRegex(moderatorActionsLinksElems, 'onclick', /recalcRep/i).html('Przelicz reputację');
  filterByAttrRegex(moderatorActionsLinksElems, 'onclick', /penalizeUser/i).html('Zawieś konto');

  // user-details table
  var userDetailsTableElem = userDetailTableElem.find('table.user-details');

  $.each(userDetailsTableElem.children('tbody').children('tr'), function() {
    var rowElem = $(this);
    var firstCellElem = rowElem.children('td').eq(0);
    var secondCellElem = firstCellElem.next();
    var fieldName = trim(firstCellElem.text().toLowerCase());
    var newFieldName = null;

    switch (fieldName) {
      case 'name':
        newFieldName = 'Nazwa użytkownika';
        break;
      case 'member for':
        newFieldName = 'Zarejestrowany od';
        secondCellElem.html(localizeRelativeTime(secondCellElem.text()));
        break;
      case 'seen':
        newFieldName = 'Ostatnio widziany';
        break;
      case 'website':
        newFieldName = 'Strona internetowa';
        break;
      case 'email':
        newFieldName = 'Adres e-mail';
        break;
      case 'real name':
        newFieldName = 'Imię i nazwisko';
        break;
      case 'location':
        newFieldName = 'Lokalizacja';
        break;
      case 'age':
        newFieldName = 'Wiek';
        break;
      default:
        break;
    }

    if (newFieldName != null) {
      firstCellElem.html(newFieldName);
    }
  });

  // user category
  var userCategoryElem = userDetailsTableElem.prevAll('h2').eq(0);

  localizeUserCategoryElem(userCategoryElem);

  // last activity
  var lastActivityElem = userDetailTableElem.find('td:last .summaryinfo');
  var lastActivityElemTextNodes = getChildTextNodes(lastActivityElem);

  if (lastActivityElemTextNodes.length == 1) { // community user
    $(lastActivityElemTextNodes[0]).replaceWith(getNodeTextContent(lastActivityElemTextNodes[0]).replace(/last activity: /i, 'Ostatnia aktywność: ').replace(/from/i, 'z'));
  }
  else if (lastActivityElemTextNodes.length > 1) {
    $(lastActivityElemTextNodes[0]).replaceWith('Ostatnia aktywność: ');

    var lastActivityElemLastRawTextNode = lastActivityElemTextNodes[lastActivityElemTextNodes.length - 1];

    $(lastActivityElemLastRawTextNode).replaceWith(getNodeTextContent(lastActivityElemLastRawTextNode).replace(/from/, 'z'));
  }

  // tabs
  var tabsElems = $('#mainbar-full table.user-detail').nextAll('#subheader').find('#tabs a');
  var userName = trim($('#mainbar-full #subheader h1').eq(0).text());
  
  if (g_currentUserName == userName) {
    // we're on our user page
    
    tabsElems.eq(0).html('statsy').attr('title', 'Twoje ogólne statystyki');
    tabsElems.eq(1).html('ostatnie').attr('title', 'Twoja ostatnia aktywność');
    tabsElems.eq(2).html('reputacja').attr('title', 'Historia Twojej reputacji');
    tabsElems.eq(3).html('ulubione').attr('title', 'Pytania, które oznaczyłeś jako ulubione');
    tabsElems.eq(4).html('głosy').attr('title', 'Ostatnio oddane przez Ciebie głosy');
    tabsElems.eq(5).html('preferencje').attr('title', 'Twoje preferencje');
  }
  else {
    // we're on some other user's page
    
    tabsElems.eq(0).html('statsy').attr('title', 'Ogólne statystyki tego użytkownika');
    tabsElems.eq(1).html('ostatnie').attr('title', 'Ostatnia aktywność tego użytkownika');
    tabsElems.eq(2).html('reputacja').attr('title', 'Historia reputacji tego użytkownika');
    tabsElems.eq(3).html('ulubione').attr('title', 'Pytania, które ten użytkownik dodał do ulubionych');
    
    if (g_isCurrentUserModerator) {
      tabsElems.eq(4).html('głosy').attr('title', 'Ostatnio oddane przez tego użytkownika głosy');
      tabsElems.eq(5).html('preferencje').attr('title', 'Preferencje tego użytkownika');
    }
  }

  var queryString = window.location.search;

  if (queryString.match(/\?tab=recent/i) != null) { // recent tab
    var historyTable = $('#mainbar-full table.history-table');

    localizeDatesInHistoryTable(historyTable);
    
    // nothing to report text
    filterByTextRegex(historyTable.find('tr > td > b'), /nothing to report\./i).html('Brak danych do wyświetlenia.');

    $.each($('tr', historyTable), function() {
      var rowElem = $(this);
      var cellElem = rowElem.children('td').eq(1);

      switch (trim(cellElem.text().toLowerCase())) {
        case 'asked': cellElem.html('<span class="recent-action-asked">zapytał</span>'); break;
        case 'answered': cellElem.html('<span class="recent-action-answered">odpowiedział</span>'); break;
        case 'awarded': cellElem.html('<span class="recent-action-awarded">przyznano</span>'); break;
        case 'revised': cellElem.html('<span class="recent-action-revised">poprawił</span>'); break;
        case 'accepted': cellElem.html('<span class="recent-action-accepted">zaakceptowano</span>'); break;
        case 'comment': cellElem.html('<span class="recent-action-comment">skomentował</span>'); break;
        default: break;
      }
    });

    $.each($('td a.badge', historyTable), function() {
      localizeBadgeElement($(this), false);
    });
  }
  else if (queryString.match(/\?tab=reputationhistory/i) != null) { // reputation history tab
    var dateSelectionElem = $('#date-selection');

    $('#mainbar-full div > span[title^="click graph"]').eq(0).attr('title', 'Kliknij wykres lub użyj formularza poniżej.');

    var textNodes = getChildTextNodes(dateSelectionElem);

    if (textNodes.length > 0) {
      $(textNodes[0]).replaceWith('Kliknij wykres lub wprowadź datę początkową: ');
    }

    if (textNodes.length > 1) {
      $(textNodes[1]).replaceWith(' i końcową: ');
    }

    dateSelectionElem.find('input[type="button"]').eq(0).val('Ustaw');
  }
  else if (queryString.match(/\?tab=favorites/i) != null) { // favorites tab

  }
  else if (queryString.match(/\?tab=votes/i) != null) { // votes tab
    var historyTable = $('#mainbar-full table.history-table');

    localizeDatesInHistoryTable(historyTable);
    
    // nothing to report text
    filterByTextRegex(historyTable.find('tr > td > b'), /nothing to report\./i).html('Brak danych do wyświetlenia.');
  }
  else if (queryString.match(/\?tab=preferences/i) != null) { // preferences tab
    var prefsElem = $('#mainbar-full div.prefs').eq(0);

    // headers
    $.each(prefsElem.find('div.module > h4'), function() {
      var headerElem = $(this);
      var headerText = headerElem.text();

      if (headerText.match(/interesting tags/i) != null) {
        headerElem.html('Interesujące tagi');
      }
      else if (headerText.match(/ignored tags/i) != null) {
        headerElem.html('Ignorowane tagi');
      }
      else if (headerText.match(/miscellaneous/i) != null) {
        headerElem.html('Różne');
      }
    });

    // buttons
    prefsElem.find('input[type="button"][value="Add"]').val('Dodaj');

    // checkboxes
    var hideIgnoredTagsLabelElem = prefsElem.find('input#hideIgnored[type="checkbox"]')
      .attr('title', 'Ukrywaj ignorowane tagi.')
      .next('label');
      
    replaceLabelText(hideIgnoredTagsLabelElem, ' Ukrywaj ignorowane tagi');

    var emailNotificationsLabelElem = prefsElem.find('input#optInEmail[type="checkbox"]')
      .attr('title', 'Wpisz się na listę mailingową.')
      .next('label');
      
    replaceLabelText(emailNotificationsLabelElem, ' Chcę otrzymywać powiadomienia e-mailowe o aktywności w obrębie moich pytań i odpowiedzi');

  }
  else { // default or stats tab
    // questions
    var questionsTable = $('a[name="questions"]').next('table');
    var questionsCount = parseInt(questionsTable.find('tr > td').eq(0).find('.summarycount').text());

    questionsTable.find('tr > td > h1').eq(0).html(capitalizeFirstLetter(getProperQuestionsNumberForm(questionsCount)));
    
    localizeUserTabs(questionsTable.find('div.tabs-question-user'));

    // answers
    var answersTable = $('a[name="answers"]').next('table');
    var answersCount = parseInt(answersTable.find('tr > td').eq(0).find('.summarycount').text());

    answersTable.find('tr > td > h1').eq(0).html(capitalizeFirstLetter(getProperAnswersNumberForm(answersCount)));

    localizeUserTabs(answersTable.find('div.tabs-answer-user'));

    // votes
    var votesTable = $('a[name="votes"]').next('table');
    var votesCount = parseInt(votesTable.find('tr > td').eq(0).find('.summarycount').text());

    votesTable.find('tr > td > h1').eq(0).html(capitalizeFirstLetter(getProperVotesNumberForm(votesCount)));

    var votesStatsElem = votesTable.next('div.user-stats-table');

    votesStatsElem.find('table tr > td').eq(0).find('div.vote span.vote-count-post').attr('title', 'całkowita liczba pozytywnych głosów oddanych przez tego użytkownika');
    votesStatsElem.find('table tr > td').eq(1).find('div.vote span.vote-count-post').attr('title', 'całkowita liczba negatywnych głosów oddanych przez tego użytkownika');

    // tags
    var tagsTable = $('a[name="tags"]').next('table');
    var tagsCount = parseInt(tagsTable.find('tr > td').eq(0).find('.summarycount').text());

    tagsTable.find('tr > td > h1').eq(0).html(capitalizeFirstLetter(getProperTagsNumberForm(tagsCount)));

    // badges
    var badgesTable = $('a[name="badges"]').next('table');
    var badgesCount = parseInt(badgesTable.find('tr > td').eq(0).find('.summarycount').text());

    badgesTable.find('tr > td > h1').eq(0).html(capitalizeFirstLetter(getProperBadgesNumberForm(badgesCount)));

    var badgesElems = $('a.badge', badgesTable.next('div.user-stats-table'));

    $.each(badgesElems, function() {
      localizeBadgeElement($(this), false);
    });
  }
}

// user edit
function localizeUserEditPage() {
  var userEditTableElem = $('#user-edit-table');
  var userEditFormElem = userEditTableElem.find('#user-edit-form');

  // header
  var header = $('#mainbar-full #subheader h1').eq(0);

  header.html(header.text().replace(/^\s*([^-]+?)\s*-.*$/i, '$1 - Edycja'));

  // user category
  var userCategoryElem = userEditFormElem.prevAll('h2').eq(0);

  localizeUserCategoryElem(userCategoryElem);

  // gravatar
  filterByAttrRegex(userEditTableElem.find('a'), 'href', /^http:\/\/www\.gravatar\.com\/$/i)
    .html('zmień zdjęcie')
    .attr('title', 'Twoj gravatar jest powiązany z Twoim adresem e-mail.')
    .click(function() {
      userEditTableElem.find('#gravatar-info')
        .html('zmiana zdjęcia powinna być widoczna najpóźniej po 24 godzinach');
    });

  // data table
  var userTableElem = userEditFormElem.children('table');

  $.each(userTableElem.children('tbody').children('tr'), function() {
    var rowElem = $(this);
    var firstCellElem = rowElem.children('td').eq(0);
    var secondCellElem = firstCellElem.next();
    var fieldName = trim(firstCellElem.text().toLowerCase());
    var newFieldName = null;

    switch (fieldName) {
      case 'display name':
        newFieldName = 'Nazwa użytkownika';
        break;
      case 'openid':
        newFieldName = 'OpenId';
        break;
      case 'openid (alternate)':
        newFieldName = 'OpenId (alternatywne)';
        break;
      case 'website':
        newFieldName = 'Strona internetowa';
        break;
      case 'email':
        newFieldName = 'Adres e-mail';
        secondCellElem.find('div.form-item-info').eq(0).html('nigdy nie wyświetlany; opcjonalne powiadomienia; gravatar');
        break;
      case 'real name':
        newFieldName = 'Imię i nazwisko';
        break;
      case 'location':
        newFieldName = 'Lokalizacja';
        break;
      case 'birthday':
        newFieldName = 'Data urodzenia';
        secondCellElem.find('div.form-item-info').eq(0).html('nigdy nie wyświetlana; używana do wyznaczenia wieku');
        break;
      case 'about me':
        newFieldName = 'O mnie';
        secondCellElem.find('div.form-item-info').eq(0).html('dozwolony jest <a target="_blank" href="http://' + g_SiteDoman + '/basic-html">prosty HTML</a>');
        break;
      default:
        break;
    }

    if (newFieldName != null) {
      firstCellElem.html(newFieldName);
    }
  });

  // buttons
  var formSubmitElem = userEditFormElem.find('div.form-submit');

  formSubmitElem.find('input[type="submit"][value="Save Profile"]').val('Zapisz profil');
  formSubmitElem.find('input[type="button"][value="Cancel"]').val('Anuluj');
}

function localizeUsersPage() {
  // header
  $('#mainbar-full #subheader h2').eq(0).html('Użytkownicy');

  // tabs
  var tabsElems = $('#mainbar-full #subheader #tabs a');

  tabsElems.eq(0).html('reputacja').attr('title', 'Użytkownicy z najwyższą reputacją');
  tabsElems.eq(1).html('najnowsi').attr('title', 'Ostatnio zarejestrowani użytkownicy');
  tabsElems.eq(2).html('najstarsi').attr('title', 'Użytkownicy z najdłuższym stażem');
  tabsElems.eq(3).html('nazwa').attr('title', 'Użytkownicy w porządku alfabetycznym według nazwy');

  // user filter label
  $('div.page-description input#userfilter[type="text"]').closest('tr')
    .children('td').eq(0).html('Zacznij pisać, aby znaleźć użytkowników:');
}

function localizeRecentActivityBar(recentActivitySelector) {
  $.each(recentActivitySelector.children('a'), function() {
    var aElem = $(this);
    
    switch (trim(aElem.text().toLowerCase())) {
      case 'last month': aElem.html('zeszły miesiąc'); break;
      case 'this month': aElem.html('ten miesiąc'); break;
      case 'last week': aElem.html('zeszły tydzień'); break;
      case 'this week': aElem.html('ten tydzień'); break;
      case 'yesterday': aElem.html('wczoraj'); break;
      case 'today': aElem.html('dzisiaj'); break;
      default: break;
    }
  });
}

function localizeTimeSpanBar(barSelector) {
  var match = barSelector.text().match(/showing ([0-9-]+) to ([0-9-]+) ; current time is ([0-9-]+ [0-9:]+( UTC)?)/i);
  
  if (match == null) {
    return;
  }
  
  var startDate = localizeDateTimeFormat(match[1]);
  var endDate = localizeDateTimeFormat(match[2]);
  var currentTime = localizeDateTimeFormat(match[3]);
  
  barSelector.html('Zakres: od ' + startDate + ' do ' + endDate + '; aktualny czas: ' + currentTime);
}

function localizeUserRecentPage() {
  // header
  $('#mainbar-full #subheader h1').eq(0).html('Ostatnia aktywność');
  
  // tabs
  var tabsElems = $('#mainbar-full #subheader #tabs a');

  tabsElems.eq(0).html('podsumowanie').attr('title', 'Podsumowanie');
  tabsElems.eq(1).html('reputacja').attr('title', 'Zmiany w Twojej reputacji');
  tabsElems.eq(2).html('odpowiedzi').attr('title', 'Ostatnie odpowiedzi na Twoje wpisy');
  tabsElems.eq(3).html('rewizje').attr('title', 'Rewizje Twoich wpisów');
  tabsElems.eq(4).html('odznaki').attr('title', 'Zdobyte przez Ciebie odznaki');
  
  // recent activity bar
  var recentActivityElem = $('#content div.recent-activity');
  
  localizeRecentActivityBar(recentActivityElem);
  
  // nothing to report text
  filterByTextRegex($('#content table.history-table tr > td > b'), /nothing to report\./i).html('Brak aktywności w tym okresie.');
  
  // tabs contents
  var queryString = window.location.search;
  
  if (queryString.match(/tab=reputation/i) != null) { // reputation tab
    var historyTable = recentActivityElem.next('table.history-table');

    localizeAccInHistoryTable(historyTable);
  }
  else if (queryString.match(/tab=responses/i) != null) { // responses tab
    var historyTable = recentActivityElem.next('table.history-table');
    
    localizeDatesInHistoryTable(historyTable);
    localizeEventTypesInHistoryTable(historyTable);    
  }
  else if (queryString.match(/tab=revisions/i) != null) { // revisions tab
    var historyTable = recentActivityElem.next('table.history-table');
    
    localizeDatesInHistoryTable(historyTable);
  }
  else if (queryString.match(/tab=badges/i) != null) { // badges tab
    var historyTable = recentActivityElem.next('table.history-table');
    
    // dates
    localizeDatesInHistoryTable(historyTable);
    
    // 'awarded' cells
    $.each(historyTable.find('tr'), function() {
      var secondCellElem = $(this).children('td').eq(1);
      var secondCellText = secondCellElem.text();
      
      switch (trim(secondCellText.toLowerCase())) {
        case 'awarded': secondCellElem.html('przyznano'); break;
        default: break;
      }
    });
    
    // badges
    $.each(historyTable.find('td a.badge'), function() {
      localizeBadgeElement($(this), false);
    });
  }
  else { // summary or default tab
    // time span bar
    localizeTimeSpanBar($('#content div.recent-activity').next('h3'));
    
    // stats div
    var statsDivElem = $('#content div.stats-div').eq(0);
    
    $.each(statsDivElem.find('td.stat-summary'), function() {
      var cellElem = $(this);
      
      switch (trim(cellElem.text().toLowerCase())) {
        case 'questions': cellElem.html('Zadane pytania'); break;
        case 'answer responses': cellElem.html('Otrzymane odpowiedzi'); break;
        case 'answers': cellElem.html('Udzielone odpowiedzi'); break;
        case 'comment responses': cellElem.html('Otrzymane komentarze'); break;
        case 'comments': cellElem.html('Wystawione komentarze'); break;
        case 'edits to your posts': cellElem.html('Zmiany Twoich wpisów'); break;
        case 'reputation earned': cellElem.html('Zdobyta reputacja'); break;
        case 'badges achieved': cellElem.html('Zdobyte odznaki'); break;
        default: break;
      }
    });
    
    // top 5 posts
    var topFivePostsHeaderElem = filterByTextRegex(statsDivElem.nextAll('h2'), /top 5 posts/i).eq(0);
    var topFivePostsHistoryTableElem = topFivePostsHeaderElem.html('5 najlepszych wpisów')
      .next('table.history-table');
      
    localizeDatesInHistoryTable(topFivePostsHistoryTableElem);
    localizeAccInHistoryTable(topFivePostsHistoryTableElem);
    
    // most recent responses
    var mostRecentResponsesHeaderElem = filterByTextRegex(statsDivElem.nextAll('h2'), /most recent responses/i).eq(0);
    var mostRecentResponsesHistoryTableElem = mostRecentResponsesHeaderElem.html('Ostatnio otrzymane odpowiedzi')
      .next('table.history-table');
      
    localizeDatesInHistoryTable(mostRecentResponsesHistoryTableElem);
    localizeEventTypesInHistoryTable(mostRecentResponsesHistoryTableElem);
  }
}

function getLocalizedCloseReason(closeReason) {
  var closeReasonLower = trim(closeReason.toLowerCase());
  
  switch (closeReasonLower) {
    case 'exact duplicate': return 'duplikat'; break;
    case 'off topic': return 'nie na temat'; break;
    case 'subjective and argumentative': return 'subiektywny i sporny'; break;
    case 'not a real question': return 'nie pytanie'; break;
    case 'blatantly offensive': return 'rażąco obraźliwy'; break;
    case 'no longer relevant': return 'już nieistotne'; break;
    case 'too localized': return 'zbyt ograniczone'; break;
    case 'spam': return 'spam'; break;
    default: break;
  }
  
  return closeReason;
}

// badges
function getLocalizedBadgeName(badgeName) {
  var badgeNameLower = trim(badgeName.toLowerCase());

  switch (badgeNameLower) {
    case 'autobiographer':
      return 'Autobiograf';
    case 'citizen patrol':
    case 'citizen-patrol':
      return 'Obywatelski patrol';
    case 'civic duty':
    case 'civic-duty':
      return 'Służba obywatelska';
    case 'cleanup':
      return 'Czystka';
    case 'commentator':
      return 'Komentator';
    case 'critic':
      return 'Krytyk';
    case 'disciplined':
      return 'Zdyscyplinowany';
    case 'editor':
      return 'Edytor';
    case 'enlightened':
      return 'Oświecony';
    case 'enthusiast':
      return 'Entuzjasta';
    case 'epic':
      return 'Imponujący';
    case 'famous question':
    case 'famous-question':
      return 'Słynne pytanie';
    case 'fanatic':
      return 'Fanatyk';
    case 'favorite question':
    case 'favorite-question':
      return 'Ulubione pytanie';
    case 'generalist':
      return 'Wszechstronny';
    case 'good answer':
    case 'good-answer':
      return 'Dobra odpowiedź';
    case 'good question':
    case 'good-question':
      return 'Dobre pytanie';
    case 'great answer':
    case 'great-answer':
      return 'Doskonała odpowiedź';
    case 'great question':
    case 'great-question':
      return 'Doskonałe pytanie';
    case 'guru':
      return 'Guru';
    case 'legendary':
      return 'Legendarny';
    case 'mortarboard':
      return 'Zasłużony';
    case 'necromancer':
      return 'Nekromanta';
    case 'nice answer':
    case 'nice-answer':
      return 'Niezła odpowiedź';
    case 'nice question':
    case 'nice-question':
      return 'Niezłe pytanie';
    case 'notable question':
    case 'notable-question':
      return 'Znakomite pytanie';
    case 'organizer':
      return 'Organizator';
    case 'peer pressure':
    case 'peer-pressure':
      return 'Presja rówieśnicza';
    case 'popular question':
    case 'popular-question':
      return 'Popularne pytanie';
    case 'populist':
      return 'Populista';
    case 'pundit':
      return 'Mędrzec';
    case 'reversal':
      return 'Radykalna zmiana';
    case 'scholar':
      return 'Naukowiec';
    case 'self-learner':
      return 'Samouk';
    case 'stellar question':
    case 'stellar-question':
      return 'Gwiazdorskie pytanie';
    case 'strunk & white':
    case 'strunk-white':
      return 'Strunk & White';
    case 'student':
      return 'Uczeń';
    case 'supporter':
      return 'Poplecznik';
    case 'taxonomist':
      return 'Taksonomista';
    case 'teacher':
      return 'Nauczyciel';
    case 'tumbleweed':
      return 'Biegacz stepowy';
    case 'yearling':
      return 'Roczniak';
    default:
      break;
  }

  return badgeName;
}

// edit post
function localizeEditPostPage() {
  // header
  var headerElem = $('#content #subheader h2.form-title').eq(0);
  var headerHtml = headerElem.html();
  
  if (headerHtml != null) {
    headerElem.html(
      headerHtml    
      .replace(/^edit/i, 'Edycja')
      .replace(/return to question/i, 'Wróć do pytania')
      .replace(/return to answer/i, 'Wróć do odpowiedzi'));
  }

  // revisions
  var revisionsListElem = $('#mainbar > div.form-item > select#revisions-list').eq(0);
  
  if (revisionsListElem.length > 0) {
    replaceLabelText(revisionsListElem.prevAll('label').eq(0), 'Rewizja:');
    
    revisionsListElem.children('option').each(function() {
      var revOptionElem = $(this);
      var revOptionText = revOptionElem.text();
      var newRevOptionText = revOptionText;
      var revOptionMatch = null;
      
      newRevOptionText = newRevOptionText.replace(/^([^\(]+\s+\()([^\)]+)/i, function(s, p1, p2) {
        return p1 + localizeRelativeTime(p2);
      });
      
      newRevOptionText = localizeRevisionComment(newRevOptionText);
      
      revOptionElem.text(newRevOptionText);
    });
  }
      
  // post editor
  localizePostEditor();
  
  // post form
  var postFormElem = $('#content form#post-form');
  
  localizePostFormTitle(postFormElem);
  localizePostFormTags(postFormElem);
  localizePostFormEditSummary(postFormElem);
  
  // submit button
  postFormElem.find('div.form-submit input#submit-button[type="submit"]').eq(0).val('Zapisz zmiany');
  
  // formatting reference
  localizeSidebarFormattingReference();
  
  // revision edit warning
  localizeSidebarRevisionEditWarning();
  
  // good edits
  localizeSidebarGoodEdits();
}

// revisions list
function localizeRevisionsListPage() {
  // header
  var headerElem = $('#content #mainbar-full #subheader h2').eq(0);
  
  headerElem.html(
    headerElem.html()
      .replace(/return to question/i, 'Wróć do pytania')
      .replace(/return to answer/i, 'Wróć do odpowiedzi'));
      
  // revisions table
  var revisionsTable = $('#content #mainbar-full #revisions table');
  
  revisionsTable.find('td.revcell1 img[id^="rev-arrow"]').attr('title', 'pokaż/ukryj tę rewizję');
  
  // vote revisions
  $.each(revisionsTable.find('tr.vote-revision td.revcell3'), function() {
    var voteRevCell = $(this);
    var voteRevActionElem = voteRevCell.children('b').eq(0);
    var textRawNode = null;
    var voteRevMatch = null;
    
    if (voteRevActionElem.length > 0) {
      var voteRevActionRawElem = voteRevCell.children('b')[0];
      
      switch (trim(voteRevActionElem.text().toLowerCase())) {
        case 'post closed':
          voteRevActionElem.html('Wpis zamknięty');
          textRawNode = voteRevActionRawElem.nextSibling;
          
          if (typeof(textRawNode) != 'undefined' && textRawNode != undefined && textRawNode != null && textRawNode.nodeType == g_NodeType_Text) {
            voteRevMatch = getNodeTextContent(textRawNode).match(/as\s+"([^"]+)"\s+by/i);
            
            if (voteRevMatch != null) {
              $(textRawNode).replaceWith(' jako "' + getLocalizedCloseReason(voteRevMatch[1]) + '" przez '); break;
            }
          }

        case 'post reopened':
          voteRevActionElem.html('Wpis otwarty');
          textRawNode = voteRevActionRawElem.nextSibling;
          
          if (typeof(textRawNode) != 'undefined' && textRawNode != undefined && textRawNode != null && textRawNode.nodeType == g_NodeType_Text) {
            voteRevMatch = getNodeTextContent(textRawNode).match(/\s*by\s*/i);
            
            if (voteRevMatch != null) {
              $(textRawNode).replaceWith(' przez '); break;
            }
          }

        case 'post made community wiki':
          voteRevActionElem.html('Wpis przeniesiony do społecznościowego wiki');
          textRawNode = voteRevActionRawElem.nextSibling;
          
          if (typeof(textRawNode) != 'undefined' && textRawNode != undefined && textRawNode != null && textRawNode.nodeType == g_NodeType_Text) {
            voteRevMatch = getNodeTextContent(textRawNode).match(/\s*by\s*/i);
            
            if (voteRevMatch != null) {
              $(textRawNode).replaceWith(' przez '); break;
            }
          }

        case 'post locked':
          voteRevActionElem.html('Wpis zablokowany');
          textRawNode = voteRevActionRawElem.nextSibling;
          
          if (typeof(textRawNode) != 'undefined' && textRawNode != undefined && textRawNode != null && textRawNode.nodeType == g_NodeType_Text) {
            voteRevMatch = getNodeTextContent(textRawNode).match(/\s*by\s*/i);
            
            if (voteRevMatch != null) {
              $(textRawNode).replaceWith(' przez '); break;
            }
          }

        case 'post unlocked':
          voteRevActionElem.html('Wpis odblokowany');
          textRawNode = voteRevActionRawElem.nextSibling;
          
          if (typeof(textRawNode) != 'undefined' && textRawNode != undefined && textRawNode != null && textRawNode.nodeType == g_NodeType_Text) {
            voteRevMatch = getNodeTextContent(textRawNode).match(/\s*by\s*/i);
            
            if (voteRevMatch != null) {
              $(textRawNode).replaceWith(' przez '); break;
            }
          }
          
        default: break;
      }
    }
  });
  
  // context menus
  $.each(revisionsTable.find('td.revcell3 > div > a'), function() {
    var menuLinkElem = $(this);
    var menuLinkText = trim(menuLinkElem.text().toLowerCase());
    
    switch (menuLinkText) {
      case 'view source': menuLinkElem.html('zobacz źródło'); menuLinkElem.attr('title', 'zobacz tę rewizję w postaci zwykłego tekstu'); break;
      case 'edit': menuLinkElem.html('edytuj'); menuLinkElem.attr('title', 'edytuj tę rewizję'); break;
      case 'rollback': menuLinkElem.html('przywróć'); menuLinkElem.attr('title', 'ustaw tę rewizję jako aktualną, usuwając przy tym nieprawidłowe głosy'); break;
      default: break;
    }
  });
}

// bootstrap
function localizeBootstrapPage() {
  $('#subheader h2').html('Poradnik trybu rozruchowego');

  $('#bootstrap-welcome').html('Witajcie w serwisie devPytania! Poniżej znajdują się metody, według których możesz pomóc rozwijać serwis:');
  
  var $bootstrapUsers = $('#bootstrap-users');
  $('h2', $bootstrapUsers).eq(0).html('Zapraszaj innych ludzi');
  $('.bootstrap-section p', $bootstrapUsers).eq(0).html('Bezpośrednio zapraszaj ludzi, aby zaczęli udzielać się w serwisie. Głosuj na ich dobre pytania bądź odpowiedzi, aby zdobyli trochę reputacji.');
  $('td.label', $bootstrapUsers).eq(0).html('Zarejestrowanych');
  $('td.label', $bootstrapUsers).eq(1).html('Aktywnych');
  $('div.progress-bar', $bootstrapUsers).eq(0).attr('title', 'Liczba zarejestrowanych użytkowników');
  $('div.progress-bar', $bootstrapUsers).eq(1).attr('title', 'Liczba użytkowników ze 100 bądź więcej punktami reputacji');
  $('p.bootstrap-tip', $bootstrapUsers).eq(0).html('Aktywni użytkownicy mają 100 lub więcej punktów reputacji.');

  var $bootstrapQuestions = $('#bootstrap-questions');
  $('h2', $bootstrapQuestions).eq(0).html('Zadawaj pytania');
  $('.bootstrap-section p', $bootstrapQuestions).eq(0).html('<a href="/questions/ask">Zadawaj jakieś pytania</a>, aby zapełnić stronę wartościową treścią i pokazać nowym użytkownikom, jak to działa.');
  $('td.label', $bootstrapQuestions).eq(0).html('Zadanych pytań');
  $('td.label', $bootstrapQuestions).eq(1).html('Pytań z odpowiedzią');
  $('div.progress-bar', $bootstrapQuestions).eq(0).attr('title', 'Liczba zadanych pytań');
  $('div.progress-bar', $bootstrapQuestions).eq(1).attr('title', 'Liczba pytań mających odpowiedzi z przynajmniej jednym głosem');

  var $bootstrapTags = $('#bootstrap-tags');
  $('h2', $bootstrapTags).eq(0).html('Twórz tagi');
  $('.bootstrap-section p', $bootstrapTags).eq(0).html('Nadawaj tagi istniejącym pytaniom bądź <a href="/questions/ask">zadawaj nowe</a>, aby tworzyć tagi, które mogą być później wykorzystywane.');
  $('td.label', $bootstrapTags).eq(0).html('Stworzonych tagów');
  $('div.progress-bar', $bootstrapTags).eq(0).attr('title', 'Liczba tagów');

  var $bootstrapLaunch = $('#bootstrap-launch');
  $('h2', $bootstrapLaunch).eq(0).html('Wystartuj!');
  $('.bootstrap-section p', $bootstrapLaunch).eq(0).html('Kiedy strona będzie gotowa, administratorzy zakończą tryb rozruchowy i ruszą z serwisem na całego!');

  // sidebar module
  var $bootstrapDetailsModule = $('#bootstrap-details-module');
  $('p', $bootstrapDetailsModule).eq(0).html('<strong>Tryb rozruchowy</strong> pomaga ukształtować społeczność, zanim strona zostanie udostępniona szerszej grupie odbiorców.');
  $('p', $bootstrapDetailsModule).eq(1).html('<strong>Wymagania co do reputacji są mniej restrykcyjne</strong> podczas trybu rozruchowego. Wszyscy użytkownicy mogą:');
  var $listItems = $('ul li', $bootstrapDetailsModule);
  $listItems.eq(0).html('Zadawać pytania');
  $listItems.eq(1).html('Odpowiadać');
  $listItems.eq(2).html('Komentować');
  $listItems.eq(3).html('Tworzyć tagi');
  $listItems.eq(4).html('Zmieniać tagi pytań');
  $listItems.eq(5).html('Głosować');
  $('p', $bootstrapDetailsModule).eq(2).html('Będziesz zdobywał punkty reputacji w sposób normalny, ale ich brak nie spowoduje zablokowana czesci funkcjonalnosci serwisu.');
}

// login
function localizeLoginPage() {
  var queryString = window.location.search;

  $('#tabs a').eq(0).html('email oraz hasło');
  $('#tabs a').eq(0).attr('title', 'Zaloguj się za pomocą adresu email oraz hasła');
  $('#tabs a').eq(1).html('openid');
  $('#tabs a').eq(1).attr('title', 'Zaloguj się za pomocą OpenID');

  if (queryString.match(/\?provider=openid/i) != null) {
    $('#subheader h2').html('Zaloguj się za pomocą OpenID');

    $('#openid_form p').eq(0).html('Wybierz swojego dostawcę <a href="http://openid.net/what/">OpenID</a>:');

    var localizeOpenIDForm = function() {
      $(this).removeAttr("href");
      openid.signin($(this).attr("title").toLowerCase());
      localizeOpenIDInputArea($(this).attr("title"));
    }

    var localizeOpenIDInputArea = function(providerName) {
      var $openIDInputArea = $('#openid_input_area');
      $('p:eq(0)', $openIDInputArea).text("Twoja nazwa użytkownika " + providerName + ".");
      $('input#openid_submit', $openIDInputArea).attr("value", "Zarejestruj się");
    }
    
    $.each(['aol', 'myopenid', 'openid_small_btn'], function() {
      $('#openid_btns a.' + this).click(localizeOpenIDForm);
    });

    $('#openid_form p:last').html('Albo, ręcznie wprowadź URL dla OpenID:');
    $('#submit-button').attr('value', 'Zaloguj');

    $('#openid-help h4:contains("Why OpenID?")').text("Dlaczego OpenID?");
    $('#openid-help p:eq(0)').text("To pojedyncza nazwa użytkownika i hasło, które pozwalają na logowanie się do dowolnego serwisu wspierającego OpenID.");
    $('#openid-help p:eq(1)').text("Jest wspierane przez tysiące serwisów internetowych.");
    $('#openid-help p:eq(2)').text("Jest otwartym standardem.");
    $('#openid-help p:eq(3) > a:eq(0)').text("więcej »");
    $('#openid-help p:eq(3) > a:eq(1)').text("zdobądź »");

    $('#openid-delegate-help h4:contains("Use your own URL")').text("Używaj własnego URLa");
    $('#openid-delegate-help p:eq(0)').html("Chcesz dodać wsparcie dla OpenID do <i>swojej</i> strony?");
    $('#openid-delegate-help p:eq(1)').text("To tak proste jak dodanie dwóch HTMLowych nagłówków!");
    $('#openid-delegate-help p:eq(2) > a:eq(0)').text("zobacz jak »");
  }
  else if (queryString.match(/\?provider=email/i) != null || queryString.match(/\?provider/i) == null) {
    $('#subheader h2').html('Zaloguj się za pomocą adresu email oraz hasła');
    $('#mainbar label:eq(0) + span a').html('bądź zaloguj się za pomocą OpenID');
    $('#mainbar label').eq(1).html('Hasło:');
    $('#submit-button').attr('value', 'Zaloguj');
    $('#account-recovery').html('Zapomniałeś hasła?');
    $('#register-link a').html('Załóż nowe konto');
    $('#login-help h2').html('Nie masz konta?');
    $('#login-help p').eq(0).html('Załóż darmowe konto, aby zdobywać odznaki oraz reputację.');
    $('#login-help p').eq(1).html('Nie musisz się rejestrować, aby zadawać pytania bądź na nie odpowiadać.');
    $('#login-help p a').html('Załóż nowe konto »');
    $('#recovery-actions h4').html('Odzyskiwanie konta');
    $('#recovery-actions p').html('Wprowadź swój adres email, a my wyślemy Ci wiadomość, która pomoże w odzyskaniu Twojego konta.');
    $('#recover-it').attr('value', 'Odzyskaj!');
  }
}

// logout
function localizeLogoutPage() {
  $('#subheader h2').html('Wyloguj się');
  $('#content .page-description p').eq(0).html("Jesteś <span class='revision-comment'>zarejestrowanym</span> użytkownikiem.");
  $('#content .page-description p').eq(1).html('Możesz zalogować się kiedy tylko chcesz, używając identyfikatora, który został przypisany do Twojego konta.');
  $('#logout-user input[type="submit"]').attr('value', 'Wyloguj się');
}

// register
function localizeRegisterPage() {
  $('#subheader h2').html('Załóż nowe konto');
  $('#password_form label').eq(0).html('Nazwa wyświetlana');
  $('#password_form label').eq(2).html('Hasło');
  $('#password_form label').eq(3).html('Hasło (jeszcze raz)');
  $('#submit-button').attr('value', 'Zarejestruj');
  $('#password_form p.note a').html('Zarejestruj się z użyciem OpenID');

  $('#register-help h2').html('Nie musisz się rejestrować, żeby się udzielać');
  $('#register-help p').eq(0).html('Możesz zadawać pytania oraz na nie odpowiadać do woli.');
  $('#register-help p').eq(1).html('Niemniej jednak są <a href="/faq#reputation">pewne rzeczy</a>, których nie będziesz mógł robić bez rejestracji.');
}

function getLocalizedBadgeDescription(badgeName) {
  var badgeNameLower = trim(badgeName.toLowerCase());

  switch (badgeNameLower) {
    case 'autobiographer':
      return 'Wypełnił wszystkie pola profilu użytkownika';
    case 'citizen patrol':
    case 'citizen-patrol':
      return 'Po raz pierwszy oznaczył treść jako nieodpowiednią';
    case 'civic duty':
    case 'civic-duty':
      return 'Oddał 300 głosów';
    case 'cleanup':
      return 'Po raz pierwszy wycofał czyjeś zmiany';
    case 'commentator':
      return 'Napisał 10 komentarzy';
    case 'critic':
      return 'Oddał pierwszy głos negatywny';
    case 'disciplined':
      return 'Usunął własny wpis z co najmniej 3 pozytywnymi głosami';
    case 'editor':
      return 'Dokonał pierwszej edycji';
    case 'enlightened':
      return 'Zaakceptował pierwszą odpowiedź na swoje pytanie z co najmniej 10 pozytywnymi głosami';
    case 'enthusiast':
      return 'Odwiedzał serwis codziennie przez 30 kolejnych dni';
    case 'epic':
      return 'Osiągał dzienny limit na zdobywaną reputację przez 50 dni';
    case 'famous question':
    case 'famous-question':
      return 'Zadał pytanie, które zostało wyświetlone 10 000 razy';
    case 'fanatic':
      return 'Odwiedzał serwis codziennie przez 100 kolejnych dni';
    case 'favorite question':
    case 'favorite-question':
      return 'Zadał pytanie, które zostało dodane do ulubionych przez 25 użytkowników';
    case 'generalist':
      return 'Aktywnie udzielał się w pytaniach dla wielu różnych tagów';
    case 'good answer':
    case 'good-answer':
      return 'Udzielił odpowiedzi, która uzyskała 25 pozytywnych głosów';
    case 'good question':
    case 'good-question':
      return 'Zadał pytanie, które uzyskało 25 pozytywnych głosów';
    case 'great answer':
    case 'great-answer':
      return 'Udzielił odpowiedzi, która uzyskała 25 pozytywnych głosów';
    case 'great question':
    case 'great-question':
      return 'Zadał pytanie, które uzyskało 25 pozytywnych głosów';
    case 'guru': return 'Udzielił odpowiedzi, która została zaakceptowana i uzyskała 40 pozytywnych głosów';
    case 'legendary':
      return 'Osiągnał dzienny limit na zdobywaną reputację przez 150 dni';
    case 'mortarboard':
      return 'Po raz pierwszy osiągnął dzienny limit na zdobywaną reputację';
    case 'necromancer':
      return 'Udzielił odpowiedzi na pytanie 60 dni później i otrzymał co najmniej 5 głosów';
    case 'nice answer':
    case 'nice-answer':
      return 'Udzielił odpowiedzi, która uzyskała 10 pozytywnych głosów';
    case 'nice question':
    case 'nice-question':
      return 'Zadał pytanie, które uzyskało 10 pozytywnych głosów';
    case 'notable question':
    case 'notable-question':
      return 'Zadał pytanie, które zostało wyświetlone 2 500 razy';
    case 'organizer':
      return 'Po raz pierwszy zmodyfikował tagi';
    case 'peer pressure':
    case 'peer-pressure':
      return 'Skasował własny wpis z co najmniej 3 głosami negatywnymi';
    case 'popular question':
    case 'popular-question':
      return 'Zadał pytanie, które zostało wyświetlone 1 000 razy';
    case 'populist':
      return 'Udzielił odpowiedzi, która uzyskała 2 razy więcej pozytywnych głosów niż zaakceptowana odpowiedź z co najmniej 10 głosami';
    case 'pundit':
      return 'Zostawił 10 komentarzy z 10 bądź więcej punktami';
    case 'reversal':
      return 'Udzielił odpowiedzi z 20 punktami na pytanie z -5 punktami';
    case 'scholar':
      return 'Po raz pierwszy zaakceptował odpowiedź na swoje pytanie';
    case 'self-learner':
      return 'Udzielił odpowiedzi na własne pytanie, która uzyskała co najmniej 3 głosy';
    case 'stellar question':
    case 'stellar-question':
      return 'Zadał pytanie, które zostało dodane do ulubionych przez 100 użytkowników';
    case 'strunk & white':
    case 'strunk-white':
      return 'Zedytował 100 wpisów';
    case 'student':
      return 'Po raz pierwszy zadał pytanie, które uzyskało co najmniej jeden pozytywny głos';
    case 'supporter':
      return 'Oddał pierwszy pozytywny głos';
    case 'taxonomist':
      return 'Utworzył tag, który zostal użyty przy 50 pytaniach';
    case 'teacher':
      return 'Po raz pierwszy udzielił odpowiedzi, która uzyskała co najmniej jeden pozytywny głos';
    case 'tumbleweed':
      return 'Zadał pytanie, na które przez tydzień nikt nie odpowiedział, którego nikt nie komentował i które mało kto oglądał';
    case 'yearling':
      return 'Aktywnie korzystał z serwisu przez rok';
    default:
      break;
  }

  return '';
}

function getBadgeColorString(badgeDescription) {
  if (badgeDescription == null) {
    return '';
  }

  var badgeDescriptionLower = badgeDescription.toLowerCase();

  if (badgeDescriptionLower.indexOf('bronze badge:') != -1) {
    return 'brązowa odznaka';
  }
  else if (badgeDescriptionLower.indexOf('silver badge:') != -1) {
    return 'srebrna odznaka';
  }
  else if (badgeDescriptionLower.indexOf('gold badge:') != -1) {
    return 'złota odznaka';
  }

  return '';
}

// localizes single badge element (an element with the 'badge' css class)
function localizeBadgeElement(badgeElem, localizeSiblingDescription) {
  var textNodes = getChildTextNodes(badgeElem);

  if (textNodes == null || textNodes.length == 0) {
    return;
  }

  var textNodeRaw = textNodes[0];
  var textNode = $(textNodeRaw);
  var badgeName = trim(getNodeTextContent(textNodeRaw));

  textNode.replaceWith(' ' + getLocalizedBadgeName(badgeName));

  var badgeDescription = badgeElem.attr('title');
  var localizedBadgeDescription = getLocalizedBadgeDescription(badgeName);
  var badgeTitle = localizedBadgeDescription;
  var badgeColorString = getBadgeColorString(badgeDescription);

  if (badgeColorString != null && badgeColorString != '') {
    badgeTitle = badgeColorString + ': ' + badgeTitle;
  }

  badgeElem.attr('title', badgeTitle);

  if (localizeSiblingDescription) {
    var lastCellElem = badgeElem.closest('tr').children('td:last');
    var newHtml = localizedBadgeDescription + '.';

    if (lastCellElem.html().indexOf('This badge can be awarded multiple times.') != -1) {
      newHtml += ' Ta odznaka może być przyznawana wielokrotnie.';
    }

    lastCellElem.html(newHtml);
  }
}

function localizeBadgesPage() {
  // badges page header and tabs
  $('#subheader > h2').eq(0).text("Odznaki");

  var tabGeneralElem = $('#content > #subheader > #tabs > a').eq(0);
  var tabTagsElem = $('#content > #subheader > #tabs > a').eq(1);

  tabGeneralElem.attr("title", "odznaki standardowe").text("standardowe");
  tabTagsElem.attr("title", "odznaki oparte na tagach").text("tag-odznaki");

  // page description
  $('#mainbar .page-description:eq(0)').html('<p>Zadawaj pytania, udzielaj odpowiedzi, głosuj na to, co uznasz za pomocne &mdash; w zamian za to ' + g_SiteName + ' obdarzą Cię odznakami. Poniżej znajdziesz ich pełną listę wraz z liczbą użytkowników, którym dana odznaka została już przyznana:</p>');

  // badges page
  var badgesElems = $('#mainbar a.badge');

  $.each(badgesElems, function() {
    localizeBadgeElement($(this), true);
  });

  // badges legend
  var sidebarModuleElem = $('#sidebar .module');

  sidebarModuleElem.children('h4').eq(0).text("Legenda");

  var badgeLegendElem = sidebarModuleElem.children('#badge-legend');
  var aElem = null;

  var queryString = window.location.search;

  if (queryString.match(/\?tab=tags/i) != null) { // tags tab
    badgeLegendElem.children('div').eq(0).html('<p>Tag-odznaki przyznawane są za udzielanie się w pytaniach nie będących częścią <b>społecznościowego wiki</b> i które mają określone tagi. Gdy w jakimś tagu &mdash; <i>dowolnym tagu</i> &mdash; pojawi się wystarczająco duża liczba pozytywnych głosów, specjalna odznaka dla tego taga zostanie stworzona i zacznie być przyznawana.</p>');

    aElem = badgeLegendElem.find('a[title^="gold badge"]');
    aElem.attr('title', 'złota tag-odznaka: bardzo rzadko spotykana');
    getChildTextNodes(aElem).replaceWith(' Złota tag-odznaka');
    aElem.parent().next().replaceWith('<p>Aby otrzymać tę tag-odznakę, musisz zdobyć 1000 pozytywnych głosów w pytaniach nie będących częścią społecznościowego wiki.</p>');

    aElem = badgeLegendElem.find('a[title^="silver badge"]');
    aElem.attr('title', 'srebrna tag-odznaka: rzadko spotykana');
    getChildTextNodes(aElem).replaceWith(' Srebrna tag-odznaka');
    aElem.parent().next().replaceWith('<p>Aby otrzymać tę tag-odznakę, musisz zdobyć 400 pozytywnych głosów w pytaniach nie będących częścią społecznościowego wiki.</p>');
  }
  else { // default or general tab
    aElem = badgeLegendElem.find('a[title^="gold badge"]');
    aElem.attr('title', 'złota odznaka: przyznawana rzadko');
    getChildTextNodes(aElem).replaceWith(' Złota odznaka');
    aElem.parent().next().replaceWith('<p>Złote odznaki to rzadkość. Samo aktywne korzystanie z serwisu nie wystarczy, by je zdobyć &mdash; do tego potrzebne są wiedza i umiejętności. Otrzymanie takiej odznaki to spore osiągnięcie!</p>');

    aElem = badgeLegendElem.find('a[title^="silver badge"]');
    aElem.attr('title', 'srebrna odznaka: przyznawana okazjonalnie');
    getChildTextNodes(aElem).replaceWith(' Srebrna odznaka');
    aElem.parent().next().replaceWith('<p>Srebrne odznaki przyznawane są za realizację celów długoterminowych. Nie spotyka się ich za często, ale dla wystarczająco wytrwałych są osiągalne.</p>');

    aElem = badgeLegendElem.find('a[title^="bronze badge"]');
    aElem.attr('title', 'brązowa odznaka: przyznawana często');
    getChildTextNodes(aElem).replaceWith(' Brązowa odznaka');
    aElem.parent().next().replaceWith('<p>Brązowe odznaki otrzymuje się za korzystanie z podstawowych funkcjonalności serwisu ' + g_SiteName + '; stosunkowo łatwo je zdobyć.</p>');
  }
}

function localizeBadgePage(badgeName) {
  // badges page header and tabs
  $('#subheader > h2').eq(0).text("Odznaka");

  // badge symbol and description
  var badgesElems = $('#mainbar-full a.badge');

  $.each(badgesElems, function() {
    localizeBadgeElement($(this), true);
  });

  // summary
  var summaryCountElem = $('#mainbar-full table td .summarycount');
  var summaryCount = parseInt(summaryCountElem.text());
  var startString = 'użytkowników zdobyło';

  if (summaryCount == 1) {
    startString = 'użytkownik zdobył';
  }

  summaryCountElem.closest('td').next('td').children('h1').html(startString + ' tę odznakę. Ostatnio przyznano ją:');
}

// badgeChar == 1: gold
// badgeChar == 2: silver
// badgeChar == 3: bronze
function localizeBadgeCounts(badgeChar) {
  if (badgeChar != '1' && badgeChar != '2' && badgeChar != '3') {
    return;
  }

  $.each($('span.badge' + badgeChar), function() {
    var parent = $(this).parent();
    var match = parent.attr('title').match(/([0-9]+).*/);

    if (match == null) {
      return;
    }

    var badgesCount = parseInt(match[1]);
    var badgesCountTitleSuffix = null;

    switch (getNumberClass(badgesCount)) {
      case g_NumberClass_Singular:
        badgesCountTitleSuffix = (badgeChar == '1' ? 'złota' : (badgeChar == '2' ? 'srebrna' : 'brązowa')) + ' odznaka';
        break;
      case g_NumberClass_Plural_1:
        badgesCountTitleSuffix = (badgeChar == '1' ? 'złotych' : (badgeChar == '2' ? 'srebrnych' : 'brązowych')) + ' odznak';
        break;
      case g_NumberClass_Plural_2:
        badgesCountTitleSuffix = (badgeChar == '1' ? 'złote' : (badgeChar == '2' ? 'srebrne' : 'brązowe')) + ' odznaki';
        break;
      default:
        break;
    }

    if (badgesCountTitleSuffix != null) {
      parent.attr('title', badgesCount + ' ' + badgesCountTitleSuffix);
    }
  });
}

// rafek's localization (TODO: refactor)
function rafeksLocalization() {
  var queryString = window.location.search;

  // TODO: location.pathname zamienic na urlPath i uzywac regexow
  // TODO: powyciagac metody dla poszczegolnych podstron

  // #topbar
  var envelopeImgElem = $('#topbar #hlinks a:eq(0) > img');
  if (envelopeImgElem.length > 0) {
    var envelopeImgTitle = envelopeImgElem.attr('title');
  
    if (envelopeImgTitle.match(/have no new replies/i) != null) {
      envelopeImgElem.attr('title', 'Nie masz nowych odpowiedzi');
    }
    else if (envelopeImgTitle.match(/have new replies/i) != null) {
      envelopeImgElem.attr('title', 'Masz nowe odpowiedzi');
    }
  }
  
  $('#topbar #hlinks a:contains("login")').text("zaloguj się");
  $('#topbar #hlinks a:contains("log out")').text("wyloguj się");
  $('#topbar #hlinks a:contains("tools")').text("narzędzia");
  $('#topbar #hsearch #search input[type="textbox"]')
    .attr("value", "szukaj")
    .focus(function() { if (this.value == "szukaj") this.value = '' }); ;

  $('#topbar #topbar-login')
    .after('<a id="topbar-register" href="/users/register">załóż konto</a>')
    .after(' <span class="link-separator">|</span> ');

  // #hmenus
  $('#hmenus > .nav > ul > li > a:eq(0)').text("Pytania");
  $('#hmenus > .nav > ul > li > a:eq(1)').text("Tagi");
  $('#hmenus > .nav > ul > li > a:eq(2)').text("Użytkownicy");
  $('#hmenus > .nav > ul > li > a:eq(3)').text("Odznaki");
  $('#hmenus > .nav > ul > li > a:eq(4)').text("Bez odpowiedzi");
  $('#hmenus > .nav > ul > li > a:eq(5)').text("Zadaj pytanie").addClass('emph-nav-button');

  var urlPath = window.location.pathname;
  var match = null;

  // #mainbar
  if (window.location.pathname == '/') {
    // #subheader
    $('#mainbar > #subheader > h2').text("Najnowsze pytania");
    $('#mainbar > #subheader > #tabs > a:eq(0)')
      .attr("title", "pytania, które ostatnio uaktualniono bądź zadano, bądź takie, na które udzielono odpowiedzi")
      .text("aktywne");
    $('#mainbar > #subheader > #tabs > a:eq(1)')
      .attr("title", "pytania z aktywną nagrodą")
      .contents().filter(function() { return this.nodeType == g_NodeType_Text; }).replaceWith("promowane");
    $('#mainbar > #subheader > #tabs > a:eq(2)')
      .attr("title", "pytania o największym zainteresowaniu i aktywności w ostatnich dniach")
      .text("gorące");
    $('#mainbar > #subheader > #tabs > a:eq(3)')
      .attr("title", "pytania o największym zainteresowaniu i aktywności w tym tygodniu")
      .text("tydzień");
    $('#mainbar > #subheader > #tabs > a:eq(4)')
      .attr("title", "pytania o największym zainteresowaniu i aktywności w tym miesiącu")
      .text("miesiąc");
      
    var badgesElems = $('a.badge', $('#sidebar #recent-badges'));

    $.each(badgesElems, function() {
      localizeBadgeElement($(this), false);
    });
    
    // #mainbar
    var lookingForMoreHtml = $('#mainbar > h2').html();

    lookingForMoreHtml = lookingForMoreHtml.replace(/Looking for more/, "Szukasz więcej");
    lookingForMoreHtml = lookingForMoreHtml.replace(/Browse the/, "Przejrzyj");
    lookingForMoreHtml = lookingForMoreHtml.replace(/complete list of questions/, "kompletną listę pytań");
    lookingForMoreHtml = lookingForMoreHtml.replace(/, or /, " albo ");
    lookingForMoreHtml = lookingForMoreHtml.replace(/popular tags/, "popularne tagi");
    lookingForMoreHtml = lookingForMoreHtml.replace(/Help us answer/, "Pomóż nam odpowiedzieć na");
    lookingForMoreHtml = lookingForMoreHtml.replace(/unanswered questions/, "pytania bez odpowiedzi");
    $('#mainbar > h2').html(lookingForMoreHtml);

    if (queryString.match(/tab=featured/i) != null) {
      $('#mainbar > h2').eq(0).html('Szukasz więcej promowanych pytań? Przejrzyj <a href="/questions?sort=featured">kompletną listę</a>.');
    }
  }
  else if ((match = urlPath.match(/^\/questions/i)) != null) {
    var tagged = (match = urlPath.match(/^\/questions\/([^\/]+)/i)) != null
    var questionsCount = parseInt($('#sidebar > .module > .summarycount').text());

    localizeStatsContainer();

    if (tagged) {
      $('#mainbar-full > #subheader > h2').text("Otagowane pytania");

      $('#sidebar > .module > .summarycount').next('p').html(getProperTaggedQuestionsNumberForm(questionsCount));

      $('#mainbar-full > #subheader > #tabs > a').eq(0).text("statsy").attr("title", "Statystyki na tym tagu");

      if (queryString.match(/sort=stats/i) != null) {
        var questionsElem = $('#mainbar-full > #questions > h2').eq(0);
        var textNodes = getChildTextNodes(questionsElem);

        if (textNodes.length > 0) {
          $(textNodes[textNodes.length - 1]).replaceWith(" Pytania");
        }

        $('#mainbar-full > #questions > table h1:contains("Last 7 Days")').text("Ostatnie 7 dni");
        $('#mainbar-full > #questions > table h1:contains("Last 30 Days")').text("Ostatnie 30 dni");
        $('#mainbar-full > #questions > table h1:contains("All Time")').text("Od początku");

        var topAnswerersElem = $('#mainbar-full > #questions > h2').eq(1);
        textNodes = getChildTextNodes(topAnswerersElem);
        if (textNodes.length > 0) {
          $(textNodes[0]).replaceWith("Najaktywniej odpowiadający w tagach ");
          $(textNodes[textNodes.length - 1]).replaceWith("");
        }

        var topAskersElem = $('#mainbar-full > #questions > h2').eq(2);
        textNodes = getChildTextNodes(topAskersElem);
        if (textNodes.length > 0) {
          $(textNodes[0]).replaceWith("Najaktywniej zadający pytania w tagach ");
          $(textNodes[textNodes.length - 1]).replaceWith("");
        }

        $('#mainbar-full > #questions h2:contains("Last 30 Days")').text("Ostatnie 30 dni");
        $('#mainbar-full > #questions h2:contains("All time")').text("Od początku");

        $('#mainbar-full > #questions > p').eq(1).text("Powyższe statystyki oparte są jedynie na pytaniach nie będących częścią społecznościowego wiki.");
      }
    }
    else {
      $('#mainbar-full > #subheader > h2').text("Wszystkie pytania");
      $('#sidebar > .module > .summarycount').next('p').html(getProperQuestionsNumberForm(questionsCount));
    }

    var tabsOffset = (tagged) ? 1 : 0;

    $('#mainbar-full > #subheader > #tabs > a').eq(0 + tabsOffset)
      .attr("title", "Najnowsze zadane pytania")
      .text("najnowsze");
    $('#mainbar-full > #subheader > #tabs > a').eq(1 + tabsOffset)
      .attr("title", "Pytania z aktywnymi nagrodami")
      .text("promowane");
    $('#mainbar-full > #subheader > #tabs > a').eq(2 + tabsOffset)
      .attr("title", "Pytania o największym zainteresowaniu i aktywności")
      .text("gorące");
    $('#mainbar-full > #subheader > #tabs > a').eq(3 + tabsOffset)
      .attr("title", "Pytania o największej ilości głosów")
      .text("głosy");
    $('#mainbar-full > #subheader > #tabs > a').eq(4 + tabsOffset)
      .attr("title", "Pytania o największej aktywności")
      .text("aktywne");
  }
  else if ((match = urlPath.match(/^\/unanswered(\/([^\/]+))?/i)) != null) {
    // #subheader
    $('#mainbar-full > #subheader > h2').text("Pytania bez odpowiedzi");
    $('#mainbar-full > #subheader > #tabs > a:eq(0)')
        .attr("title", "pytania z tagami, w których się udzielałeś")
        .text("moje tagi");
    $('#mainbar-full > #subheader > #tabs > a:eq(1)')
        .attr("title", "najnowsze pytania bez odpowiedzi")
        .text("najnowsze");
    $('#mainbar-full > #subheader > #tabs > a:eq(2)')
        .attr("title", "pytania bez odpowiedzi o największej liczbie głosów")
        .text("głosy");

    // #mainbar
    localizeStatsContainer();

    // #sidebar
    $('#sidebar > .module > h4:contains("Unanswered Tags")').text("Tagi bez odpowiedzi");

    var questionsCount = parseInt($('#sidebar > .module > .summarycount').text());

    $('#sidebar > .module > .summarycount')
      .next('p').html(getProperQuestionsNumberForm(questionsCount) + " bez <b class=\"unansweredfg\">pozytywnie ocenionych odpowiedzi</b>")
      .next('p').filter(function() { return $(this).text().match(/in your tags/i) != null; }).html("w Twoich tagach");
  }
  else if ((match = urlPath.match(/^\/tags/i)) != null) {
    localizeTagsPage();
  }

  // #sidebar
  if (window.location.pathname == '/') {
    $('#sidebar > .module > h4:contains("Recent Tags")').text("Ostatnie tagi");
    $('#sidebar > .module > p > a[href="/tags"]').text("wszystkie tagi »");
    $('#sidebar > .module > h4:contains("Recent Badges")').text("Ostatnie odznaki");
    $('#sidebar > .module > p > a[href="/badges"]').text("wszystkie odznaki »");
  }

  $('#sidebar > .module > h4:contains("Interesting Tags")').text("Interesujące tagi");
  $('#sidebar > .module > h4:contains("Ignored Tags")').text("Ignorowane tagi");
  $('#sidebar > .module > table input[value="Add"]').attr("value", "Dodaj");
  $('#sidebar > .module > h4:contains("Related Tags")').text("Powiązane tagi");
}

// client-side validation
function localizeValidatorMessages() {
  if (typeof($.validator) == 'undefined' || typeof($.validator.messages) == 'undefined') {
    return;
  }
  
  $.validator.messages.required = "To pole jest wymagane.";
  $.validator.messages.remote = "Wprowadzona wartość jest nieprawidłowa.";
  $.validator.messages.email = "Wprowadź poprawny adres e-mail.";
  $.validator.messages.url = "Wprowadź poprawny URL.";
  $.validator.messages.date = "Wprowadź poprawną datę.";
  $.validator.messages.dateISO = "Wprowadź poprawną datę (ISO).";
  $.validator.messages.number = "Wprowadź poprawną liczbę.";
  $.validator.messages.digits = "Wprowadź tylko cyfry.";
  $.validator.messages.creditcard = "Wprowadź poprawny numer karty kredytowej.";
  $.validator.messages.equalTo = "Wprowadź jeszcze raz tę samą wartość.";
  $.validator.messages.accept = "Wprowadź wartość z poprawnym rozszerzeniem.";
  $.validator.messages.maxlength = $.format("Maksymalna liczba znaków: {0}.");
  $.validator.messages.minlength = $.format("Minimalna liczba znaków: {0}.");
  $.validator.messages.rangelength = $.format("Minimalna liczba znaków: {0}. Maksymalna liczba znaków: {1}.");
  $.validator.messages.range = $.format("Wprowadź wartość pomiędzy {0} i {1}.");
  $.validator.messages.max = $.format("Wprowadź wartość mniejszą bądź równą {0}.");
  $.validator.messages.min = $.format("Wprowadź wartość większą bądź równą {0}.");
}

function localizeCaptchaPage() {
  // header
  $('#content #subheader h2').eq(0).html('Weryfikacja człowieczeństwa');
  
  // sidebar
  var areYouHumanModuleElem = $('#sidebar div.module').eq(0);
  
  areYouHumanModuleElem.html('<h4>Czy jesteś człowiekiem?</h4><p>Przepraszamy za utrudnienia, ale nie jesteśmy w stanie <i>jednoznacznie</i> stwierdzić, czy jesteś żywą osobą czy może skryptem.</p><p>Nie bierz tego do siebie.</p><p>W dzisiejszych czasach boty i skrypty potrafią całkiem sprawnie naśladować ludzi!</p><p>Jak tylko rozwiążesz poniższą <a href="http://pl.wikipedia.org/wiki/CAPTCHA">CAPTCHĘ</a>, będziesz mógł kontynuować.</p>');
  
  // submit button
  $('#mainbar form input[type="submit"]').eq(0).val('Jestem człowiekiem');
  
  // form errors
  filterByTextRegex($('#mainbar form').nextAll('div.form-error'), /oops! those aren\'t the correct word/i).html('Ups! To nie są te słowa.');
}

function obtainCurrentUserInfo() {
  var hlinksSelector = $('#header #topbar #hlinks a');
  
  for (var i = 0; i < hlinksSelector.length; i++) {
    var hlink = hlinksSelector.eq(i);
    var hlinkMatch = null;
    
    if ((hlinkMatch = hlink.attr('href').match(/^\/users\/(-?[0-9]+)\/[^\/\?]+/i)) != null) {
      g_currentUserId = parseInt(hlinkMatch[1]);
      g_currentUserName = trim(hlink.text());
      
      var modFlairElem = hlink.next('span.mod-flair');
      
      if (modFlairElem.length > 0) {
        if (trim(modFlairElem.text()) == '♦♦') {
          g_isCurrentUserAdministrator = true;
          g_isCurrentUserModerator = true;
        }
        else if (trim(modFlairElem.text()) == '♦') {
          g_isCurrentUserModerator = true;
        }
      }
      
      break;
    }
  }
}

function localizeSearchResultsPage() {
  // header
  $('#content #subheader h2').eq(0).html('Wyniki wyszukiwania');

  // tabs
  var tabsElems = $('#content #subheader #tabs a');

  tabsElems.eq(0).html('istotność').attr('title', 'Sortuj według najlepszego dopasowania');
  tabsElems.eq(1).html('najnowsze').attr('title', 'Sortuj według daty');
  tabsElems.eq(2).html('głosy').attr('title', 'Sortuj według liczby głosów');
  tabsElems.eq(3).html('aktywne').attr('title', 'Sortuj według aktywności');
  
  // no results
  var pageDescriptionElem = $('#content #mainbar div.page-description');
  
  $.each(pageDescriptionElem.children('p'), function() {
    var pElem =$(this);
    var pElemText = pElem.text();
    
    if (pElemText.match(/^your search returned no matches/i) != null) {
      pElem.replaceWith('<p>Nie znaleziono żadnych pytań pasujących do zapytania.</p>');
    }
    else if (pElemText.match(/^suggestions/i) != null) {
      pElem.replaceWith('<p>Sugestie:</p>');
    }
    else if (pElemText.match(/^alternately, try your search in google/i) != null) {
      pElem.replaceWith('<p>Możesz również spróbować poszukać w Google:</p>');
    }
  });
  
  pageDescriptionElem.children('ul').eq(0);
  $.each(pageDescriptionElem.children('ul').eq(0).children('li'), function() {
    var liElem = $(this);
    var liElemText = liElem.text();
    
    if (liElemText.match(/^place your search terms in quotes/i) != null) {
      liElem.html('Aby wyszukać frazy, zastosuj cudzysłów:');
    }
    else if (liElemText.match(/^search within a specific set of tags/i) != null) {
      liElem.html('Szukaj według tagów:');
      
      var tagExampleElems = liElem.nextAll('p').eq(0).find('span.search-tag-example');
      
      $.each(tagExampleElems, function() {
        var tagExampleElem = $(this);
      
        tagExampleElem.html(tagExampleElem.html().replace(/\[another-tag\]/i, '[inny-tag]'));
      });
    }
    else if (liElemText.match(/^use fewer words/i) != null) {
      liElem.html('Użyj mniejszej liczby słów:');
    }
    else if (liElemText.match(/^make sure all words are spelled correctly/i) != null) {
      liElem.html('Upewnij się, że nie popełniłeś żadnej literówki.<br /><br />');
    }
    else if (liElemText.match(/^use different words/i) != null) {
      liElem.html('Użyj innych słów.<br /><br />');
    }
    else if (liElemText.match(/^use more general words/i) != null) {
      liElem.html('Użyj słów o bardziej ogólnym znaczeniu.<br /><br />');
    }
  });
  
  // sidebar module
  var searchModuleElem = $('#content #sidebar div.module').eq(0);
  var searchHighlightText = trim(searchModuleElem.find('span.search-highlight').eq(0).text());

  searchModuleElem.html('<p>Przeglądasz pytania pasujące do zapytania</p><p><span class="search-highlight">' + searchHighlightText + '</span></p><ul><li>Możesz wyszukiwać według tagów, ujmując słowa w nawiasy kwadratowe, np.: [tag-1], [tag-2].</li><li>Aby wyszukać frazy, zastosuj cudzysłów.</li><li>Możesz także używać operatorów ~ (dopasowanie częściowe) oraz - (negacja) umieszczając je przed poszczególnymi słowami.</li></ul>');
}

function checkBrowserFeatures() {
  g_supportsTextContent = typeof(document.getElementsByTagName('body')[0].textContent) != 'undefined';
  g_supportsInnerText = typeof(document.getElementsByTagName('body')[0].innerText) != 'undefined'
}

function displayPageContents() {
  $('body > div.container').show();
  $('div#footer').show();
  $('div#notify-container').show();
  $('div#custom-header').show();
}

// localization entry point
$(document).ready(function() {
  checkBrowserFeatures();

  obtainCurrentUserInfo();

  // TODO: refactor
  rafeksLocalization();

  localizePageTitle();
  localizeCommonElements();
  localizeValidatorMessages();
  localizeBootstrapModule();

  var urlPath = window.location.pathname;
  var match = null;

  if ((match = urlPath.match(/^\/questions\/ask/i)) != null) {
    localizeAskQuestionPage();
  }
  else if ((match = urlPath.match(/^\/questions\/[0-9]+/i)) != null) {
    localizeQuestionPage();
  }
  else if ((match = urlPath.match(/^\/users\/-?[0-9]+/i)) != null) {
    localizeUserPage();
  }
  else if ((match = urlPath.match(/^\/users\/edit\/-?[0-9]+/i)) != null) {
    localizeUserEditPage();
  }
  else if ((match = urlPath.match(/^\/users\/recent\/-?[0-9]+/i)) != null) {
    localizeUserRecentPage();
  }
  else if ((match = urlPath.match(/^\/users\/login/i)) != null) {
    localizeLoginPage();
  }
  else if ((match = urlPath.match(/^\/users\/logout/i)) != null) {
    localizeLogoutPage();
  }
  else if ((match = urlPath.match(/^\/users\/register/i)) != null) {
    localizeRegisterPage();
  }
  else if ((match = urlPath.match(/^\/users/i)) != null) {
    localizeUsersPage();
  }
  else if ((match = urlPath.match(/^\/posts\/[0-9]+\/edit/i)) != null) {
    localizeEditPostPage();
  }
  else if ((match = urlPath.match(/^\/badges\/[0-9]+\/([^\/]+)/i)) != null) {
    localizeBadgePage(match[1]);
  }
  else if ((match = urlPath.match(/^\/badges/i)) != null) {
    localizeBadgesPage();
  }
  else if ((match = urlPath.match(/^\/captcha/i)) != null) {
    localizeCaptchaPage();
  }
  else if ((match = urlPath.match(/^\/search/i)) != null) {
    localizeSearchResultsPage();
  }
  else if ((match = urlPath.match(/^\/revisions\/[0-9]+\/list/i)) != null) {
    localizeRevisionsListPage();
  }
  else if ((match = urlPath.match(/^\/bootstrap/i)) != null) {
    localizeBootstrapPage();
  }

  

  displayPageContents();
});

