Skip to content

feat: Deepl翻訳を食品情報出力と工程順表示に適用#2003

Open
hikahana wants to merge 9 commits intogm3/developfrom
feat/hikahan/deepl
Open

feat: Deepl翻訳を食品情報出力と工程順表示に適用#2003
hikahana wants to merge 9 commits intogm3/developfrom
feat/hikahan/deepl

Conversation

@hikahana
Copy link
Contributor

@hikahana hikahana commented Feb 14, 2026

対応Issue

resolve #0

概要

  • DeepLを利用した翻訳処理を追加し、食品情報・工程順の表示/出力で翻訳名を優先表示するように対応しました。
  • PDF/CSV出力と管理画面の表示を合わせて更新し、翻訳データがある場合に一貫した出力になるようにしました。

実装詳細

  • api/Gemfiledeepl-rb を追加し、application_controller.rbGroup モデルに翻訳取得処理を実装しました。
  • food_products_api_controller.rb / cooking_process_orders_api_controller.rb / output_csv_controller.rb で翻訳済み名称を優先するようにレスポンス・出力ロジックを調整しました。
  • print_pdf_controller.rb と各PDFテンプレートで翻訳名の表示に対応しました。
  • admin_view/nuxt-project/pages/cooking_process_order/index.vue_id.vue で翻訳名優先の表示に更新しました。
  • api/db/schema.rb を更新し、関連インデックス・関連付けを追加しました。

画面スクリーンショット等

英語で保存してます。
image

日本語訳されている。
image

csvも日本語訳されてる。
調理工程申請_CSV (2).csv

テスト項目

  • 翻訳データありの団体で、食品情報PDFの品目名が翻訳名で表示されること
  • 翻訳データありの団体で、CSV出力の食品名・工程順関連項目が翻訳名で出力されること
  • 管理画面の調理工程順一覧/詳細で翻訳名が優先表示され、未翻訳時は従来名で表示されること

備考

  • なし

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここに処理置いちゃったけど別のとこがいいかな?

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

このPRはDeepL翻訳機能を統合して、食品情報と調理工程順の表示・出力で英語データを日本語に自動翻訳するようにしたものだよ〜🌟 国際参加団体向けのシステム改善でめっちゃ重要な機能追加だね!✨

Changes:

  • ApplicationControllerにDeepL翻訳ロジックを実装(キャッシュ付き)し、API/PDF/CSV出力全体で利用可能に🔄
  • 食品製品APIと調理工程順APIのレスポンスにtranslated_nametranslated_tentフィールドを追加📝
  • PDF出力(食品情報、保健所書類等)とCSV出力(調理工程順)で翻訳名を優先表示するように更新🎨
  • 管理画面(Nuxt)の調理工程順一覧/詳細で翻訳名を表示💻

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
api/Gemfile, api/Gemfile.lock deepl-rb gem を追加してDeepL API統合を実現
api/app/controllers/application_controller.rb translate_to_ja メソッドを実装。7日間キャッシュ、エラー時は元テキスト返却
api/app/controllers/print_pdf_controller.rb helper_method として translate_to_ja を PDF テンプレートで利用可能に
api/app/controllers/api/v1/food_products_api_controller.rb 食品製品APIレスポンスに translated_name を追加
api/app/controllers/api/v1/cooking_process_orders_api_controller.rb 調理工程順APIレスポンスに翻訳フィールドを追加(translated_name, translated_tent)
api/app/controllers/api/v1/output_csv_controller.rb BOM文字列を mutable に変更(+演算子)、調理工程順CSVで翻訳を適用
api/app/views/print_pdf/*.pdf.erb 4つのPDFテンプレートで食品名・購入品・店舗名に translate_to_ja を適用
api/app/models/group.rb ORDER_STATUS_CHECK_INCLUDES 定数と with_order_status_check_relations スコープを追加
api/db/schema.rb マイグレーションバージョンを更新、groups テーブルに複数のインデックスを追加
admin_view/nuxt-project/pages/cooking_process_order/*.vue 調理工程順の一覧・詳細で translated_name/translated_tent を優先表示

Comment on lines +67 to +74
response[:food_product] = food_product.as_json.merge(
'translated_name' => translate_to_ja(food_product.name)
)

if order.present?
response[:cooking_process_order] = order.as_json.merge(
'translated_tent' => translate_to_ja(order.tent)
)
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deep_dupを使用したハッシュ操作に問題があります。cooking_process_orderはハッシュ(:food_product:cooking_process_orderをキーに持つ)ですが、line 67-68でActiveRecordオブジェクトであるかのようにfood_product.as_jsonを呼び出しています。

deep_dupの結果はハッシュのコピーなので、response[:food_product]は既にハッシュまたはActiveRecordオブジェクトです。もしActiveRecordオブジェクトの場合はas_jsonが必要ですが、既にハッシュの場合は不要です。

以下のように修正することを推奨します:

  • food_productが既にハッシュであれば、as_json呼び出しを削除する
  • またはActiveRecordオブジェクトを保持するなら、deep_dupではなく適切なシリアライズ処理を行う
Suggested change
response[:food_product] = food_product.as_json.merge(
'translated_name' => translate_to_ja(food_product.name)
)
if order.present?
response[:cooking_process_order] = order.as_json.merge(
'translated_tent' => translate_to_ja(order.tent)
)
if food_product.respond_to?(:as_json)
response[:food_product] = food_product.as_json.merge(
'translated_name' => translate_to_ja(food_product.name)
)
elsif food_product.is_a?(Hash)
name = food_product[:name] || food_product['name']
response[:food_product] = food_product.merge(
'translated_name' => translate_to_ja(name)
)
end
if order.present?
if order.respond_to?(:as_json)
response[:cooking_process_order] = order.as_json.merge(
'translated_tent' => translate_to_ja(order.tent)
)
elsif order.is_a?(Hash)
tent = order[:tent] || order['tent']
response[:cooking_process_order] = order.merge(
'translated_tent' => translate_to_ja(tent)
)
end

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +79
def translate_to_ja(text)
return text if text.blank?
return text unless translatable_english_text?(text)
return text if deepl_api_key.blank?

Rails.cache.fetch(deepl_cache_key(text), expires_in: 7.days) do
request_deepl_translation(text)
end
rescue StandardError => e
Rails.logger.warn("[DeepL] translation failed: #{e.class} #{e.message}")
text
end

def request_deepl_translation(text)
DeepL.configure do |config|
config.auth_key = deepl_api_key
end
translation = DeepL.translate(text, nil, 'JA')
translation&.text.presence || text
rescue DeepL::Exceptions::RequestError => e
Rails.logger.warn("[DeepL] request failed: #{e.class} #{e.message}")
text
end

def deepl_api_key
ENV['DEEPL_API_KEY'].presence
end

def deepl_cache_key(text)
"deepl:ja:#{Digest::SHA256.hexdigest(text)}"
end

def translatable_english_text?(text)
has_latin = text.match?(/[A-Za-z]/)
has_japanese = text.match?(/[\p{Hiragana}\p{Katakana}\p{Han}]/)
has_latin && !has_japanese
end
Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DeepL API連携のテストが不足しています。translate_to_jaメソッドやDeepL統合機能に対するテストコードがこのPRに含まれていません。

以下のケースをカバーするテストを追加することを推奨します:

  • 英語テキストが正常に翻訳される
  • 日本語テキストはそのまま返される(翻訳されない)
  • DeepL APIキーが設定されていない場合、元のテキストが返される
  • DeepL APIエラー時の graceful degradation(元のテキストを返す)
  • キャッシュが正しく機能する

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +43
ORDER_STATUS_CHECK_INCLUDES = [
:user,
:group_category,
:fes_year,
:sub_rep,
:place_order,
:stage_orders,
:stage_common_option,
:power_orders,
:rental_orders,
:employees,
:public_relation,
:venue_map,
:announcement,
:cooking_process_order,
{ food_products: :purchase_lists }
].freeze

scope :with_order_status_check_relations, -> { includes(ORDER_STATUS_CHECK_INCLUDES) }

Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ORDER_STATUS_CHECK_INCLUDES定数とwith_order_status_check_relationsスコープがGroupモデルに追加されていますが、このPR内で使用されていません。

これらは既存のコードで使用されているか、または将来のリファクタリングのために追加されたものでしょうか?もし既存コードでの使用を意図している場合、実際の使用箇所への適用も含めるべきです。未使用のコードであれば、このPRから削除し、実際に必要になった時に追加することを推奨します。

Suggested change
ORDER_STATUS_CHECK_INCLUDES = [
:user,
:group_category,
:fes_year,
:sub_rep,
:place_order,
:stage_orders,
:stage_common_option,
:power_orders,
:rental_orders,
:employees,
:public_relation,
:venue_map,
:announcement,
:cooking_process_order,
{ food_products: :purchase_lists }
].freeze
scope :with_order_status_check_relations, -> { includes(ORDER_STATUS_CHECK_INCLUDES) }

Copilot uses AI. Check for mistakes.
Rails.logger.warn("[DeepL] request failed: #{e.class} #{e.message}")
text
end

Copy link

Copilot AI Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DeepL APIキーの設定方法についてのドキュメントがありません。

環境変数DEEPL_API_KEYを設定する必要がありますが、その手順がREADMEやコメントに記載されていません。開発者やデプロイ担当者がこの機能を使用するために必要な設定手順を文書化してください。

例:

  • READMEに環境変数の説明を追加
  • .env.exampleファイルにDEEPL_API_KEYのエントリを追加
  • コメントでAPIキーの取得方法へのリンクを提供
Suggested change
# DeepL API の認証キーを環境変数から取得するメソッド
# 環境ごとに `DEEPL_API_KEY` を設定してね(例: .env / 環境変数マネージャーなど)
# DeepL API キーの取得方法: https://www.deepl.com/ja/pro-api からアカウント登録 → API キー発行

Copilot uses AI. Check for mistakes.
@hikahana hikahana requested a review from YosukeIida February 17, 2026 11:05
@YosukeIida
Copy link
Collaborator

@codex 日本語でレビューしてください.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6bcbd26a79

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +48 to +50
Rails.cache.fetch(deepl_cache_key(text), expires_in: 7.days) do
request_deepl_translation(text)
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge DeepL障害時のフォールバック値をキャッシュしない

translate_to_jaRails.cache.fetch 内で翻訳を実行していますが、翻訳側で一時的な RequestError が起きると原文を返すため、その原文が 7 日間キャッシュされます。DeepL の一時障害やレート制限が発生した瞬間に、以後は API が復旧しても同じ文言が再翻訳されず、管理画面/PDF/CSV で未翻訳表示が長期間固定されます。

Useful? React with 👍 / 👎.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hikahana これ対応しますか?できますか?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants