Wikivoyage:AutoWikiBrowser

Da Wikivoyage.

AutoWikiBrowser (spesso abbreviato AWB) è un editor MediaWiki semi-automatico per Windows XP e versioni successive, progettato per effettuare le operazioni ripetitive e noiose in modo più semplice e veloce. Per l'installazione su sistemi Linux vedi la guida in inglese su questa pagina Ogni modifica fatta con AWB deve essere riesaminata manualmente prima di essere salvata, e (se necessario) bisogna applicare manualmente le correzioni necessarie. Per una guida più estesa vedi la relativa pagina su Wikipedia

Le seguenti operazioni consentono l'uso di AWB su una macchina Windows con impostazioni per Wikivoyage.

Installare AWB[modifica]

  1. scarica l'ultima versione da qui
  2. Estrai il contenuto
  3. Doppio click su AutoWikiBrowser.exe per avviare AWB

Configurare AWB[modifica]

Configurare di AWB richiede l'impostazione di alcuni parametri e il caricamento di un set di impostazioni standard di AWB che sono stati adattati per Wikivoyage. Per la documentazione tecnica dettagliata vedi questa pagina

  1. Configura AWB per Wikivoyage. Seleziona Options → Preferences → Site → Project → Wikivoyage. e poi scegli la lingua. Nel nostro caso 'it'
  2. Imposta il login: Seleziona File → Log in/Profiles → Add → Login. Scrivi il tuo username e password in modo che le modifiche di AWB appaiano fatte dal tuo account.
  3. Importa la configurazione specifica per Wikivoyage. Copia il testo XML qui sotto e salvalo in un file con estensione .xml. Poi da AWB seleziona File → Log in/Profiles → Add → Login e premi Edit sul login da te salvato. Metti la spunta a "Select default settings" e inserisci il percorso del file xml. Una volta fatto il login potrai iniziare ad usare AWB per Wikivoyage.


file di configurazione AWB per Wikivoyage italiano
<?xml version="1.0" encoding="utf-8"?>
<AutoWikiBrowserPreferences xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xml:space="preserve" Version="5.5.6.0">
  <Project>wikivoyage</Project>
  <LanguageCode>it</LanguageCode>
  <CustomProject />
  <Protocol>http://</Protocol>
  <LoginDomain />
  <List>
    <ListSource />
    <SelectedProvider>CategoryListProvider</SelectedProvider>
    <ArticleList />
  </List>
  <FindAndReplace>
    <Enabled>true</Enabled>
    <IgnoreSomeText>false</IgnoreSomeText>
    <IgnoreMoreText>false</IgnoreMoreText>
    <AppendSummary>true</AppendSummary>
    <Replacements>
      <Replacement>
        <Find>\|thumbnail\|</Find>
        <Replace>|thumb|</Replace>
        <Comment />
        <IsRegex>false</IsRegex>
        <Enabled>true</Enabled>
        <Minor>true</Minor>
        <BeforeOrAfter>false</BeforeOrAfter>
        <RegularExpressionOptions>IgnoreCase</RegularExpressionOptions>
      </Replacement>
    </Replacements>
    <AdvancedReps />
    <SubstTemplates />
    <IncludeComments>false</IncludeComments>
    <ExpandRecursively>true</ExpandRecursively>
    <IgnoreUnformatted>false</IgnoreUnformatted>
  </FindAndReplace>
  <Editprefs>
    <GeneralFixes>true</GeneralFixes>
    <Tagger>false</Tagger>
    <Unicodify>true</Unicodify>
    <Recategorisation>0</Recategorisation>
    <NewCategory />
    <NewCategory2 />
    <ReImage>0</ReImage>
    <ImageFind />
    <Replace />
    <SkipIfNoCatChange>false</SkipIfNoCatChange>
    <RemoveSortKey>false</RemoveSortKey>
    <SkipIfNoImgChange>false</SkipIfNoImgChange>
    <AppendText>false</AppendText>
    <AppendTextMetaDataSort>false</AppendTextMetaDataSort>
    <Append>true</Append>
    <Text />
    <Newlines>2</Newlines>
    <AutoDelay>10</AutoDelay>
    <BotMaxEdits>0</BotMaxEdits>
    <SupressTag>false</SupressTag>
    <RegexTypoFix>true</RegexTypoFix>
  </Editprefs>
  <General>
    <AutoSaveEdit>
      <Enabled>false</Enabled>
      <SavePeriod>30</SavePeriod>
      <SaveFile />
    </AutoSaveEdit>
    <SelectedSummary>correzioni</SelectedSummary>
    <Summaries>
      <string>correzioni</string>
      <string>typo</string>
      <string>fix vari</string>
      <string>sistemo</string>
    </Summaries>
    <PasteMore>
      <string />
      <string />
      <string />
      <string />
      <string />
      <string />
      <string />
      <string />
      <string />
      <string />
    </PasteMore>
    <FindText />
    <FindRegex>false</FindRegex>
    <FindCaseSensitive>false</FindCaseSensitive>
    <WordWrap>true</WordWrap>
    <ToolBarEnabled>true</ToolBarEnabled>
    <BypassRedirect>true</BypassRedirect>
    <AutoSaveSettings>true</AutoSaveSettings>
    <noSectionEditSummary>false</noSectionEditSummary>
    <restrictDefaultsortAddition>true</restrictDefaultsortAddition>
    <restrictOrphanTagging>true</restrictOrphanTagging>
    <noMOSComplianceFixes>true</noMOSComplianceFixes>
    <syntaxHighlightEditBox>false</syntaxHighlightEditBox>
    <highlightAllFind>false</highlightAllFind>
    <PreParseMode>false</PreParseMode>
    <NoAutoChanges>false</NoAutoChanges>
    <OnLoadAction>0</OnLoadAction>
    <DiffInBotMode>false</DiffInBotMode>
    <Minor>true</Minor>
    <AddToWatchlist>2</AddToWatchlist>
    <TimerEnabled>false</TimerEnabled>
    <SortListAlphabetically>true</SortListAlphabetically>
    <AddIgnoredToLog>false</AddIgnoredToLog>
    <EditToolbarEnabled>true</EditToolbarEnabled>
    <filterNonMainSpace>false</filterNonMainSpace>
    <AutoFilterDuplicates>true</AutoFilterDuplicates>
    <FocusAtEndOfEditBox>false</FocusAtEndOfEditBox>
    <scrollToUnbalancedBrackets>false</scrollToUnbalancedBrackets>
    <TextBoxSize>9</TextBoxSize>
    <TextBoxFont>Courier New</TextBoxFont>
    <LowThreadPriority>false</LowThreadPriority>
    <Beep>false</Beep>
    <Flash>false</Flash>
    <Minimize>false</Minimize>
    <LockSummary>false</LockSummary>
    <SaveArticleList>true</SaveArticleList>
    <SuppressUsingAWB>false</SuppressUsingAWB>
    <AddUsingAWBToActionSummaries>false</AddUsingAWBToActionSummaries>
    <IgnoreNoBots>false</IgnoreNoBots>
    <ClearPageListOnProjectChange>false</ClearPageListOnProjectChange>
    <SortInterWikiOrder>true</SortInterWikiOrder>
    <ReplaceReferenceTags>true</ReplaceReferenceTags>
    <LoggingEnabled>true</LoggingEnabled>
    <AlertPreferences>
      <int>1</int>
      <int>2</int>
      <int>3</int>
      <int>4</int>
      <int>5</int>
      <int>6</int>
      <int>7</int>
      <int>8</int>
      <int>9</int>
      <int>10</int>
      <int>11</int>
      <int>12</int>
      <int>13</int>
      <int>14</int>
      <int>15</int>
      <int>16</int>
      <int>17</int>
      <int>18</int>
      <int>19</int>
      <int>20</int>
      <int>21</int>
    </AlertPreferences>
  </General>
  <SkipOptions>
    <SkipNonexistent>true</SkipNonexistent>
    <Skipexistent>false</Skipexistent>
    <SkipWhenNoChanges>true</SkipWhenNoChanges>
    <SkipSpamFilterBlocked>false</SkipSpamFilterBlocked>
    <SkipInuse>false</SkipInuse>
    <SkipWhenOnlyWhitespaceChanged>true</SkipWhenOnlyWhitespaceChanged>
    <SkipOnlyGeneralFixChanges>true</SkipOnlyGeneralFixChanges>
    <SkipOnlyMinorGeneralFixChanges>false</SkipOnlyMinorGeneralFixChanges>
    <SkipOnlyCosmetic>false</SkipOnlyCosmetic>
    <SkipOnlyCasingChanged>false</SkipOnlyCasingChanged>
    <SkipIfRedirect>false</SkipIfRedirect>
    <SkipIfNoAlerts>false</SkipIfNoAlerts>
    <SkipDoes>false</SkipDoes>
    <SkipDoesNot>false</SkipDoesNot>
    <SkipDoesText />
    <SkipDoesNotText />
    <Regex>false</Regex>
    <CaseSensitive>false</CaseSensitive>
    <AfterProcessing>false</AfterProcessing>
    <SkipNoFindAndReplace>false</SkipNoFindAndReplace>
    <SkipMinorFindAndReplace>false</SkipMinorFindAndReplace>
    <SkipNoRegexTypoFix>false</SkipNoRegexTypoFix>
    <SkipNoDisambiguation>false</SkipNoDisambiguation>
    <SkipNoLinksOnPage>false</SkipNoLinksOnPage>
    <GeneralSkipList />
  </SkipOptions>
  <Module>
    <Enabled>true</Enabled>
    <Language>C# 3.5</Language>
    <Code>// implementing the "aggressive" rules is more likely to produce false positives
private static readonly bool AGGRESSIVE = true;
private static readonly Regex ListingTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;("listing,see,do,buy,eat,drink,sleep".Split(',')));
private static readonly string[] ListingTemplateParamNames = {"type","nome","alt","sito","email","indirizzo","lat","long","indicazioni","tel","numero verde","fax","orari","checkin","checkout","prezzo","descrizione"};
private static readonly string[] ListingPhoneParamNames = {"tel","fax","numero verde"};
private static readonly Regex PhoneNumberRegex = new Regex(@"'*[\d\+\(][\s\d\(\)\-\.'\+]+[\d\)]'*");
private static readonly Regex MailtoRegex = new Regex(@"mailto:[/]*", RegexOptions.IgnoreCase);
private static readonly Regex ExcessWhitespaceRegex = new Regex(@"\s\s+", RegexOptions.Singleline);
// "http://www.example.com"
private static readonly string ValidUrlPattern = @"((http(s)?:)//)?(([a-z]+\.)+)([a-z]+)";
private static readonly Regex ValidUrlRegex = new Regex(ValidUrlPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase);
// "[http://www.example.com]"
private static readonly Regex FootnoteUrlRegex = new Regex(@"\[(" + ValidUrlPattern + @"([^\]\s]+))\]", RegexOptions.Singleline);
// "Foo (disambiguation)"
private static readonly Regex CityNameWithDisambiguationRegex = new Regex(@"([^\(]+) \([^\)]+\)", RegexOptions.Singleline);
// "blah, CA 99999", "blah CA", etc
private static readonly Regex AddressWithStateOrZipRegex = new Regex(@"(.+)[\.,\-]+\s*(AL|alabama|AK|alaska|AZ|arizona|AR|arkansas|CA|california|CO|colorado|CT|connecticut|DC|DE|delaware|FL|florida|GA|georgia|HI|hawaii|ID|idaho|IL|illinois|IN|indiana|IA|iowa|KS|kansas|KY|kentucky|LA|louisiana|ME|maine|MD|maryland|MA|massachusetts|MI|michigan|MN|minnesota|MS|mississippi|MO|missouri|MT|montana|NE|nebraska|NV|nevada|NH|new hampshire|NJ|new jersey|NM|new mexico|NY|new york|NC|north carolina|ND|north dakota|OH|ohio|OK|oklahoma|OR|oregon|PA|pennsylvania|RI|rhode island|SC|south carolina|SD|south dakota|TN|tennessee|TX|texas|UT|utah|VT|vermont|VA|virginia|WA|washington|WV|west virginia|WI|wisconsin|WY|wyoming)([\s,\-]*[0-9]{5})?$", RegexOptions.Singleline | RegexOptions.IgnoreCase);
// "* ", "** ", etc
private static readonly Regex EmptyListItemRegex = new Regex(@"^\*+\s*\n", RegexOptions.Multiline);
private static readonly Regex FootnoteToFrontLinkRegex = new Regex(@"('*)((?!The )\p{Lu}[\w\-'/]*[\w]( (e|del|di|da|&amp;|il|lo|la|le|per|\p{Lu}[\w\-'/]*[\w]))*)('*)[, ]*\[(http[^ ]+)( )*\]");
private static readonly Regex TimeValuesShouldUseColonAsSeperator = new Regex(@"\b([1-9]|10|11|12)\.([0-5][0-9])([ ]*)((a|p)\.?\s*m\.|(a|p)\.?\s*m\b)", RegexOptions.IgnoreCase);
private static readonly Regex TimeValuesSuffixAM = new Regex(@"\b([1-9]|10|11|12)(:[0-5][0-9])*[ ]*(a\.\s*m\.|a\s*m\b)", RegexOptions.IgnoreCase);
private static readonly Regex TimeValuesSuffixPM = new Regex(@"\b([1-9]|10|11|12)(:[0-5][0-9])*[ ]*(p\.\s*m\.|p\s*m\b)", RegexOptions.IgnoreCase);
private static readonly Regex ExternalToInternalLinkWikipedia = new Regex(@"\[http[s]?://it.wikipedia.org/wiki/([^\] ]+)[ ]+([^\]]+)]", RegexOptions.IgnoreCase);
private static readonly Regex ExternalToInternalLinkWikipediaNoText = new Regex(@"\[http[s]?://it.wikipedia.org/wiki/([^\] ]+)[ ]*]", RegexOptions.IgnoreCase);
private static readonly Regex ExternalToInternalLinkWikivoyage = new Regex(@"\[http[s]?://it.wikivoyage.org/wiki/([^\] ]+)[ ]+([^\]]+)]", RegexOptions.IgnoreCase);
private static readonly Regex ExternalToInternalLinkWikivoyageNoText = new Regex(@"\[http[s]?://it.wikivoyage.org/wiki/([^\] ]+)[ ]*]", RegexOptions.IgnoreCase);
// "* blah blah blah", "** blah blah blah", etc
private static readonly Regex CandidateListingItemRegex = new Regex(@"^\*+\s*([^\{]{2}.+)$", RegexOptions.Multiline);
private static readonly Regex ListingNameRegex = new Regex(@"(il\s+)*'''(.{3,}?)'''", RegexOptions.IgnoreCase);
// "[http://www.example.com/ Example Text]"
private static readonly Regex ExternalLinkWithTextRegex = new Regex(@"\[(http[^\]\s]+)\s+([^\]]+)\]", RegexOptions.IgnoreCase);
// "123-456-7890"
private static readonly string ListingPhoneNumber = @"((''|\+|\()*\d+(''|\)*)[\s\-]+)+(''|\+|\()*\d+(''|\)*)( ext\.? \d+)?";
private static readonly Regex ListingPhoneNumberRegex = new Regex(ListingPhoneNumber, RegexOptions.IgnoreCase);
// "fax: 123-456-7890"
private static readonly string ListingFaxNumber = @"(\(''|''\(|\()?fax(:)?(\s)*(" + ListingPhoneNumber + @")(''\)|\)''|\))?";
private static readonly Regex ListingFaxNumberRegex = new Regex(ListingFaxNumber, RegexOptions.IgnoreCase);
// "tele: 123-456-7890" and similar
private static readonly string ListingPhoneNumberWithLabel = @"(\(''|''\(|\()?(\u260e|chiama|call:telefono:|telephone|tel:|tel\.:|tel\.|tel|tel:|tel|ph:|ph\.:|ph\.|ph|\u260E)(\s)*(" + ListingPhoneNumber + @")(''\)|\)''|\))?";
private static readonly Regex ListingPhoneNumberWithLabelRegex = new Regex(ListingPhoneNumberWithLabel, RegexOptions.IgnoreCase);
// "toll-free: 123-456-7890" and similar
private static readonly string ListingTollfreeNumber = @"(\(''|''\(|\()?(toll[ \-]?free)(:)?(\s)*(" + ListingPhoneNumber + @")(''\)|\)''|\))?";
private static readonly Regex ListingTollfreeNumberRegex = new Regex(ListingTollfreeNumber, RegexOptions.IgnoreCase);
private static readonly string InvalidLeadingOrTrailingPunctuation = @",|\-|\*|\:|\–";
private static readonly string InvalidLeadingPunctuation = @"\.|!|\?|\)|\]|\}|&amp;mdash;";
private static readonly string InvalidTrailingPunctuation = @"\(|\[|\{";
private static readonly string InvalidDuplicatePunctuation = @"\.|!|\?|" + InvalidLeadingOrTrailingPunctuation;
private static readonly Regex InvalidLeadingPunctuationRegex = new Regex(@"^(\s|" + InvalidLeadingPunctuation + "|" + InvalidLeadingOrTrailingPunctuation + @")+", RegexOptions.Multiline);
private static readonly Regex InvalidTrailingPunctuationRegex = new Regex(@"(\s|" + InvalidTrailingPunctuation + "|" + InvalidLeadingOrTrailingPunctuation + @")+$", RegexOptions.Multiline);
private static readonly Regex InvalidDuplicatePunctuationRegex = new Regex(@"(" + InvalidDuplicatePunctuation + @"|\s)+(" + InvalidDuplicatePunctuation + @")");
// "email: foo@bar.com" OR "mailto:foo@bar.com" OR "foo@bar.com"
private static readonly string ListingEmail = @"(mailto:|e-mail:)?\s*(\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b)";
private static readonly Regex ListingEmailRegex = new Regex(ListingEmail, RegexOptions.IgnoreCase);
// "1234 First St"
private static readonly string ListingAddress = @"([\d]+([/\-][\d]+)? ([nesw]\.? )?([\p{L}\d]+[ \.\-]*){1,3} (avenue|ave|av|boulevard|blvd|court|ct|drive|dr|expressway|expwy|freeway|fwy|highway( \d{1,3})?|hwy( \d{1,3})?|lane|ln|loop|parkway|pkwy|place|pl|road|rd|row|street|st|way|via|viale|piazza|gåta|väg|Straße|Strasse|parcheggio|statale|ulica|ulitsa|uliza|vicolo)\b(\.? (#(\s)*[\d]+|nord|nordest|Nord|Est|NO|N|Est|E|Sud|SE|SO|S|Ovest|O)\b)?)[\. , ]*";
private static readonly Regex ListingAddressRegex = new Regex(ListingAddress, RegexOptions.IgnoreCase);
// the above pattern will match things like "25 km by road", so add a pattern to catch those
private static readonly string ListingAddressFalsePositives = @"\b(km|kilometer|kilometers|mi|mile|miles)\b";
private static readonly Regex ListingAddressFalsePositivesRegex = new Regex(ListingAddressFalsePositives, RegexOptions.IgnoreCase);
// "Calle Ricardo Montalban, 452"
private static readonly string ListingAddressInternational = @"(avenida|ave|av|calle|estrada|est|rua)(\.)? ([\p{L}\d]+[ \.\-]*){1,3}, [\d]+([/\-][\d]+)?";
private static readonly Regex ListingAddressInternationalRegex = new Regex(ListingAddressInternational, RegexOptions.IgnoreCase);
private static readonly Regex ListingAddressIsDirectionsRegex = new Regex(@"^(between|corner|end|next|on|)\s", RegexOptions.Multiline);
//private static readonly Regex CityStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;("outlinecity,usablecity,guidecity,starcity".Split(',')));
//private static readonly Regex CountryStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;("outlinecountry,usablecountry,guidecountry,starcountry".Split(',')));
//private static readonly Regex DiveguideStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;("outlinediveguide,usablediveguide,guidediveguide,stardiveguide".Split(',')));
//private static readonly Regex DistrictStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;/("outlinedistrict,usabledistrict,guidedistrict,stardistrict".Split(',')));
//private static readonly Regex ItineraryStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;("outlineitinerary,usableitinerary,guideitinerary,staritinerary".Split(',')));
//private static readonly Regex ParkStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;("outlinepark,usablepark,guidepark,starpark".Split(',')));
//private static readonly Regex PhrasebookStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;("outlinephrasebook,usablephrasebook,guidephrasebook,starphrasebook".Split(',')));
//private static readonly Regex RegionStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;("outlineregion,usableregion,guideregion,starregion".Split(',')));
//private static readonly Regex TopicStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List&lt;string&gt;("outlinetopic,usabletopic,guidetopic,startopic".Split(',')));
//private static readonly Regex ListingAltParamRegex = new Regex(@"\|\s*alt\s*=", RegexOptions.Singleline);
// "()", "[]", "{}"
private static readonly Regex EmptyPunctuationRegex = new Regex(@"(\(\s*\)|\[\s*\]|\{\s*\})");
private static readonly Regex OnlyPunctuationRegex = new Regex(@"^['\-\(\)\[\]\{\}\*\.\?!\s]+$", RegexOptions.Singleline);
// match a single digit
private static readonly Regex DigitRegex = new Regex(@"\d");
private static readonly Regex DoubleSpaceRegex = new Regex(@"\s{2,}");
private static readonly Regex InvalidGetInHeadingRegex = new Regex(@"^(get in|Arrivare|come arrivare|getting in|getting there)", RegexOptions.IgnoreCase);
private static readonly Regex InvalidGetAroundHeadingRegex = new Regex(@"^(get around|getting around)", RegexOptions.IgnoreCase);
private static readonly Regex InvalidSeeHeadingRegex = new Regex(@"^(Monumenti|monumenti|Vedere|Attrazioni|attrazioni)", RegexOptions.IgnoreCase);
private static readonly Regex InvalidDoHeadingRegex = new Regex(@"^(Attività|Tempo libero)", RegexOptions.IgnoreCase);
private static readonly Regex InvalidBuyHeadingRegex = new Regex(@"^(shopping|negozi)", RegexOptions.IgnoreCase);
private static readonly Regex InvalidEatHeadingRegex = new Regex(@"^(ristoranti|a pranzo|Mangiare)", RegexOptions.IgnoreCase);
private static readonly Regex InvalidDrinkHeadingRegex = new Regex(@"^(bars|nightlife)", RegexOptions.IgnoreCase);
private static readonly Regex InvalidSleepHeadingRegex = new Regex(@"^(accommodation|hotels)", RegexOptions.IgnoreCase);
private static readonly Regex InvalidGoNextHeadingRegex = new Regex(@"^(nei dintorni|Uscire)", RegexOptions.IgnoreCase);
private static readonly Regex MidrangeHeadingRegex = new Regex(@"^prezzi[ \-]*modici", RegexOptions.IgnoreCase);
private static readonly Regex ByOnHeadingRegex = new Regex(@"^(presso|su) (.+)", RegexOptions.IgnoreCase);
public string ProcessArticle(string articleText, string articleTitle, int wikiNamespace, out string summary, out bool skip) {
	string originalText = articleText;
	summary = "";
	skip = false;
	articleText = UpdateHeadings(articleText, articleTitle, wikiNamespace, ref summary, ref skip);
	articleText = ExternalToInternalLink(articleText, articleTitle, wikiNamespace, ref summary, ref skip);
	articleText = FootnoteToFrontlink(articleText, articleTitle, wikiNamespace, ref summary, ref skip);
	articleText = FormatTimeValues(articleText, articleTitle, wikiNamespace, ref summary, ref skip);
	if (AGGRESSIVE) {
		articleText = ConvertTextToListings(articleText, articleTitle, wikiNamespace, ref summary, ref skip);
	}
	articleText = FormatListings(articleText, articleTitle, wikiNamespace, ref summary, ref skip);
	if (articleText.Equals(originalText)) {
		skip = true;
	}
	return articleText;
}
// ensure that headings match the article templates
public string UpdateHeadings(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) { 
	foreach(Match m in WikiRegexes.Headings.Matches(articleText)) {
		string originalHeading = m.Value;
		string originalTitle = m.Groups[1].Value;
		string newTitle = originalTitle;
		string lowerTitle = originalTitle.ToLower().Trim();
		int headingLevel = 1;
		while (originalHeading[headingLevel] == '=') {
			headingLevel++;
		}
		Match match = null;
		if (headingLevel == 2) {
			if (MatchText(lowerTitle, InvalidGetInHeadingRegex, ref match)) {
				newTitle = "Come arrivare";
			} else if (MatchText(lowerTitle, InvalidGetAroundHeadingRegex, ref match)) {
				newTitle = "Come spostarsi";
			} else if (MatchText(lowerTitle, InvalidSeeHeadingRegex, ref match)) {
				newTitle = "Cosa vedere";
			} else if (MatchText(lowerTitle, InvalidDoHeadingRegex, ref match)) {
				newTitle = "Cosa fare";
			} else if (MatchText(lowerTitle, InvalidBuyHeadingRegex, ref match)) {
				newTitle = "Acquisti";
			} else if (MatchText(lowerTitle, InvalidEatHeadingRegex, ref match)) {
				newTitle = "Dove mangiare";
			} else if (MatchText(lowerTitle, InvalidDrinkHeadingRegex, ref match)) {
				newTitle = "Come divertirsi";
			} else if (MatchText(lowerTitle, InvalidSleepHeadingRegex, ref match)) {
				newTitle = "Dove alloggiare";
			} else if (MatchText(lowerTitle, InvalidGoNextHeadingRegex, ref match)) {
				newTitle = "Nei dintorni";
			}
		} else {
			if (MatchText(lowerTitle, MidrangeHeadingRegex, ref match)) {
				newTitle = "Prezzi modici";
			} else if (MatchText(lowerTitle, ByOnHeadingRegex, ref match)) {
				newTitle = Capitalize(match.Groups[1].Value) + " " + match.Groups[2].Value.ToLower();
			}
		}
		if (!newTitle.Equals(originalTitle)) {
			string headingBars = originalHeading.Substring(0, headingLevel);
			articleText = articleText.Replace(originalHeading, headingBars + newTitle + headingBars);
			summary = UpdateEditSummary(summary, "sistemo sezioni");
		}
	}
	return articleText;
}

// convert footnote links to frontlinks
public string FootnoteToFrontlink(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) {
	string originalText = articleText;
	articleText = FootnoteToFrontLinkRegex.Replace(articleText, "$1[$6 $2]$5");
	if (!articleText.Equals(originalText)) {
		summary = UpdateEditSummary(summary, "sistemo note");
	}
	return articleText;
}
// convert external links to interwiki/internal links
public string ExternalToInternalLink(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) {
	string originalText = articleText;
	articleText = ExternalToInternalLinkWikipedia.Replace(articleText, "[[w:$1|$2]]");
	articleText = ExternalToInternalLinkWikipediaNoText.Replace(articleText, "[[w:$1]]");
	articleText = ExternalToInternalLinkWikivoyage.Replace(articleText, "[[$1|$2]]");
	articleText = ExternalToInternalLinkWikivoyageNoText.Replace(articleText, "[[$1]]");
	if (!articleText.Equals(originalText)) {
		summary = UpdateEditSummary(summary, "fix link");
	}
	return articleText;
}
public string FormatTimeValues(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) {
	string originalText = articleText;
	articleText = TimeValuesShouldUseColonAsSeperator.Replace(articleText, "$1:$2$3$4");
	articleText = TimeValuesSuffixAM.Replace(articleText, "$1$2AM");
	articleText = TimeValuesSuffixPM.Replace(articleText, "$1$2PM");
	if (!articleText.Equals(originalText)) {
		summary = UpdateEditSummary(summary, "sistemo date");
	}
	return articleText;
}
public string ConvertTextToListings(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) {
	//if (!IsCityArticle(articleText) &amp;&amp; !IsDistrictArticle(articleText) &amp;&amp; !IsParkArticle(articleText)) {
		// do not try to convert text to listings for non-city or park articles
		//return articleText;
	//}
	string originalText = articleText;
	// loop through all sections
	foreach(KeyValuePair&lt;string, string&gt; sectionData in SplitToSecondLevelSections(articleText)) {
		string sectionName = sectionData.Key;
		if (!sectionName.ToLower().Equals("see") &amp;&amp; !sectionName.ToLower().Equals("do") &amp;&amp; !sectionName.ToLower().Equals("buy") &amp;&amp; !sectionName.ToLower().Equals("eat") &amp;&amp; !sectionName.ToLower().Equals("drink") &amp;&amp; !sectionName.ToLower().Equals("sleep")) {
			// only convert text that's in a section that supports non-generic listings
			continue;
		}
		string listingType = GetValidListingTypeForSection(sectionName);
		string sectionText = sectionData.Value;
		// get all list items within the section

		foreach(Match m in CandidateListingItemRegex.Matches(sectionText)) {
			string listItemText = m.Groups[1].Value;
			string templateCall = ConvertListingItemtoTemplatedListing(listItemText, listingType, ref summary);
			if (templateCall != "") {
				articleText = articleText.Replace(listItemText, templateCall);
				summary = UpdateEditSummary(summary, "converto in listing");
			}
		}
	}
	return articleText;
}
public string ConvertListingItemtoTemplatedListing(string listItemText, string listingType, ref string summary) {
	string templateCall = "{{" + listingType + "}}";
	if (!ProcessListingNameInListItem(ref listItemText, ref templateCall)) {
		// if we don't have a listing name don't bother trying to convert anything else
		return "";
	}
	ProcessListingPhoneInListItem(ref listItemText, ref templateCall);
	ProcessListingEmailInListItem(ref listItemText, ref templateCall);
	ProcessListingUrlInListItem(ref listItemText, ref templateCall);
	ProcessListingAddressInListItem(ref listItemText, ref templateCall);
	ProcessListingContentInListItem(ref listItemText, ref templateCall);
	return templateCall;
}
private bool ProcessListingNameInListItem(ref string listItemText, ref string templateCall) {
	Match m = ListingNameRegex.Match(listItemText);
	if (!m.Success || m.Index != 0) {
		// if there isn't a name at the beginning of the listing, don't convert
		return false;
	}
	string nome = m.Groups[2].Value;
	templateCall = Tools.SetTemplateParameterValue(templateCall, "nome", nome);
	// see if the nome is front-linked
	Match sitoMatch = ExternalLinkWithTextRegex.Match(nome);
	if (sitoMatch.Success &amp;&amp; sitoMatch.Index == 0) {
		// split the nome &amp; sito fields
		string sito = sitoMatch.Groups[1].Value;
		templateCall = Tools.SetTemplateParameterValue(templateCall, "sito", sito);
		nome = sitoMatch.Groups[2].Value;
		templateCall = Tools.SetTemplateParameterValue(templateCall, "nome", nome);
	}
	// remove nome from list item text
	listItemText = RemoveValueFromListItemText(listItemText, m.Value);
	return true;
}
private void ProcessListingPhoneInListItem(ref string listItemText, ref string templateCall) {
	Match telMatch = ListingPhoneNumberWithLabelRegex.Match(listItemText);
	if (telMatch.Success) {
		string tel = telMatch.Groups[4].Value;
		templateCall = Tools.SetTemplateParameterValue(templateCall, "tel", tel);
		listItemText = RemoveValueFromListItemText(listItemText, telMatch.Value);
	}
	Match faxMatch = ListingFaxNumberRegex.Match(listItemText);
	if (faxMatch.Success) {
		string fax = faxMatch.Groups[4].Value;
		templateCall = Tools.SetTemplateParameterValue(templateCall, "fax", fax);
		listItemText = RemoveValueFromListItemText(listItemText, faxMatch.Value);
	}
	Match tollfreeMatch = ListingTollfreeNumberRegex.Match(listItemText);
	if (tollfreeMatch.Success) {
		string tollfree = tollfreeMatch.Groups[5].Value;
		templateCall = Tools.SetTemplateParameterValue(templateCall, "tollfree", "numero verde");
		listItemText = RemoveValueFromListItemText(listItemText, tollfreeMatch.Value);
	}
	if (!telMatch.Success) {
		// try to find a tel number without a label
		telMatch = ListingPhoneNumberRegex.Match(listItemText);
		if (telMatch.Success) {
			string tel = telMatch.Value;
			if (DigitRegex.Matches(tel).Count &gt; 6) {
				// only consider a tel number valid if it contains more than six digits
				templateCall = Tools.SetTemplateParameterValue(templateCall, "tel", tel);
				listItemText = RemoveValueFromListItemText(listItemText, telMatch.Value);
			}
		}
	}
}
private void ProcessListingEmailInListItem(ref string listItemText, ref string templateCall) {
	Match emailMatch = ListingEmailRegex.Match(listItemText);
	if (emailMatch.Success) {
		string email = emailMatch.Groups[2].Value;
		templateCall = Tools.SetTemplateParameterValue(templateCall, "email", email);
		listItemText = RemoveValueFromListItemText(listItemText, emailMatch.Value);
	}
}
private void ProcessListingUrlInListItem(ref string listItemText, ref string templateCall) {
	if (Tools.GetTemplateParameterValue(templateCall, "sito") != "") {
		// sito was already set when processing listing nome
		return;
	}
	Match sitoMatch = FootnoteUrlRegex.Match(listItemText);
	if (sitoMatch.Success) {
		string sito = sitoMatch.Groups[1].Value;
		templateCall = Tools.SetTemplateParameterValue(templateCall, "sito", sito);
		listItemText = RemoveValueFromListItemText(listItemText, sitoMatch.Value);
	}
}
private void ProcessListingAddressInListItem(ref string listItemText, ref string templateCall) {
	Match indirizzoMatch = ListingAddressRegex.Match(listItemText);
	if (indirizzoMatch.Success) {
		string indirizzo = indirizzoMatch.Groups[1].Value;
		Match falsePositiveMatch = ListingAddressFalsePositivesRegex.Match(indirizzo);
		if (!falsePositiveMatch.Success) {
			templateCall = Tools.SetTemplateParameterValue(templateCall, "indirizzo", indirizzo);
			listItemText = RemoveValueFromListItemText(listItemText, indirizzoMatch.Value);
		}
	} else {
		indirizzoMatch = ListingAddressInternationalRegex.Match(listItemText);
		if (indirizzoMatch.Success) {
			string indirizzo = indirizzoMatch.Groups[1].Value;
			templateCall = Tools.SetTemplateParameterValue(templateCall, "indirizzo", indirizzo);
			listItemText = RemoveValueFromListItemText(listItemText, indirizzoMatch.Value);
		}
	}
}
private void ProcessListingContentInListItem(ref string listItemText, ref string templateCall) {
	if (String.IsNullOrEmpty(listItemText)) {
		return;
	}
	// strip empty punctuation
	listItemText = EmptyPunctuationRegex.Replace(listItemText, "");
	// strip sentence fragments left over from removing the listing nome
	if (listItemText.ToLower().StartsWith("is ")) {
		listItemText = listItemText.Substring("is ".Length);
	}
	// make sure first character is capitalized
	listItemText = Capitalize(listItemText);
	// if only punctuation is left, remove everything
	if (OnlyPunctuationRegex.IsMatch(listItemText)) {
		listItemText = "";
	}
	templateCall = Tools.SetTemplateParameterValue(templateCall, "descrizione", listItemText);
}
private string RemoveValueFromListItemText(string listItemText, string value) {
	listItemText = listItemText.Replace(value, "").Trim();
	listItemText = InvalidDuplicatePunctuationRegex.Replace(listItemText, "$1");
	listItemText = StripLeadingPunctuation(listItemText).Trim();
	return listItemText;
}
// Perform various tasks on listings to ensure params and other values
// are formatted correctly.
public string FormatListings(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) {
	string originalText = articleText;
	// loop through all sections
	foreach(KeyValuePair&lt;string, string&gt; sectionData in SplitToSecondLevelSections(articleText)) {
		string sectionName = sectionData.Key;
		string sectionText = sectionData.Value;
		// get all listing tags within the section
		foreach(Match m in ListingTemplateNamesRegex.Matches(sectionText)) {
			string templateCall = m.Value;
			string originalTemplateCall = m.Value;
			templateCall = ConvertGenericListingToSpecificType(templateCall, ref summary);
			templateCall = MatchListingTypeToSection(templateCall, sectionName, ref summary);
			templateCall = FormatListingParams(templateCall, ref summary);
			templateCall = SanitizeListingPhoneNumbers(templateCall, ref summary);
			templateCall = SanitizeListingEmail(templateCall, ref summary);
			templateCall = SanitizeListingUrl(templateCall, ref summary);
			if (AGGRESSIVE) {
				templateCall = SanitizeListingAddress(templateCall, articleTitle, ref summary);
			}
			if (!templateCall.Equals(originalTemplateCall)) {
				articleText = articleText.Replace(originalTemplateCall, templateCall);
			}
		}
	}
	return articleText;
}
// change "{{listing|type=xyz|...}}" to "{{xyz|...}}"
public string ConvertGenericListingToSpecificType(string templateCall, ref string summary) {
	string originalTemplateCall = templateCall;
	string listingType = Tools.GetTemplateName(templateCall);
	if (listingType.Equals("listing")) {
		string templateType = Tools.GetTemplateParameterValue(templateCall, "type");
		if (templateType.Equals("see") || templateType.Equals("do") || templateType.Equals("buy") || templateType.Equals("eat") || templateType.Equals("drink") || templateType.Equals("sleep")) {
			templateCall = Tools.RenameTemplate(templateCall, templateType);
			templateCall = Tools.RemoveTemplateParameter(templateCall, "type");
		}
	}
	if (!templateCall.Equals(originalTemplateCall)) {
		summary = UpdateEditSummary(summary, "listing appropriato");
	}
	return templateCall;
}
// make sure listings are formatted according to the style guidelines in
// Wikivoyage:Listings
public string FormatListingParams(string templateCall, ref string summary) {
	string originalTemplateCall = templateCall;
	string listingType = Tools.GetTemplateName(templateCall);
	string formattedValue = "{{" + listingType + "\n";
	// loop through expected template arguments and format appropriately
	foreach(string param in ListingTemplateParamNames) {
		if (param.Equals("descrizione")) {
			continue;
		}
		string paramValue = Tools.GetTemplateParameterValue(templateCall, param);
		if (param.Equals("type") &amp;&amp; (paramValue == "" || !listingType.Equals("listing"))) {
			// only listing uses the "type" attribute
			if (paramValue == "") {
				templateCall = Tools.RemoveTemplateParameter(templateCall, param);
			}
			continue;
		}
		if ((param.Equals("image") || param.Equals("lastedit")) &amp;&amp; paramValue == "") {
			// empty image &amp; lastedit attributes are unnecessary
			continue;
		}
		if (listingType.Equals("sleep") &amp;&amp; param.Equals("orari") &amp;&amp; paramValue == "") {
			// sleep listings don't use the "orari" attribute
			if (paramValue == "") {
				templateCall = Tools.RemoveTemplateParameter(templateCall, param);
			}
			continue;
		}
		if (!listingType.Equals("sleep") &amp;&amp; (param.Equals("checkin") || param.Equals("checkout"))) {
			// only sleep listings use the "checkin" and "checkout" attributes
			if (paramValue == "") {
				templateCall = Tools.RemoveTemplateParameter(templateCall, param);
			}
			continue;
		}
		//if (param.Equals("alt") &amp;&amp; paramValue == "" &amp;&amp; !ListingAltParamRegex.IsMatch(templateCall)) {
			// do not add an alt tag if it isn't already present
			//continue;
		//}
		// replace excess whitespace with single spaces
		paramValue = DoubleSpaceRegex.Replace(paramValue, " ");
		formattedValue += "| " + param + "=" + paramValue;
		// add either a newline or a space after the param value, depending on param and template type
		if (param.Equals("email") || param.Equals("indicazioni") || param.Equals("fax") || param.Equals("prezzo") || param.Equals("image") || param.Equals("lastedit")) {
			formattedValue += "\n";
		} else {
			formattedValue += " ";
		}
		templateCall = Tools.RemoveTemplateParameter(templateCall, param);
	}
	// loop through any unexpected template args and format on their own lines
	int remainingTemplateArgs = Tools.GetTemplateArgumentCount(templateCall);
	foreach(KeyValuePair&lt;string, string&gt; templateParameter in Tools.GetTemplateParameterValues(templateCall)) {
		string param = templateParameter.Key;
		if (param.Equals("descrizione")) {
			continue;
		}
		string paramValue = templateParameter.Value;
		if (paramValue == "") {
			// any empty, unrecognized listing params can be removed
			continue;
		}
		formattedValue += "| " + param + "=" + paramValue + "\n";
	}
	// now add template descrizione on its own line
	formattedValue += "| descrizione=" + Tools.GetTemplateParameterValue(templateCall, "descrizione") + "\n";
	formattedValue += "}}";
	if (!originalTemplateCall.Equals(formattedValue)) {
		// suppress edit summary for now - it is being applied to any article with listings
		// whether they are updated or not
		// summary = UpdateEditSummary(summary, "formato listing");
	}
	return formattedValue;
}
// update the listing tel number fields as much as possible to match
// Wikivoyage:Phone numbers
public string SanitizeListingPhoneNumbers(string templateCall, ref string summary) {
	string originalTemplateCall = templateCall;
	// loop through expected template arguments and format appropriately
	foreach(string param in ListingPhoneParamNames) {
		string paramValue = Tools.GetTemplateParameterValue(templateCall, param);
		paramValue = SanitizePhoneNumber(paramValue);
		templateCall = Tools.UpdateTemplateParameterValue(templateCall, param, paramValue);
	}
	if (!templateCall.Equals(originalTemplateCall)) {
		summary = UpdateEditSummary(summary, "formato phone");
	}
	return templateCall;
}
// update the listing email field to ensure it is valid
public string SanitizeListingEmail(string templateCall, ref string summary) {
	string originalTemplateCall = templateCall;
	string email = Tools.GetTemplateParameterValue(templateCall, "email");
	email = MailtoRegex.Replace(email, "").Trim();
	templateCall = Tools.UpdateTemplateParameterValue(templateCall, "email", email);
	if (!templateCall.Equals(originalTemplateCall)) {
		summary = UpdateEditSummary(summary, "fix e-mail");
	}
	return templateCall;
}
// update the listing URL field to ensure it is valid
public string SanitizeListingUrl(string templateCall, ref string summary) {
	string originalTemplateCall = templateCall;
	string sito = Tools.GetTemplateParameterValue(templateCall, "sito");
	Match match = FootnoteUrlRegex.Match(sito);
	if (match.Success) {
		sito = match.Groups[1].Value;
	}
	match = ValidUrlRegex.Match(sito);
	if (match.Success &amp;&amp; !sito.ToLower().StartsWith("http://") &amp;&amp; !sito.ToLower().StartsWith("https://") &amp;&amp; !sito.ToLower().StartsWith("//")) {
		sito = "http://" + sito;
	}
	templateCall = Tools.UpdateTemplateParameterValue(templateCall, "sito", sito);
	if (!templateCall.Equals(originalTemplateCall)) {
		summary = UpdateEditSummary(summary, "sistemo indirizzo web");
	}
	return templateCall;
}
// update the listing indirizzo field to ensure it is valid
public string SanitizeListingAddress(string templateCall, string articleName, ref string summary) {
	string originalTemplateCall = templateCall;
	string indirizzo = Tools.GetTemplateParameterValue(templateCall, "indirizzo");
	if (String.IsNullOrEmpty(indirizzo)) {
		return templateCall;
	}
	Match m = ListingAddressIsDirectionsRegex.Match(indirizzo);
	if (m.Success) {
		// the indirizzo field belongs in the indicazioni field
		string indicazioni = Tools.GetTemplateParameterValue(templateCall, "indicazioni");
		if (String.IsNullOrEmpty(indicazioni)) {
			templateCall = Tools.UpdateTemplateParameterValue(templateCall, "indicazioni", indirizzo);
			templateCall = Tools.UpdateTemplateParameterValue(templateCall, "indirizzo", "");
			summary = UpdateEditSummary(summary, "indicazioni");
			return templateCall;
		}
	}
	// strip out state and zip code if present
	m = AddressWithStateOrZipRegex.Match(indirizzo);
	if (m.Success) {
		indirizzo = m.Groups[1].Value.Trim();
	}
	indirizzo = StripStrayPunctuation(indirizzo);
	// strip out the city if it is present
	string city = GetCityFromArticleName(articleName);
	if (indirizzo.ToLower().EndsWith(city.ToLower())) {
		int pos = indirizzo.ToLower().LastIndexOf(city.ToLower());
		indirizzo = indirizzo.Substring(0, pos).Trim();
	}
	indirizzo = StripStrayPunctuation(indirizzo);
	// properly abbreviate street name
	indirizzo = AbbreviateStreeType(indirizzo, "via", "Via");
	indirizzo = AbbreviateStreeType(indirizzo, "Piazza", "Pz");
	indirizzo = AbbreviateStreeType(indirizzo, "Viale", "V.le");
	indirizzo = AbbreviateStreeType(indirizzo, "Ulica", "Ul");
	indirizzo = AbbreviateStreeType(indirizzo, "Ulitsa", "Ul");
	indirizzo = AbbreviateStreeType(indirizzo, "Uliza", "Ul.");
	indirizzo = AbbreviateStreeType(indirizzo, "Prospekt", "Pr");
	indirizzo = AbbreviateStreeType(indirizzo, "Strasse", "Str");
	indirizzo = AbbreviateStreeType(indirizzo, "Straße", "Str");
	templateCall = Tools.UpdateTemplateParameterValue(templateCall, "indirizzo", indirizzo);
	if (!templateCall.Equals(originalTemplateCall)) {
		summary = UpdateEditSummary(summary, "indirizzi");
	}
	return templateCall;
}
// make sure that the listing type matches the section in which the listing
// is found (example: "see" listings in the "See" section)
public string MatchListingTypeToSection(string templateCall, string sectionName, ref string summary) {
	string originalTemplateCall = templateCall;
	if (sectionName.ToLower() == "eat and drink" || sectionName.ToLower() == "see and do") {
		// skip these "combined" sections
		return templateCall;
	}
	string expectedListingType = GetValidListingTypeForSection(sectionName);
	string listingType = Tools.GetTemplateName(templateCall);
	if (!listingType.Equals(expectedListingType)) {
		templateCall = Tools.RenameTemplate(templateCall, expectedListingType);
	}
	if (!templateCall.Equals(originalTemplateCall)) {
		summary = UpdateEditSummary(summary, "aggiorno listing");
	}
	return templateCall;
}
// return a map of section name-section descrizione for all second level headings.
// the opening text of the article is returned without a section name
private static List&lt;KeyValuePair&lt;string, string&gt;&gt; SplitToSecondLevelSections(string articleText) {
	List&lt;KeyValuePair&lt;string, string&gt;&gt; sections = new List&lt;KeyValuePair&lt;string, string&gt;&gt;();
	int lastmatchpos = 0;
	Match lastMatch = null;
	foreach(Match m in WikiRegexes.HeadingLevelTwo.Matches(articleText)) {
		if (m.Index &gt; 0) {
			// Don't add empty first section if page starts with heading
			string sectionContent = articleText.Substring(lastmatchpos, m.Index-lastmatchpos);
			string sectionName = (lastMatch != null) ? lastMatch.Groups[1].Value.Trim() : "";
			sections.Add(new KeyValuePair&lt;string, string&gt;(sectionName, sectionContent));
		}
		lastmatchpos = m.Index;
		lastMatch = m;
	}
	// Add text of final section
	string sectionContentLast = articleText.Substring(lastmatchpos);
	string sectionNameLast = (lastMatch != null) ? lastMatch.Groups[1].Value : "";
	sections.Add(new KeyValuePair&lt;string, string&gt;(sectionNameLast, sectionContentLast));
	return sections;
}
// return the expected listing type for the given section name ("See" returns "see").
private static string GetValidListingTypeForSection(string sectionName) {
	if (sectionName == "Cosa vedere") {
		return "see";
	} if (sectionName == "Cosa fare") {
		return "do";
	} if (sectionName == "Acquisti") {
		return "buy";
	} if (sectionName == "Dove mangiare" || sectionName.ToLower() == "Mangiare") {
		return "eat";
	} if (sectionName == "Come divertirsi") {
		return "drink";
	} if (sectionName == "Dove alloggiare") {
		return "sleep";
	} else {
		return "listing";
	}
}
private static string SanitizePhoneNumber(string telNumberText) {
	// strip out the tel number, in case it is contained within other text
	// such as "888-888-8888 (front office)"
	Match match = PhoneNumberRegex.Match(telNumberText);
	if (match.Success) {
		string telNumber = match.Value;
		string originalPhoneNumber = match.Value;
		// remove invalid characters
		telNumber = telNumber.Replace("'", "");
		telNumber = telNumber.Replace("(", " ").Trim();
		telNumber = telNumber.Replace(")", " ").Trim();
		// convert periods to dashes
		telNumber = telNumber.Replace(".", "-");
		telNumber = ExcessWhitespaceRegex.Replace(telNumber, " ");
		// if there is a pattern like " -", "- ", "+ " left, replace the space
		telNumber = telNumber.Replace(" -", "-");
		telNumber = telNumber.Replace("- ", "-");
		telNumber = telNumber.Replace("+ ", "+");
		// if the tel number starts with a 1, change it to +1
		if (telNumber.StartsWith("1 ") || telNumber.StartsWith("1-")) {
			telNumber = "+" + telNumber;
		}
		telNumberText = telNumberText.Replace(originalPhoneNumber, telNumber);
	}
	return telNumberText;
}
// return the city from the article name.  if the article name is "Foo (Disambiguation)"
// then this method returns "Foo".
private static string GetCityFromArticleName(string articleName) {
	string basePageName = Tools.BasePageName(articleName);
	Match match = CityNameWithDisambiguationRegex.Match(basePageName);
	return (match.Success) ? match.Groups[1].Value : basePageName;
}
// if the indirizzo ends in a full street type value, convert to the abbreviated value
private static string AbbreviateStreeType(string indirizzo, string invalidStreetType, string validStreetType) {
	if (indirizzo.ToLower().EndsWith(" " + invalidStreetType.ToLower())) {
		int pos = indirizzo.ToLower().LastIndexOf(invalidStreetType.ToLower());
		if (pos &gt; 0) {
			indirizzo = indirizzo.Substring(0, pos) + validStreetType;
		}
	}
	return indirizzo;
}
// remove any leading or trailing punctuation
private static string StripStrayPunctuation(string text) {
	return StripPunctuation(text, true, true);
}
// remove any leading punctuation
private static string StripLeadingPunctuation(string text) {
	return StripPunctuation(text, true, false);
}
// remove any trailing punctuation
private static string StripTrailingPunctuation(string text) {
	return StripPunctuation(text, false, true);
}
// remove any leading punctuation
private static string StripPunctuation(string text, bool stripLeading, bool stripTrailing) {
	if (stripTrailing) {
		text = InvalidTrailingPunctuationRegex.Replace(text, "");
	}
	if (stripLeading) {
		text = InvalidLeadingPunctuationRegex.Replace(text, "");
	}
	return text;
}
// return true if the text matches the pattern, otherwise return null,  the "match"
// param will be populated with the match object
private static bool MatchText(string matchText, Regex regex, ref Match match) {
	match = regex.Match(matchText);
	return (match.Success);
}
private static string Capitalize(string text) {
	if (String.IsNullOrEmpty(text)) {
		return text;
	}
	// make sure first character is capitalized
	return (text.Length == 1) ? Char.ToUpper(text[0]) + "" : Char.ToUpper(text[0]) + text.Substring(1);
}
// add the value to the edit summary if it is not already present
private static string UpdateEditSummary(string summary, string textToAdd) {
	if (summary == "") {
		return textToAdd;
	}
	foreach(string summaryField in summary.Split(',')) {
		if (summaryField.Trim().Equals(textToAdd)) {
			// text already present in edit summary
			return summary;
		}
	}
	return summary += ", " + textToAdd;
}
// return true if the article contains a city status template
//public static bool IsCityArticle(string articleText) {
//	return CityStatusTemplateNamesRegex.IsMatch(articleText);
//}
// return true if the article contains a country status template
//public static bool IsCountryArticle(string articleText) {
//	return CountryStatusTemplateNamesRegex.IsMatch(articleText);
//}
// return true if the article contains a dive guide status template
//public static bool IsDiveguideArticle(string articleText) {
//	return DiveguideStatusTemplateNamesRegex.IsMatch(articleText);
//}
// return true if the article contains a district status template
//public static bool IsDistrictArticle(string articleText) {
//	return DistrictStatusTemplateNamesRegex.IsMatch(articleText);
//}
// return true if the article contains an itinerary status template
//public static bool IsItineraryArticle(string articleText) {
//	return ItineraryStatusTemplateNamesRegex.IsMatch(articleText);
//}
// return true if the article contains a park status template
//public static bool IsParkArticle(string articleText) {
//	return ParkStatusTemplateNamesRegex.IsMatch(articleText);
//}
// return true if the article contains a phrasebook status template
//public static bool IsPhrasebookArticle(string articleText) {
//	return PhrasebookStatusTemplateNamesRegex.IsMatch(articleText);
//}
// return true if the article contains a region status template
//public static bool IsRegionArticle(string articleText) {
//	return RegionStatusTemplateNamesRegex.IsMatch(articleText);
//}
// return true if the article contains a topic status template
//public static bool IsTopicArticle(string articleText) {
//	return TopicStatusTemplateNamesRegex.IsMatch(articleText);
//}
// TODO:
// - clean up frontlink conversion logic
// - move tollfree numbers to tollfree in listings
// - don't allow "otheruses" to be moved above the page banner</Code>
  </Module>
  <ExternalProgram>
    <Enabled>false</Enabled>
    <Skip>false</Skip>
    <Program />
    <Parameters />
    <PassAsFile>true</PassAsFile>
    <OutputFile />
  </ExternalProgram>
  <Disambiguation>
    <Enabled>false</Enabled>
    <Link />
    <Variants />
    <ContextChars>20</ContextChars>
  </Disambiguation>
  <Special>
    <namespaceValues>
      <int>0</int>
      <int>1</int>
      <int>2</int>
      <int>3</int>
      <int>4</int>
      <int>5</int>
      <int>6</int>
      <int>7</int>
      <int>10</int>
      <int>11</int>
      <int>14</int>
      <int>15</int>
    </namespaceValues>
    <remDupes>true</remDupes>
    <sortAZ>true</sortAZ>
    <filterTitlesThatContain>false</filterTitlesThatContain>
    <filterTitlesThatContainText />
    <filterTitlesThatDontContain>false</filterTitlesThatDontContain>
    <filterTitlesThatDontContainText />
    <areRegex>false</areRegex>
    <opType>-1</opType>
    <remove />
  </Special>
  <Tool>
    <ListComparerUseCurrentArticleList>0</ListComparerUseCurrentArticleList>
    <ListSplitterUseCurrentArticleList>0</ListSplitterUseCurrentArticleList>
    <DatabaseScannerUseCurrentArticleList>0</DatabaseScannerUseCurrentArticleList>
  </Tool>
  <Plugin />
</AutoWikiBrowserPreferences>


Eseguire modifiche con AWB[modifica]

Per operare modifiche con AWB è necessario innanzitutto individuare un elenco di articoli da editare. Una volta fatto, AWB creerà una lista in un riquadro al lato sinistro della sua interfaccia e di volta in volta mostrerà il Diff di ogni modifica. Per iniziare ad operare con AWB clicca su Start (ultima linguetta del riquadro centrale) e poi ancora sul pulsante Start. AWB visualizzerà il testo con le modifiche che intende apportare e un riquadro con diverse opzioni, comprese quelle di modifica manuale. Per non effettuare alcuna modifica premi Skip, per salvarla fai clic su Save.

  • Attenzione: AWB potrebbe apportare modifiche diverse da quelle attese, in quanto si basa su espressioni regolari, e spetta a voi per rivedere le modifiche proposte e correggere eventuali errori prima di salvare. La responsabilità di ogni modifica è solo vostra.

Modifiche manuali possono essere effettuate modificando il contenuto della scheda "Edit". Una volta salvata una modifica questa apparirà nella cronologia della relativa pagina. In ogni caso, appena salvato o saltato un diff, AWB procederà con le successive pagine nella lista.

Creare la lista[modifica]

Vai nel riquadro "Source" e digitare il nome dell'articolo da modificare o una modalità di creazione della lista, quindi utilizza "Make list" per le diverse opzioni o per generare la lista pronta all'utilizzo.

Mi sembra di aver capito, ma...

Se non riesci ad afferrare qualche concetto o non capisci il perché di tale procedura, ci metti cinque secondi a chiederlo e avere risposta. Se pensi invece di avere una proposta, piccola o grande che sia, siamo tutti pronti ad ascoltarti.

L'elenco di tutte le pagine riguardanti Wikivoyage si trova nella pagina Aiuto:Aiuto.