機械翻訳(MT)システムの出力はどこを間違えるのか、ITエンジニアが読みそうなドキュメントを対象とし、実際のサンプルで確認する。
目的は、現在広く使われているMTシステムが間違いやすい部分を特定し、利用時にどこに注意を払うべきかを把握することである。MTシステム間で優劣を付けることは目的としない。対象や方法は下記の通りで、MT出力は記載のアクセス日のものである。
目次
原文
今回は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の問題点と言われていた訳抜けが現在でも発生するようだ。日本語の訳文だけ見ていても抜けは分からない。「意味が通らない」など日本語に少しでもおかしさを感じたら、原文と見比べる癖は付けておきたいところだ。