Help:Extension:Translate/翻訳メモリ

From MediaWiki.org
Jump to navigation Jump to search
This page is a translated version of the page Help:Extension:Translate/Translation memories and the translation is 83% complete.

Other languages:
Deutsch • ‎English • ‎Lëtzebuergesch • ‎Nederlands • ‎Zazaki • ‎dansk • ‎español • ‎français • ‎lietuvių • ‎polski • ‎português • ‎português do Brasil • ‎български • ‎русский • ‎українська • ‎العربية • ‎فارسی • ‎தமிழ் • ‎中文 • ‎日本語

翻訳拡張機能翻訳メモリは複数のバックエンドをサポートします。利用できるバックエンドとは、データベース、Solr と ElasticSearch です。このページではそれぞれの仕様をより詳細に説明し、利用者に最適のものをインストールする手助けをしていきます。

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

比較

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

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

必要条件

ElasticSearch バックエンド

ElasticSearch の設定歯比較的簡単です。配布パッケージに同梱されていない場合は、先方能佐糸からダウンロードします。合わせて拡張機能のElastica extension も入手してください。そして翻訳拡張機能に固有の環境設定は、puppet/modules/elasticsearch/files/elasticsearch.ymlで確認をお願いします。

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

Elasticsearch のメジャーアップグレード(2.x から 5.x へなど)を実行する前に、リリースノートおよび説明文書に書いてある、アップグレード手順を熟読するよう、強く推奨します。 Elastic にはmigration plugin があり、新しいバージョンをインストールする準備をサポートできる場合があります。 これら注意点を慎重に実行しないとElasticsearch のアップグレードを拒否され、意禅野バージョンにもロールバックできないといった微妙な状況にはまることがあります。

後続のメジャーなバージョンをインストールした直後には、ttmserver-export.phpを実行しようとすると失敗する事例が見られます。Once the next major version is installed it's probable that the next time you run it fails. 原因は Elasticsearch が内部で移行プロセスを実行して作成するデータマッピングと、ttmserver-export.phpが探すマッピングが不整合を起こす場合があります。 インデックス全体を強制的に再構築するには、--reindexフラッグを使用します。

経験的な知恵として、メジャーのアップグレード直後には--reindexフラッグを使ってttmserver-export.phpを実行することをお勧めします。インデックスは常に Elasticsearch の現状バージョンで作成されること、それがメジャーアップグレードの要件であることを、利用者の責任で十分に認識する必要があります。

Solr バックエンド

以下は、Solr for TTMServer のインストールおよび構成の、一般的な手順のまとめです。手順は、利用者各自の状況に適応させる必要があります。

# Solr には java が必須
sudo apt-get install openjdk-6-jre-headless
# Solr を次のサイトからダウンロードして解凍する: http://lucene.apache.org/solr/downloads.html
wget http://www.nic.funet.fi/pub/mirrors/apache.org/lucene/solr/3.6.0/apache-solr-3.6.0.tgz
tar xzf apache-solr-*.tgz
cd apache-solr-*/example
# config ファイルを拡張機能ディレクトリからコピー
cp .../Translate/ttmserver/schema.xml solr/conf
# サーバを起動
java -jar start.jar

Solr バックエンドの使用に当たり、Solarium ライブラリを入手します。もっとも簡便な方法は、拡張機能 Solarium extensionのインストールです。このページの「設定」節に Solr バックエンドの設定サンプルがありますので、参照してください。configキーを使うと、Solarium に関する煩雑な環境設定を省略でき、手順はたとえば Wikimedia configuration を参照してください。

インストール

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

設定

翻訳メモリを含め、翻訳支援ソフトはどれも$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 バックエンドの設定
$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/master/lib/Elastica/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
$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' ] ]
);
Solr バックエンドの設定
$wgTranslateTranslationServices['TTMServer'] = array(
        'type' => 'ttmserver',
        'class' => 'SolrTTMServer',
        'cutoff' => 0.75,
        /* See http://wiki.solarium-project.org/index.php/V2:Basic_usage
        'config' => This will be passed to Solarium_Client
         */
);

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

キー 適用先 説明
config Solr および ElasticSearch 設定は Solarium もしくは 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 Writable services 文字列の配列。書き込みを複製するサービスのリストを定義し、複数のTTMサービスを最新の状態に保つ。迅速な切り替えや計画的なメンテナンス作業中のダウンタイムの削減に役立つ (MLEB 2017.04 で追加)。
TTMServerキーを$wgTranslateTranslationServicesの配列インデックスに用いると、新しい訳文で翻訳メモリを更新できます。それには更新されないリモート TTMServers は使用できません。 MLEB 2017.04 時点でTTMServerキーは環境設定変数$wgTranslateTranslationDefaultServiceを用い、設定できます。

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

Bootstrap

Solr もしくは 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).

Solr バックエンド

Solr Solr search platform backend works similar to the database backend, except that it uses a dedicated search engine for increased speed. The results are by default ranked with the levenshtein algorithm on the Solr side, but other available string matching algorithms can also be used, like ngram matching for example.

In Solr there are no tables. Instead we have documents with fields. Here is an example document:

  <doc>
    <str name="wiki">sandwiki-bw_</str>
    <str name="uri">http://localhost/wiki/MediaWiki:Action-read/bn</str>
    <str name="messageid">MediaWiki:Action-read</str>
    <str name="globalid">sandwiki-bw_-MediaWiki:Action-read-813862/bn</str>
    <str name="language">bn</str>
    <str name="content">এই পাতাটি পড়ুন</str>
    <arr name="group">
      <str>core</str>
      <str>core-1.20</str>
      <str>core-1.19</str>
      <str>mediawiki</str>
    </arr>
    <long name="_version_">1421795636117766144</long>
  </doc>

Each translation has its own document and message documentation has one too. To actually get suggestions we first perform the search sorted by string similarity algorithm for all documents in the source language. Then we do another query to fetch translations if any for those messages.

We are using lots of hooks to keep the translation memory database updated in almost real time. If user translates similar messages one after another, the previous translation can (in the best case) be displayed as suggestion for the next message.

New translation (if not fuzzy)

  1. Create document

Updated translation (if not fuzzy)

  1. Delete wiki:X language:Y message:Z
  2. Create document

Updated message definition

  1. Create new document

All existing documents for the message stay around because globalid is different.

Translation is fuzzied

  1. Delete wiki:X language:Y message:Z

Messages changes group membership

  1. Delete wiki:Z message:Z
  2. Create document (for all languages)

Message goes out of use

  1. Delete wiki:Z message:Z
  2. Create document (for all languages)

Any further changes to definitions or translations are not updated to TM.

Translation memory query

  1. Collect similar messages with strdist("message definition",content)
  2. Collect translation with globalid:[A,B,C]

Search query

  1. Find all matches with text:"search query"

Can be narrowed further by facets on language or group field.

Identifier fields Field globalid uniquely identifies the translation or message definition by combining the following fields:

  • wiki identifier (MediaWiki database id)
  • message identifier (Title of the base page)
  • message version identifier (Revision id of the message definition page)
  • message language

The used format is wiki-message-version/language.

さらに上記の削除クエリを実行するため、wiki id、message id と言語にそれぞれ別個のフィールドを当てています。