利用者:Naggy Nagumo/翻訳並べ替え.js

出典: フリー多機能辞典『ウィクショナリー日本語版(Wiktionary)』
ナビゲーションに移動 検索に移動

注意: 保存後、変更を確認するにはブラウザーのキャッシュを消去する必要がある場合があります。

  • Firefox / Safari: Shift を押しながら 再読み込み をクリックするか、Ctrl-F5 または Ctrl-R を押してください (Mac では ⌘-R)
  • Google Chrome: Ctrl-Shift-R を押してください (Mac では ⌘-Shift-R)
  • Internet Explorer / Microsoft Edge: Ctrl を押しながら 最新の情報に更新 をクリックするか、Ctrl-F5 を押してください
  • Opera: Ctrl-F5を押してください
// <nowiki>

// 2020/02/13現在、Chromeでしかちゃんと動かない!
// 正規表現の先読み・後読み構文がChromeでしか対応していないらしい。
EDIT.翻訳並べ替え = {
	実行: function () {
		function 翻訳並べ替え() {
			const テキストボックスID = EDIT.テキストボックスID;
			const 元のテキスト = $('#' + テキストボックスID).val();

			const コメント = [];
			const コメント退避済みテキスト = EDIT.コメントを退避(元のテキスト, コメント);

			const ウィキテキスト解析データ = ウィキテキスト翻訳データ解析(コメント退避済みテキスト);
			if (!ウィキテキスト解析データ) {
				return false;
			}

			const 翻訳以外データ = ウィキテキスト解析データ.翻訳以外;
			const 翻訳データ = 言語名順並べ替え(ウィキテキスト解析データ.翻訳);
			if (!翻訳データ) {
				return false;
			}
			console.log(翻訳データ);

			let 並べ替えたテキスト = ウィキテキストに変換(翻訳データ, 翻訳以外データ);
			if (!並べ替えたテキスト) {
				return false;
			}

			並べ替えたテキスト = EDIT.コメントを戻す(並べ替えたテキスト, コメント);

			$('#' + テキストボックスID).val(並べ替えたテキスト);
			if (元のテキスト !== 並べ替えたテキスト) {
				EDIT.要約欄にメッセージを挿入('[翻訳を正規化]');
			}

			return true;
		}

		function ウィキテキスト翻訳データ解析(ウィキテキスト) {
			const 翻訳ブロックリスト = [];

			const 表示言語名ブロックリスト = [];
			const 訳語リストの一覧 = $('.mw-parser-output div.translations').toArray();
			Object.keys(訳語リストの一覧).forEach(function (番号) {
				const 表示言語名ブロック = $(訳語リストの一覧[番号]).find('li, li > dl > dd').map(function (i) {
					let テキスト = $(this).text();
					テキスト = テキスト.split(':')[0].trim();
					return テキスト;
				}).toArray();
				表示言語名ブロックリスト.push(表示言語名ブロック);
			});

			// ウィキテキストで翻訳を取得
			let 翻訳ブロックを取得する正規表現 = /(?<=\{\{trans-top[^\n]*?\n)([\s\S]*?)(?=\n\{\{trans-bottom\}\})/g;
			let 翻訳ブロックを分割する正規表現 = /(?<=\{\{trans-top[^\n]*?\n)[\s\S]*?(?=\n\{\{trans-bottom\}\})/g;
			let res;
			while ((res = 翻訳ブロックを取得する正規表現.exec(ウィキテキスト)) !== null) {
				const 翻訳ブロック = res[1].split('\n');
				翻訳ブロックリスト.push(翻訳ブロック);
			}
			const 翻訳以外データ = ウィキテキスト.split(翻訳ブロックを分割する正規表現);

			// 要素数不一致で終了
			if (表示言語名ブロックリスト.length !== 翻訳ブロックリスト.length) {
				return null;
			}
			let 要素数不一致 = false;
			Object.keys(表示言語名ブロックリスト).forEach(function (i) {
				if (表示言語名ブロックリスト[i].length !== 翻訳ブロックリスト[i].length) {
					要素数不一致 = true;
				}
			});
			if (要素数不一致) {
				return null;
			}

			const 翻訳データ = [];
			Object.keys(翻訳ブロックリスト).forEach(function (i) {
				const 翻訳ブロック = 翻訳ブロックリスト[i];
				const 表示言語名ブロック = 表示言語名ブロックリスト[i];
				const ブロック内翻訳データ = [];
				let 親ソートキー;
				Object.keys(翻訳ブロック).forEach(function (j) {
					const 表示言語名 = 表示言語名ブロック[j];
					let ソートキー;
					let テキスト = 翻訳ブロック[j];
					テキスト = EDIT.退避済みコメントを除去(テキスト);
					if(テキスト.indexOf(':') !== -1){
						mw.notify('記述スタイルが不正なため言語名を抽出できません。再度プレビューを表示して実行しなおしてください。');
					}
					テキスト = テキスト
						.replace(/^(\*\*|:\*)/g, '*:')
						.replace(/^(\*:?)\s*\[*(.*?)\]*\s*[::]\s*/g, '$1$2: ')
						.replace(/^(\*:?)\{\{([^\|]*?)\}\}:/g, '$1{{T|$2}}:')
						.replace(/\s+$/g, '');

					// ソートキーの抽出
					if (EDIT.CONSTANTS.表示名ソートキー対応表[表示言語名]) {
						ソートキー = EDIT.CONSTANTS.表示名ソートキー対応表[表示言語名];
					}
					// ソートキーが決められない場合表示名でソート。
					if (!ソートキー) {
						console.log(`ソートキー不明: ${表示言語名}, "${テキスト}"`);
						ソートキー = EDIT.言語名の漢字の読み方を推測(表示言語名);
						ソートキー = UTIL.sortkey(ソートキー).sort1;
					}

					if ((/^\*:/g.exec(テキスト) !== null)) {
						// マクロランゲージに属する小言語はマクロランゲージのソートキーを前につける
						ソートキー = 親ソートキー + ' ' + ソートキー;
					}
					else {
						親ソートキー = ソートキー;
					}

					ブロック内翻訳データ.push({ '言語': 表示言語名, 'テキスト': テキスト, 'ソートキー': ソートキー });
				});
				翻訳データ.push(ブロック内翻訳データ);
			});

			return {
				翻訳: 翻訳データ,
				翻訳以外: 翻訳以外データ
			};
		}

		function 言語名順並べ替え(データ) {
			データ.forEach(ブロック => {
				ブロック.sort((a, b) => {
					if (a.ソートキー < b.ソートキー) {
						return -1;
					}
					if (a.ソートキー > b.ソートキー) {
						return 1;
					}
					return 0;
				});
			});

			return データ;
		}

		function ウィキテキストに変換(ソート済み翻訳データ, 翻訳以外データ) {
			let テキスト = '';
			Object.keys(ソート済み翻訳データ).forEach(function (i) {
				const 翻訳ブロック = ソート済み翻訳データ[i];

				テキスト += 翻訳以外データ[i];

				const 翻訳ブロックの内容 = [];
				翻訳ブロック.forEach( => {
					翻訳ブロックの内容.push(.テキスト);
				});
				テキスト += 翻訳ブロックの内容.join('\n');
			});
			テキスト += 翻訳以外データ[翻訳以外データ.length - 1];

			return テキスト;
		}

		return 翻訳並べ替え();
	}
};

EDIT.翻訳並べ替え.ボタン = $('<button>翻訳並べ替え</button>').click(function () {

	// テキストボックスが変更されている場合実行不可とする
	if ($('#' + EDIT.テキストボックスID).text() !== $('#' + EDIT.テキストボックスID).val()) {
		alert('プレビューボタンを押して再度実行してください。');
		return;
	}

	const 実行終了条件 = EDIT.翻訳並べ替え.実行();

	if (!実行終了条件) {
		alert('エラーが発生しました。プレビューボタンを押してから再度お試しください。');
		return;
	}

});
$('#editform').before(EDIT.翻訳並べ替え.ボタン);

// </nowiki>