// Wikipedia用の翻訳支援処理実装クラスソース</summary>
//
// <copyright file="MediaWikiTranslator.cs" company="honeplusのメモ帳">
-// Copyright (C) 2012 Honeplus. All rights reserved.</copyright>
+// Copyright (C) 2013 Honeplus. All rights reserved.</copyright>
// <author>
// Honeplus</author>
// ================================================================================================
// 対象記事に言語間リンクが存在する場合、処理を継続するか確認
// ※ 言語間リンク取得中は、処理状態を解析中に変更
- MediaWikiLink interlanguage;
+ string interlanguage;
using (var sm = this.StatusManager.Switch(Resources.StatusParsing))
{
interlanguage = article.GetInterlanguage(this.To.Language.Code);
}
- if (interlanguage != null)
+ if (!string.IsNullOrEmpty(interlanguage))
{
// 確認処理の最中は処理時間をカウントしない(ダイアログ等を想定するため)
this.Stopwatch.Stop();
- if (this.IsContinueAtInterwikiExisted != null && !this.IsContinueAtInterwikiExisted(interlanguage.Title))
+ if (this.IsContinueAtInterwikiExisted != null && !this.IsContinueAtInterwikiExisted(interlanguage))
{
throw new ApplicationException("user canceled");
}
this.Stopwatch.Start();
- this.Logger.AddResponse(Resources.LogMessageTargetArticleHadInterWiki, interlanguage.Title);
+ this.Logger.AddResponse(Resources.LogMessageTargetArticleHadInterWiki, interlanguage);
}
// 冒頭部を作成
/// <returns>冒頭部のテキスト。</returns>
protected virtual string CreateOpening(string title)
{
- string langPart = String.Empty;
+ string langPart = string.Empty;
IElement langLink = this.GetLanguageLink();
if (langLink != null)
{
}
string langBody = this.To.FormatLang(this.From.Language.Code, title);
- if (String.IsNullOrEmpty(langBody))
+ if (string.IsNullOrEmpty(langBody))
{
langBody = title;
}
MediaWikiLink link = new MediaWikiLink();
link.Title = page.Title;
link.Interwiki = this.From.Language.Code;
- return "\n\n" + link.ToString() + "\n" + String.Format(
+ return "\n\n" + link.ToString() + "\n" + string.Format(
Resources.ArticleFooter,
FormUtils.ApplicationName(),
this.From.Language.Code,
page.Title,
- page.Timestamp.HasValue ? page.Timestamp.Value.ToString("U") : String.Empty) + "\n";
+ page.Timestamp.HasValue ? page.Timestamp.Value.ToString("U") : string.Empty) + "\n";
}
#endregion
if (parent.Title.StartsWith(title))
{
// サブページ(親)の場合、変換してもしょうがないのでセクションだけチェックして終了
- if (!String.IsNullOrEmpty(link.Section))
+ if (!string.IsNullOrEmpty(link.Section))
{
link.Section = this.ReplaceLinkSection(link.Section);
link.ParsedString = null;
link.Title = title;
}
- else if (!String.IsNullOrEmpty(link.Interwiki))
+ else if (!string.IsNullOrEmpty(link.Interwiki))
{
// 言語間リンク・姉妹プロジェクトへのリンクの場合、変換対象外とする
// ただし、先頭が : でない、翻訳先言語への言語間リンクだけは削除
{
// 記事自体が存在しない(赤リンク)場合、リンクはそのまま
}
- else if (interWiki == String.Empty)
+ else if (interWiki == string.Empty)
{
// 言語間リンクが存在しない場合、可能なら{{仮リンク}}に置き換え
- if (!String.IsNullOrEmpty(this.To.LinkInterwikiFormat))
+ if (!string.IsNullOrEmpty(this.To.LinkInterwikiFormat))
{
return this.ReplaceLinkLinkInterwiki(link);
}
}
// セクション部分([[#関連項目]]とか)を変換
- if (!String.IsNullOrEmpty(link.Section))
+ if (!string.IsNullOrEmpty(link.Section))
{
link.Section = this.ReplaceLinkSection(link.Section);
}
// 記事自体が存在しない(赤リンク)場合、リンクはそのまま
return template;
}
- else if (interWiki == String.Empty)
+ else if (interWiki == string.Empty)
{
// 言語間リンクが存在しない場合、[[:en:Template:xxx]]みたいな普通のリンクに置換
// おまけで、元のテンプレートの状態をコメントでつける
protected virtual IElement ReplaceVariable(MediaWikiVariable variable, MediaWikiPage parent)
{
// 変数、これ自体は処理しないが、再帰的に探索
- string old = variable.Value.ToString();
- variable.Value = this.ReplaceElement(variable.Value, parent);
- if (variable.Value.ToString() != old)
+ if (variable.Value != null)
{
- // 内部要素が変化した(置き換えが行われた)場合、変換前のテキストを破棄
- variable.ParsedString = null;
+ string old = variable.Value.ToString();
+ variable.Value = this.ReplaceElement(variable.Value, parent);
+ if (variable.Value.ToString() != old)
+ {
+ // 内部要素が変化した(置き換えが行われた)場合、変換前のテキストを破棄
+ variable.ParsedString = null;
+ }
}
return variable;
if (this.ItemTable.TryGetValue(decodedTitle, out item))
{
// 存在する場合はその値を使用
- if (!String.IsNullOrWhiteSpace(item.Alias))
+ if (!string.IsNullOrWhiteSpace(item.Alias))
{
// リダイレクトがあれば、そのメッセージも表示
this.Logger.AddAlias(new MediaWikiLink(item.Alias));
}
- if (!String.IsNullOrEmpty(item.Word))
+ if (!string.IsNullOrEmpty(item.Word))
{
this.Logger.AddDestination(new MediaWikiLink(item.Word), true);
return item.Word;
else
{
this.Logger.AddDestination(new TextElement(Resources.LogMessageInterWikiNotFound), true);
- return String.Empty;
+ return string.Empty;
}
}
// 記事名から記事を探索
item = new TranslationDictionary.Item { Timestamp = DateTime.UtcNow };
MediaWikiPage page = this.GetDestinationPage(title);
- if (page != null && page.IsRedirect())
- {
- // リダイレクトの場合、リダイレクトである旨出力し、その先の記事を取得
- this.Logger.AddAlias(new MediaWikiLink(page.Redirect.Title));
- item.Alias = page.Redirect.Title;
- page = this.GetDestinationPage(page.Redirect.Title);
- }
-
if (page == null)
{
// ページ自体が存在しない場合はnull
return null;
}
+ if (page.IsRedirect())
+ {
+ // リダイレクトの場合、リダイレクトである旨出力
+ this.Logger.AddAlias(new MediaWikiLink(page.Title));
+ item.Alias = page.Title;
+ }
+
// 記事があればその言語間リンクを取得
- MediaWikiLink interlanguage = page.GetInterlanguage(this.To.Language.Code);
- if (interlanguage != null)
+ string interlanguage = page.GetInterlanguage(this.To.Language.Code);
+ if (!string.IsNullOrEmpty(interlanguage))
{
- item.Word = interlanguage.Title;
- this.Logger.AddDestination(interlanguage);
+ item.Word = interlanguage;
+ MediaWikiLink link = new MediaWikiLink(interlanguage);
+ link.Interwiki = this.To.Language.Code;
+ this.Logger.AddDestination(link);
}
else
{
// 見つからない場合は空
- item.Word = String.Empty;
+ item.Word = string.Empty;
this.Logger.AddDestination(new TextElement(Resources.LogMessageInterWikiNotFound));
}
// 言語コード等も特に無く、かつセクションが指定されている場合
// (記事名もセクションも指定されていない・・・というケースもありえるが、
// その場合他に指定できるものも思いつかないので通す)
- return String.IsNullOrEmpty(link.Title)
- || (link.Title == parent && String.IsNullOrEmpty(link.Interwiki) && !String.IsNullOrEmpty(link.Section));
+ return string.IsNullOrEmpty(link.Title)
+ || (link.Title == parent && string.IsNullOrEmpty(link.Interwiki) && !string.IsNullOrEmpty(link.Section));
}
/// <summary>
// 記事自体が存在しない(赤リンク)場合、リンクはそのまま
return link;
}
- else if (interWiki == String.Empty)
+ else if (interWiki == string.Empty)
{
// 言語間リンクが存在しない場合、コメントで元の文字列を保存した後
// [[:en:xxx]]みたいな形式に置換。また | 以降は削除する
// ※ 渡されたlinkをそのまま使わないのは、余計なゴミが含まれる可能性があるため
MediaWikiLink title = new MediaWikiLink { Title = link.Title, Section = link.Section };
string langTitle = title.GetLinkString();
- if (!String.IsNullOrEmpty(title.Section))
+ if (!string.IsNullOrEmpty(title.Section))
{
// 変換先言語版のセクションは、セクションの変換を通したものにする
title.Section = this.ReplaceLinkSection(title.Section);
{
// 指定された記事をWikipediaから取得、リダイレクトの場合その先まで探索
// ※ この処理ではキャッシュは使用しない。
- // ※ 万が一相互にリダイレクトしていると無限ループとなるが、特に判定はしない。
- // ユーザーが画面上から止めることを期待。
this.Logger.AddMessage(Resources.LogMessageGetTargetArticle, this.From.Location, title);
MediaWikiPage page;
- for (string s = title; this.TryGetPage(s, out page); s = page.Redirect.Title)
+ if (!this.TryGetPage(title, out page))
{
- if (page == null)
- {
- // 記事が存在しない場合、メッセージを出力して終了
- this.Logger.AddResponse(Resources.LogMessageTargetArticleNotFound);
- break;
- }
-
- // 取得した記事のURIを以後のアクセスで用いるRefererとして登録
- this.From.WebProxy.Referer = page.Uri.AbsoluteUri;
- this.To.WebProxy.Referer = page.Uri.AbsoluteUri;
-
- if (!page.IsRedirect())
- {
- // リダイレクト以外ならこれで終了
- break;
- }
+ // 取得失敗時はそのまま終了
+ return null;
+ }
+ else if (page == null)
+ {
+ // 記事が存在しない場合、メッセージを出力して終了
+ this.Logger.AddResponse(Resources.LogMessageTargetArticleNotFound);
+ return null;
+ }
- // リダイレクトであれば、さらにその先の記事を取得
+ if (page.IsRedirect())
+ {
+ // リダイレクトであれば、その旨メッセージを表示
this.Logger.AddResponse(Resources.LogMessageRedirect
- + " " + new MediaWikiLink(page.Redirect.Title).ToString());
+ + " " + new MediaWikiLink(page.Title).ToString());
+ }
+
+ // ページ本文にアクセスして遅延読み込みを実行させる
+ if (!this.TryLoadPage(page))
+ {
+ // 読み込み失敗時はそのまま終了
+ return null;
}
+ // 取得した記事のURIを以後のアクセスで用いるRefererとして登録
+ this.From.WebProxy.Referer = page.Uri.AbsoluteUri;
+ this.To.WebProxy.Referer = page.Uri.AbsoluteUri;
+
return page;
}
/// <summary>
+ /// 翻訳支援対象のページの本文・タイムスタンプを読み込み。
+ /// </summary>
+ /// <param name="page">翻訳支援対象のページ。</param>
+ /// <returns>読み込み成功の場合<c>true</c>、失敗した(通信エラーなど)の場合<c>false</c>。</returns>
+ private bool TryLoadPage(MediaWikiPage page)
+ {
+ // ページ本文にアクセスして遅延読み込みを実行させる
+ try
+ {
+ string dummy = page.Text;
+ }
+ catch (Exception e)
+ {
+ // その他例外の場合、エラー情報を出力
+ this.Logger.AddError(e);
+ return false;
+ }
+
+ return true;
+ }
+
+ /// <summary>
/// 指定した言語での言語名称を [[言語名称|略称]]の内部リンクで取得。
/// </summary>
/// <returns>
// 略称を取得
IElement shortName = null;
- if (!String.IsNullOrEmpty(name.ShortName))
+ if (!string.IsNullOrEmpty(name.ShortName))
{
shortName = new TextElement(name.ShortName);
}
{
// 確認ダイアログを表示
if (MessageBox.Show(
- String.Format(Resources.QuestionMessageArticleExisted, interwiki),
+ string.Format(Resources.QuestionMessageArticleExisted, interwiki),
Resources.QuestionTitle,
MessageBoxButtons.YesNo,
MessageBoxIcon.Question)