Help:Extension:Translate/翻訳メモリ

This page is a translated version of the page Help:Extension:Translate/Translation memories and the translation is 73% complete.
Outdated translations are marked like this.

翻訳拡張機能翻訳メモリは、ElasticSearchをサポートします。このページでは、ElasticSearchの仕様をより詳細に説明し、利用者にElasticSearchをインストールする手助けをしていきます。

例えば外部機械翻訳サービスなど他の翻訳支援ソフトとは異なり、この翻訳メモリは利用者のウィキの新しい訳文によって絶えず更新されます。ElasticSearch の使用を選択した場合、全訳文を対象にした高度な検索 Special:SearchTranslations も利用できます。

比較

既定でデータベースバックエンドを使用。依存関係はなく設定も不要です。ただし複数のウィキ間でデータベースバックエンドの共有はできず、あるいは大量の翻訳コンテンツの処理はできません。ElasticSearchのバックエンドもサポートします。他のウィキの翻訳メモリも、先方の Web API を開いた状態なら使用可能です。ElasticSearchと異なる点は、利用中のウィキの翻訳を使った、リモートバックエンドの更新はできないことです。

データベース リモート API ElasticSearch
既定で有効 はい いいえ いいえ
複数のソースを保持できる いいえ はい はい
ローカルの翻訳により更新 はい いいえ はい
データベースに直接アクセス はい いいえ いいえ
ソースへのアクセス エディター リンク ローカルの場合エディター、その他はリンク
API サービスとして共有できる はい はい はい
パフォーマンス うまく対応できない 不明 そこそこ使える

必要条件

ElasticSearch バックエンド

ElasticSearch の設定は比較的簡単です。 配布パッケージに同梱されていない場合は、ウェブサイトから入手してください。 併せて Elastica 拡張機能も入手する必要があります。 そして翻訳拡張機能に固有の環境設定は、puppet/modules/elasticsearch/files/elasticsearch.ymlで確認をお願いします。

ブートストラップ スクリプトが必要なスキーマを作成します。複数のウィキで ElasticSearch バックエンドを利用する場合は、既定で翻訳メモリが共有されます。利用者が環境設定でインデックス引数を設定すると、共有されません。

Elasticsearch のメジャーアップグレード(2.x から 5.x へなど)を実行する前に、リリースノートおよび説明文書に書いてある、アップグレード手順を熟読するよう、強く推奨します。

インストール

必要条件が整ったら、インストール前に設定を微調整し、ブートストラップを実行する必要があります。

設定

翻訳メモリを含め、翻訳支援ソフトはどれも $wgTranslateTranslationServices 環境変数を使って設定されます。

プライマリの翻訳メモリ バックエンドはTTMServerキーを必ず使います。プライマリのバックエンドは翻訳更新情報を受け取り、Special:SearchTranslations に渡します。

TTMServers の設定サンプルは以下のとおり。

既定の設定
$wgTranslateTranslationServices['TTMServer'] = array(
        'database' => false, // Passed to wfGetDB
        'cutoff' => 0.75,
        'type' => 'ttmserver',
        'public' => false,
);
リモート API 構成
$wgTranslateTranslationServices['example'] = array(
        'url' => 'http://example.com/w/api.php',
        'displayname' => 'example.com',
        'cutoff' => 0.75,
        'timeout' => 3,
        'type' => 'ttmserver',
        'class' => 'RemoteTTMServer',
);
ElasticSearch バックエンドの設定
In this case the single back-end service will be used both for reads & writes.
$wgTranslateTranslationServices['TTMServer'] = array(
        'type' => 'ttmserver',
        'class' => 'ElasticSearchTTMServer',
        'cutoff' => 0.75,
        /*
         * See http://elastica.io/getting-started/installation.html
         * See https://github.com/ruflin/Elastica/blob/8.x/src/Client.php
        'config' => This will be passed to \Elastica\Client
         */
);
ElasticSearch マルチバックエンド設定(MLB 2017.04 でサポート)
// Defines the default service used for read operations
// Allows to quickly switch to another backend
// 'mirrors' configuration option is no longer supported since MLEB 2023.10
$wgTranslateTranslationDefaultService = 'cluster1';
$wgTranslateTranslationServices['cluster1'] = array(
        'type' => 'ttmserver',
        'class' => 'ElasticSearchTTMServer',
        'cutoff' => 0.75,
        /*
         * Defines the list of services to replicate writes to.
         * Only "writable" services are allowed here.
         */
        'mirrors' => [ 'cluster2' ],
        'config' => [ 'servers' => [ 'host' => 'elastic1001.cluster1.mynet' ] ]
);
$wgTranslateTranslationServices['cluster2'] = array(
        'type' => 'ttmserver',
        'class' => 'ElasticSearchTTMServer',
        'cutoff' => 0.75,
        /*
         * if "cluster2" is defined as the default service it will start to replicate writes to "cluster1".
         */
        'mirrors' => [ 'cluster1' ],
        'config' => [ 'servers' => [ 'host' => 'elastic2001.cluster2.mynet' ] ]
);
ElasticSearch multiple services with single readable service using writable configuration (supported by MLEB 2023.04)
With writable configuration the following rules are enforced:
  • If writable is specified, services marked as writable are considered write only and others are considered read only.
  • If no service is specified as writable then services are considered both readable and writable.
  • The default service must always be readable.

If a service is marked as writable, the mirrors configuration will not be allowed.

// Three services configured with one being readable and the others being writable.
$wgTranslateTranslationServices['dc0'] = [
	'type' => 'ttmserver',
	'class' => 'ElasticSearchTTMServer',
	'cutoff' => 0.75,
	// Default service cannot be marked as write-only
];

$wgTranslateTranslationServices['dc1'] = [
	'type' => 'ttmserver',
	'class' => 'ElasticSearchTTMServer',
	'cutoff' => 0.75,
	// Marks this service as write-only 
	'writable' => true,
];

$wgTranslateTranslationServices['dc2'] = [
	'type' => 'ttmserver',
	'class' => 'ElasticSearchTTMServer',
	'cutoff' => 0.75,
	'writable' => true
];

$wgTranslateTranslationDefaultService = 'dc0';

利用できるキーと値は以下の通りです:

キー 適用先 説明
config ElasticSearch 設定は Elastica に渡す。
cutoff すべて マッチング候補の最小しきい値。しきい値を超えた場合も、複数の最良の提案のみ表示。
database ローカル 翻訳メモリを別の場所に保存するには、ここでデータベース名を指定します。また、そのデータベースへの接続方法を決めるため、MediaWikiの ロードバランサーも設定する必要があります。
displayname リモート The text shown in the tooltip when hovering the suggestion source link (the bullets).
index ElasticSearch ElasticSearch で用いるインデックス。既定: ttmserver.
public すべて このウィキの api.php を通してこの TTMServer を呼び出せるかどうか。
replicas ElasticSearch クラスタを実行中はレプリカ数を拡張できます。既定値: 0。
shards ElasticSearch How many shards to use. Default: 5.
timeout リモート リモート サービスからの応答を待機する時間 (秒単位)。
type すべて 翻訳結果から見た TTMServer の種類。
url リモート リモート TTMServer の api.php の URL
use_wikimedia_extra ElasticSearch Boolean, when the extra plugin is deployed you can disable dynamic scripting on Elastic v1.x. This plugin is now mandatory for Elastic 2.x clusters.
mirrors (DEPRECATED Since MLEB 2023.04) Writable services 文字列の配列。書き込みを複製するサービスのリストを定義し、複数のTTMサービスを最新の状態に保つ。迅速な切り替えや計画的なメンテナンス作業中のダウンタイムの削減に役立つ (MLEB 2017.04 で追加)。 Cannot be used along with the newly added writable configuration.
writable (Added in MLEB 2023.04) Write-only services Boolean value, defined for a service if that service is write-only. The default service (wgTranslateTranslationDefaultService) cannot be marked as write-only. If out of all the translation memory services configured, none are marked as writable then all services are considered to be readable and writable. See タスク T322284
新しい翻訳を使って翻訳メモリを更新する場合は、$wgTranslateTranslationServices の配列添字としてキー TTMServer を使用する必要があります。リモート TTMServer 群は更新できないため、これには使用できません。 MLEB 2017.04 のバージョンでは、キー TTMServer は構成変数 $wgTranslateTranslationDefaultService で構成できます。 Support for Solr backend was dropped in MLEB-2019.10, in October, 2019.

現在、対応しているデータベース バックエンドは MySQL のみです。

Bootstrap

ひとたび ElasticSearch を選び、要件と設定が整ったら、ttmserver-export.phpを実行し翻訳メモリをブートします。翻訳メモリのバックエンドを変更したときも必ずブートしてください。断片化翻訳メモリを複数のウィキに使用している場合は、個別にひとつずつブートストラップする必要があります。

大量の翻訳を要するサイトの場合は、--thread引数を用いるスレッドを複数使い、プロセスの処理速度を上げるよう検討してください。時間は、メッセージ群完了統計の完全度に大きく依存します(不完全なものはブートストラップ中に計算)。新しい翻訳は自動的にフックによって追加されます。初めて訳文が作成されると、新しい翻訳原文(メッセージ定義)を追加します。

ブートストラップが行う以下のことは、その他の処理では実行されません。

  • 翻訳メモリスキーマの追加と更新。
  • 既存の翻訳を翻訳メモリに追加する。
  • 翻訳メモリを空にしたあと再設定し、未使用の翻訳エントリを開放。

特定のメッセージの翻訳が更新されると、それまでの訳文は翻訳メモリから除外されます。ただし新しい定義に対して翻訳が更新され新しいエントリが追加されても、古い定義とそれに対する古い翻訳はパージするまでデータベースに残されます。特定のメッセージの定義変更や、すべてのメッセージ群からの削除が発生しても、直後には何も起こりません。翻訳をファジーとして保存しても、新しい翻訳が追加されたり、古い翻訳が翻訳メモリから削除されることはありません。

TTMServer API

もし利用者独自の TTMServer サービスを実行したいならば、仕様は以下のとおりです。

クエリのパラメーター:

サービスでは以下のパラメータを受け入れる必要があります。

キー
format json
action ttmserver
service 複数の共有翻訳メモリがある場合は、オプションのサービス識別子。ない場合は、既定のサービスが使用されます。
sourcelanguage MediaWiki で使用しているものと同様の言語コード。IETF 言語タグと ISO693 をご覧ください。
targetlanguage MediaWiki で使用しているものと同様の言語コード。IETF 言語タグと ISO693 をご覧ください。
test 翻訳元言語の元の文章

利用者のサービスには JSON オブジェクトにオブジェクトの配列とttmserverキーを備える必要があります。それらオブジェクトには、以下のデータが含まれる必要があります。

キー
source 翻訳元のテキストです。
target 翻訳の提案です。
context オプションで、翻訳原文のローカル識別子。
location 提案が使用されているページを示すURL。
quality 候補の品質を表す10進数の範囲[0..1]。1は完全一致を意味する。

例:

{
        "ttmserver": [
                {
                        "source": "January",
                        "target": "tammikuu",
                        "context": "Wikimedia:Messages\\x5b'January'\\x5d\/en",
                        "location": "https:\/\/translatewiki.net\/wiki\/Wikimedia:Messages%5Cx5b%27January%27%5Cx5d\/fi",
                        "quality": 0.85714285714286
                },
                {
                        "source": "January",
                        "target": "tammikuu",
                        "context": "Mantis:S month january\/en",
                        "location": "https:\/\/translatewiki.net\/wiki\/Mantis:S_month_january\/fi",
                        "quality": 0.85714285714286
                },
                {
                        "source": "January",
                        "target": "Tammikuu",
                        "context": "FUDforum:Month 1\/en",
                        "location": "https:\/\/translatewiki.net\/wiki\/FUDforum:Month_1\/fi",
                        "quality": 0.85714285714286
                },
                {
                        "source": "January",
                        "target": "tammikuun",
                        "context": "MediaWiki:January-gen\/en",
                        "location": "https:\/\/translatewiki.net\/wiki\/MediaWiki:January-gen\/fi",
                        "quality": 0.85714285714286
                },
                {
                        "source": "January",
                        "target": "tammikuu",
                        "context": "MediaWiki:January\/en",
                        "location": "https:\/\/translatewiki.net\/wiki\/MediaWiki:January\/fi",
                        "quality": 0.85714285714286
                }
        ]
}

データベース バックエンド

The backend contains three tables: translate_tms, translate_tmt and translate_tmf. Those correspond to sources, targets and fulltext. You can find the table definitions in sql/translate_tm.sql. The sources contain all the message definitions. Even though usually they are always in the same language, say, English, the language of the text is also stored for the rare cases this is not true.

Each entry has a unique id and two extra fields, length and context. Length is used as the first pass filter, so that when querying we don't need to compare the text we're searching with every entry in the database. The context stores the title of the page where the text comes from, for example "MediaWiki:Jan/en". From this information we can link the suggestions back to "MediaWiki:Jan/de", which makes it possible for translators to quickly fix things, or just to determine where that kind of translation was used.

The second pass of filtering comes from the fulltext search. The definitions are mingled with an ad hoc algorithm. First the text is segmented into segments (words) with MediaWiki's Language::segmentByWord. If there are enough segments, we strip basically everything that is not word letters and normalize the case. Then we take the first ten unique words, which are at least 5 bytes long (5 letters in English, but even shorter words for languages with multibyte code points). Those words are then stored in the fulltext index for further filtering for longer strings.

When we have filtered the list of candidates, we fetch the matching targets from the targets table. Then we apply the levenshtein edit distance algorithm to do the final filtering and ranking. Let's define:

E
編集距離
S
提案を探す元となっている文字列
Tc
提案の文章
To
Tc が翻訳結果となるような元の文章

The quality of suggestion Tc is calculated as E/min(length(Tc),length(To)). Depending on the length of the strings, we use: either PHP's native levenshtein function; or, if either of the strings is longer than 255 bytes, the PHP implementation of levenshtein algorithm.[1] It has not been tested whether the native implementation of levenshtein handles multibyte characters correctly. This might be another weak point when source language is not English (the others being the fulltext search and segmentation).