MT出力の現状チェック(1):APIリファレンス

共有

機械翻訳(MT)システムの出力はどこを間違えるのか、ITエンジニアが読みそうなドキュメントを対象とし、実際のサンプルで確認する。

目的は、現在広く使われているMTシステムが間違いやすい部分を特定し、利用時にどこに注意を払うべきかを把握することである。MTシステム間で優劣を付けることは目的としない。対象や方法は下記の通りで、MT出力は記載のアクセス日のものである。

  • MTシステム: 個人の利用者が多そうな無料システム。今回はGoogle翻訳DeepL(テキスト入力する形で利用)
  • 言語方向: 英語→日本語
  • ドキュメント・タイプ: APIリファレンス、プロダクト紹介、マニュアルなど
  • 評価方法: エラー評価。JTF翻訳品質評価ガイドライン(PDF)の大カテゴリーと重大度を利用

目次

  1. 原文
  2. DeepLの出力
    1. エラーと思われる部分
    2. 考察
  3. Google翻訳の出力
    1. エラーと思われる部分
    2. 考察
  4. 結論

原文

今回はPython言語のウェブアプリケーション・フレームワークである「Flask」のAPIリファレンスで「JSON Support」の一部を対象にする。なお、HTMLからテキスト形式でコピーし、リストの点を追加するなど、最低限の整形をした。

URL:https://flask.palletsprojects.com/en/2.1.x/api/#module-flask.json (2022-07-30アクセス)

DeepLの出力

(2022-07-30アクセス)

対訳で見やすいよう、左側に原文、右側にMT出力を置いた(画面が小さいと縦並び)。

ハイライトされ、隅付きかっこ(【1】など)が付加された部分はエラーと思われるため、後ほど取り上げる。

JSON Support

Flask uses the built-in json module for handling JSON. It will use the current blueprint’s or application’s JSON encoder and decoder for easier customization. By default it handles some extra data types:

- datetime.datetime and datetime.date are serialized to RFC 822 strings. This is the same as the HTTP date format.
- decimal.Decimal is serialized to a string.
- uuid.UUID is serialized to a string.
- dataclasses.dataclass is passed to dataclasses.asdict().
- Markup (or any object with a __html__ method) will call the __html__ method to get a string.

Jinja’s |tojson filter is configured to use Flask’s dumps() function. The filter marks the output with |safe automatically. Use the filter to render data inside <script> tags.

<script>
    const names = {{ names|tosjon }};
    renderChart(names, {{ axis_data|tojson }});
</script>

flask.json.jsonify(*args, **kwargs)

Serialize data to JSON and wrap it in a Response with the application/json mimetype.

Uses dumps() to serialize the data, but args and kwargs are treated as data rather than arguments to json.dumps().

1. Single argument: Treated as a single value.
2. Multiple arguments: Treated as a list of values. jsonify(1, 2, 3) is the same as jsonify([1, 2, 3]).
3. Keyword arguments: Treated as a dict of values. jsonify(data=data, errors=errors) is the same as jsonify({"data": data, "errors": errors}).
4. Passing both arguments and keyword arguments is not allowed as it’s not clear what should happen.

from flask import jsonify

@app.route("/users/me")
def get_current_user():
    return jsonify(
        username=g.user.username,
        email=g.user.email,
        id=g.user.id,
    )

Will return a JSON response like this:

{
  "username": "admin",
  "email": "admin@localhost",
  "id": 42
}

The default output omits indents and spaces after separators. In debug mode or if JSONIFY_PRETTYPRINT_REGULAR is True, the output will be formatted to be easier to read.

Changelog

Parameters:
        - args (Any) –
        - kwargs (Any) –

Return type:  Response
JSON サポート

Flask は JSON を扱うために組み込みの json モジュールを使用します。より簡単にカスタマイズできるように、現在のブループリントやアプリケーションのJSONエンコーダとデコーダを使用します。デフォルトでは、いくつかの特別なデータ型を扱います。

- datetime.datetime と datetime.date は、RFC 822 文字列にシリアライズされます。これは、HTTPの日付形式と同じです。
- decimal.Decimalは、文字列にシリアライズされます。
- uuid.UUIDは、文字列にシリアライズされます。
- dataclasses.dataclassはdataclasses.asdict()に渡される【1】。
- Markup【2】 (または __html__ メソッドを持つオブジェクト) は __html__ メソッドを呼び出して文字列を取得します。

Jinja の |tojson フィルタは Flask の dumps() 関数を使用するように設定されています。このフィルタは、出力を自動的に |safe でマークします。<script>タグの中のデータをレンダリングするために、このフィルター【3】を使います。

<script> タグ内【4】
    const names = {{ names|tosjon }};
    renderChart(names, {{ axis_data|tojson }}) とします。【5】
</script>

flask.json.jsonify(*args, **kwargs)

データをJSONにシリアライズし、application/json mimetypeでResponseにラップ【6】します。

データのシリアライズには dumps() を使用しますが、args と kwargs は json.dumps() の引数ではなく、データとして扱われます。

1. 1. 単一の引数。1.【7】単一引数:単一の値として扱われます。
2. 2. 複数の引数。【8】 jsonify(1, 2, 3)はjsonify([1, 2, 3])と同じ意味です。
3. 3. キーワード引数。【9】 jsonify(data=data, errors=errors) は jsonify({"data": data, "errors": errors})と同じです。
4. 4. 引数とキーワード引数の両方を渡すことは、何が起こるか分からないので禁止されています。

from flask import jsonify

@app.route("/users/me")
def get_current_user():
    return jsonify(
        username=g.user.username,
        email=g.user.email【10】
        id=g.user.id,
    )

このようなJSONレスポンスが返されます。

{
  "username": "admin",
  "email": "admin@localhost",
  "id": 42
}

デフォルトの出力では、セパレータの後のインデントとスペースは省略されます。デバッグモードまたは JSONIFY_PRETTYPRINT_REGULAR が True の場合、出力は読みやすいようにフォーマットされます。

変更履歴

パラメータ
        - args (任意【11】)
        - kwargs (任意)

戻り値のタイプ【12】  レスポンス【13】

エラーと思われる部分

#カテゴリ重大度説明
1スタイル軽度リストであるため、敬体と常体の表記は他と揃ってほしい
2用語軽度特に原文通りである必要はないため、「マークアップ」でよい
3用語軽度直前に「フィルタ」という表記が出ていて、統一されていない
4正確さ軽度HTMLのソースコード内に余計な日本語が付いてしまっている
5正確さ重度4と同じで、ソースコードに余計な日本語が入っている。またセミコロンも消えてソースコードが変わってしまっている
6流暢さなし原文もwrapだが「入れる」程度の表現でよいか。評価者の好みに入るかもしれないので、エラーとせず
7正確さ軽度リストの番号が1〜4まで重複して出力されている。1番については「単一の引数」と「単一引数」の言葉が2度出現
8正確さ重度原文の「Treated as a list of values.」がまるまる訳抜けしてしまっている
9正確さ重度原文の「Treated as a dict of values.」がまるまる訳抜けしてしまっている
10正確さ重度ソースコードなのにカンマ(,)が句点(。)に変わっている。そのままコピーしたらプログラムは動作しない
11正確さ軽度確かにどんな型でもよいが、Anyという型があるので「Any」とすべきか
12用語軽度プログラミング用語としては「型」が一般的か。また直後のコロンも訳文で消えている
13正確さ軽度ここは型の説明なので「Response」としなければならない

考察

MT出力を使う際にとりわけ注意を払うべき点がいくつかあった。

  • 8と9を見ても分かるように「訳抜け」が発生することがある。NMT(ニューラル機械翻訳)の登場直後はこの訳抜けがNMTの弱点だと言われていて、最近は改善されたとも聞いているが、やはりまだ発生するようだ。抜けが怖いのは、抜けていることが訳文から分からない点だ。訳文に違和感があればまだ原文を確認できるが、抜けているとそれもできない。
  • ソースコードを訳してしまうことがある。ソースコードは原文通りに維持すべき部分である。ここが訳されてしまうと、ソースコードをコピー&ペーストした際に、プログラムが動作しなくなる恐れがある。10のようにカンマ(,)が句点(。)に変わっているだけだと、細かすぎて見落とす恐れがある。

Google翻訳の出力

(2022-07-30アクセス)

JSON Support

Flask uses the built-in json module for handling JSON. It will use the current blueprint’s or application’s JSON encoder and decoder for easier customization. By default it handles some extra data types:

- datetime.datetime and datetime.date are serialized to RFC 822 strings. This is the same as the HTTP date format.
- decimal.Decimal is serialized to a string.
- uuid.UUID is serialized to a string.
- dataclasses.dataclass is passed to dataclasses.asdict().
- Markup (or any object with a __html__ method) will call the __html__ method to get a string.

Jinja’s |tojson filter is configured to use Flask’s dumps() function. The filter marks the output with |safe automatically. Use the filter to render data inside <script> tags.

<script>
    const names = {{ names|tosjon }};
    renderChart(names, {{ axis_data|tojson }});
</script>

flask.json.jsonify(*args, **kwargs)

Serialize data to JSON and wrap it in a Response with the application/json mimetype.

Uses dumps() to serialize the data, but args and kwargs are treated as data rather than arguments to json.dumps().

1. Single argument: Treated as a single value.
2. Multiple arguments: Treated as a list of values. jsonify(1, 2, 3) is the same as jsonify([1, 2, 3]).
3. Keyword arguments: Treated as a dict of values. jsonify(data=data, errors=errors) is the same as jsonify({"data": data, "errors": errors}).
4. Passing both arguments and keyword arguments is not allowed as it’s not clear what should happen.

from flask import jsonify

@app.route("/users/me")
def get_current_user():
    return jsonify(
        username=g.user.username,
        email=g.user.email,
        id=g.user.id,
    )

Will return a JSON response like this:

{
  "username": "admin",
  "email": "admin@localhost",
  "id": 42
}

The default output omits indents and spaces after separators. In debug mode or if JSONIFY_PRETTYPRINT_REGULAR is True, the output will be formatted to be easier to read.

Changelog

Parameters:
        - args (Any) –
        - kwargs (Any) –

Return type:  Response
JSON のサポート

Flask は、組み込みの json モジュールを使用して JSON を処理します。カスタマイズを容易にするために、現在のブループリントまたはアプリケーションの JSON エンコーダーとデコーダーを使用します。デフォルトでは、いくつかの追加のデータ型を処理します:

- datetime.datetime と datetime.date は、RFC 822 文字列にシリアル化されます。これは、HTTP 日付形式と同じです。
- decimal.Decimal は文字列にシリアル化されます。
- uuid.UUID は文字列にシリアル化されます。
- dataclasses.dataclass は dataclasses.asdict() に渡されます。
- マークアップ (または __html__ メソッドを持つ任意のオブジェクト) は、__html__ メソッドを呼び出して文字列を取得します。

Jinja の |tojson フィルターは、Flask の dumps() 関数を使用するように構成されています。フィルター【1】は、出力に |safe のマークを自動的に付けます。 <script> タグ内のデータをレンダリングするには、フィルター【1】を使用します。

<スクリプト>【2】
    const 【3】 = {{ 【3】|tosjon }};
    renderChart(names, {{ axis_data|tojson }});
</script>

フラスコ【4】.json.jsonify(*args, **kwargs)

データを JSON にシリアライズし、それを application/json mimetype の Response にラップ【5】 します。

dumps() を使用してデータをシリアル化しますが、args と kwargs は json.dumps() への引数ではなくデータとして扱われます。

1. 単一の引数: 単一の値として扱われます。
2. 複数の引数: 値のリストとして扱われます。 jsonify(1, 2, 3) は jsonify([1, 2, 3]) と同じです。
3. キーワード引数: 値の辞書として扱われます。 jsonify(data=data, errors=errors) は jsonify({"data": data, "errors": errors}) と同じです。
4.何が起こるべきかが明確でないため、引数とキーワード引数の両方を渡すことは許可されていません。

フラスコインポートjsonifyから【6】

@app.route("/users/me")
デフォルト【7】 get_current_user():
    jsonify( を返す【8】
        ユーザー名=g.user.ユーザー名、【9】
        email=g.user.email,
        id=g.user.id,
    )

次のような JSON 応答が返されます。

{
  "ユーザー名": "管理者"【10】,
  "email": "admin@localhost",
  "id": 42
}

デフォルトの出力では、区切り記号の後のインデントとスペースが省略されます。デバッグ モードの場合、または JSONIFY_PRETTYPRINT_REGULAR が True の場合、出力は読みやすいように書式設定されます。

変更ログ

パラメーター:
        - 引数【11】 (任意【12】) -
        - kwargs (任意) –

戻り値の型: レスポンス【13】

エラーと思われる部分

#カテゴリ重大度説明
1正確さ軽度単に「フィルター」とあるが、原文は「the filter」で、直前の「|tojsonフィルター」を指している。theを訳出して「このフィルター」などとすべき
2正確さ重度タグ名が訳されており、コピーして使った場合に動作しない
3正確さ重度変数名が訳されており、コピーした場合に動作しない
4正確さ軽度クラス名が訳されている。ただし見出しなのでコピーして使う恐れはなさそう
5正確さ軽度「application/json mimetype Response にラップ」とした方が内容的には正確か(「ラップ」より「入れる」程度でよさそうではあるが)
6正確さ重度インポート文が訳されており、コピーした場合に動作しない
7〜9正確さ重度ソースコードが訳されており、コピーした場合に動作しない(なお関数定義の「def」なので、デフォルトでもない)
10正確さ軽度レスポンスのサンプルではあるが、原文を維持すべき場所
11正確さ軽度この関数説明の見出しにあるパラメーター名(つまりargs)と同じにしておく必要がある
12正確さ軽度DeepLのときと同様、Anyという型があるので「Any」とすべきか
13正確さ軽度型の説明なので「Response」とすべき

考察

  • DeepLと同様、ソースコード部分が訳されてしまっている(2、3、6〜9)。今回はMTシステムにテキストのみを入力したため、MTシステム側で本文とソースコード部分とを見分けにくかったのかもしれない。テキストだけでなくHTMLタグなども一緒に処理できるのであれば、MTシステム側で判別できるようになるかもしれない。
  • 日本語には冠詞(aやthe)がないため、訳出しないことも多い。しかし1にあるように、単に「フィルター」としただけでは、直前の「|tojsonフィルター」を指しているのか、フィルター全般なのかが分からない。既出の事柄を指す(前方照応という)場合、定冠詞theはきちんと訳出されてほしいところだ。なおDeepLでは「このフィルター」と訳出されている。

結論

APIリファレンスは具体的なソースコードを挙げて説明している部分が多く、ソースコードは日本語化してはいけない部分がほとんどだ。現状のMTシステムでは、テキストのみを入力した場合、ソースコードか否かの判別は難しいのかもしれない。そのためソースコードをそのままコピー&ペーストする際は特に注意が必要である。

NMTの問題点と言われていた訳抜けが現在でも発生するようだ。日本語の訳文だけ見ていても抜けは分からない。「意味が通らない」など日本語に少しでもおかしさを感じたら、原文と見比べる癖は付けておきたいところだ。


共有