【EC-CUBE4】DoctrineExtensionsでEC-CUBEのDBを多言語化する 更新日時:2020-07-27 閲覧時間: 5 min 閲覧回数:
EC-CUBE4ではフロント画面やメール文はデフォルトでyamlファイルでの多言語化が用意されており (英語だけほかの言語が欲しいなら自前で用意) .envのECCUBE_LOCALE
の値を切り替えることで言語を切り替えることが可能です。
でも、DBの商品テーブル(dtb_product)とかは多言語対応の類が用意されていないので、 多言語で用意したEC-CUBEから1つのDBを参照しようとすると1つの言語でしか表示できません。 かといってそれぞれの言語ずつDBを用意すると受注データがとっ散らかって管理が大変です。
EC-CUBEの基盤になっているSymfonyにはDoctrineExtensionsというライブラリがあります。 参考: Github 今回はこれを使って商品名とかの多言語化を進めました。
但し書き EC-CUBE4.0.3、PHP7.2、mysql8で確認 外部ライブラリの導入+src/Eccube/Entity配下の修正なので、アップデートするときにさし戻ったり、障害がでたりするかもしれません。 手順漏れがあるかも。 正直EC-CUBE/Symfonyでまともに開発したのがこれが初めて(仕事はLaravelが中心でEC-CUBEは3系でプラグインのコード少し見たくらい)なのでもっといい方法があるかも。 インストール 手順: Github (EC-CUBE4ってSymfony3.4ですけどこれでもできました)
composer require gedmo/doctrine-extensions
EC-CUBEでDoctrineExtensionsを使えるようにする
app/config/eccube/services.yamlのservicesの後ろにこれを追加
parameters: ...(中略)... services: ...(中略)... Gedmo\Translatable\TranslatableListener: tags: - { name: doctrine.event_subscriber, connection: default } calls: - [ setAnnotationReader, [ '@annotation_reader' ] ] - [ setDefaultLocale, [ 'ja' ] ] - [ setTranslationFallback, [ false ] ]
app/config/eccube/packages/doctrine.yamlのormにもこれを追加
parameters: ...(中略)... doctrine: dbal: ...(中略)... orm: ...(中略)... mappings: translatable: type: annotation alias: Gedmo prefix: Gedmo\Translatable\Entity dir: "%kernel.project_dir%/vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
リクエストが来た時に.envのEC_LOCALEの言語で処理したいのでイベントリスナーを追加
<?php namespace Customize \EventListener ; use Gedmo \Translatable \TranslatableListener ; use Symfony \Component \EventDispatcher \EventSubscriberInterface ; use Symfony \Component \HttpKernel \KernelEvents ; use Symfony \Component \HttpKernel \Event \GetResponseEvent ; use Eccube \Common \EccubeConfig ; class DoctrineExtensionListener implements EventSubscriberInterface { private $translatableListener; private $container; private $eccubeConfig; public function __construct ( TranslatableListener $translatableListener, EccubeConfig $eccubeConfig ) { $this ->translatableListener = $translatableListener; $this ->eccubeConfig = $eccubeConfig; } public static function getSubscribedEvents () { return [ KernelEvents::REQUEST => 'onKernelRequest' ]; } public function onKernelRequest (GetResponseEvent $event) : void { $this ->translatableListener->setTranslatableLocale($this ->eccubeConfig['eccube_locale' ]); $this ->translatableListener->setPersistDefaultLocaleTranslation(true ); $this ->translatableListener->setTranslationFallback(true ); } }
これらを設定後下記のコマンドを実行します
bin/console eccube:generate:proxies bin/console doctrine:schema:update --dump-sql --force bin/console doctrine:mapping:info
これでext_translationsというテーブルができれいればOKです。
多言語設定法 各Entityの多言語化したいカラムにTranslatableアノテーションを追加します。 例えばProductだと商品名を多言語化したいわけですので
src/Eccube/Entity/Procut.php
namespace Eccube \Entity ; use Doctrine \Common \Collections \ArrayCollection ; use Doctrine \ORM \Mapping as ORM ; use Gedmo \Mapping \Annotation as Gedmo ; if (!class_exists('\Eccube\Entity\Product' )) { class Product extends \Eccube \Entity \AbstractEntity {...(中略)... private $name;
として
bin/console eccube:generate:proxies bin/console doctrine:schema:update --dump-sql --force bin/console doctrine:mapping:info
を実行します。
動作検証 最初に日本語版(ECCUBE_LOCALE=ja)で商品を登録すると
mysql> select * from dtb_product order by id desc limit 1\G *************************** 1. row *************************** id: 13 creator_id: 1 product_status_id: 2 name: 日本語名 note: NULL description_list: NULL description_detail: NULL search_word: NULL free_area: NULL create_date: 2020-06-26 09:46:54 update_date: 2020-06-26 09:46:55 discriminator_type: product 1 row in set (0.00 sec) mysql> select * from ext_translations\G *************************** 42. row *************************** id : 42 locale: ja object_class: Eccube\Entity\Product field : name foreign_key: 13 content : 日本語名 42 rows in set (0.01 sec)
と日本語名がext_translationsに登録されているのがわかります。 フロントもちゃんと日本語名が出ていればOKです。
次に英語版(ECCUBE_LOCALE=en)で商品編集から同じ商品を開き 名前を編集します (この設定だとフォールバックして日本語の商品名がフォームに出てるかも)
DBを見てみると
mysql> select * from dtb_product\G *************************** 11. row *************************** id: 13 creator_id: 1 product_status_id: 2 name: 日本語名 note: NULL description_list: NULL description_detail: NULL search_word: NULL free_area: NULL create_date: 2020-06-26 09:46:54 update_date: 2020-06-26 09:51:17 discriminator_type: product 11 rows in set (0.00 sec) mysql> select * from ext_translations\G *************************** 42. row *************************** id : 42 locale: ja object_class: Eccube\Entity\Product field : name foreign_key: 13 content : 日本語名 *************************** 43. row *************************** id : 43 locale: en object_class: Eccube\Entity\Product field : name foreign_key: 13 content : English Name 43 rows in set (0.00 sec)mysql>
ext_translationsに日本語版と英語版2つ設定されているのがわかります。
フロント側でも英語版なら英語名、日本語版なら日本語名が出ていればOKです。
追記(20200702) TwitterやGithubのissueEC-CUBEの中の方とかから反響を頂いていてちょっとびっくりしました。https://github.com/EC-CUBE/ec-cube/issues/4600
こちらはあくまでテーブルの項目の多言語化の方法までの紹介となります。
CSVのアップロード機能等に関しては考慮されていないのでご注意ください。