質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.87%

  • PHP

    12496questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • CakePHP

    1691questions

    CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

[cakePHP3] 多言語化対応 セレクトボックスより手動で設定する方法について

解決済

回答 2

投稿 2016/07/23 02:32

  • 評価
  • クリップ 1
  • VIEW 756

xjapan

score 68

CakePHP3の多言語化についての質問です。
やりたいことは、全ページのフッターに言語を選択するセレクトボックスを設置して、手動でも言語を変換できるようにしたいと考えています。

実装には、関数__()を利用して、src/localeフォルダを作成し、配下に、各言語フォルダとその中に、.poファイルと.moファイルを作成するやり方です。切り替えには、bootstrap.phpに、ini_set('intl.default_locale', 'ロケールID'); を 追加してページを変更したいと考えています。

とりあえず、よい方法かどうかはわからないのですが、
Template/Element に lang.ctpを作りそこに、下記のようなコードを追加しました。lang.ctpはLayout/default.phpより読み込まれ、すべてに適応します。要は、セレクトフォームよりpostで渡ってきた、ロケールIDをクッキーにセットして、bootstrap.phpのini_set('intl.default_locale', 'ロケールID')のロケールIDを変えようとしてます。

<?php

        if(filter_input(INPUT_POST, 'lang' )){
             $lg = filter_input(  INPUT_POST, "lang" );
           setcookie( 'lang', $lg );   //クッキーにセット
        }

        $request_uri = filter_input(INPUT_SERVER, 'REQUEST_URI' );       //URIを取得
        $param = ereg_replace('/?$', '', $request_uri);

        $params = array();
        if ('' != $param) {
            $params = explode('/', $param);   //切り分けて配列にいれる。
        }

        if(!isset($params[3])||!isset($params[4])){    //私の環境では、コントローラーが[3]、アクションが[4]です。
        $url_a = 'indexs';              //URIがない場合 ルートの時
        $url_c = 'index';               //   〃
        }else{
        $url_a = $params[3];
        $url_c = $params[4];
        }
?>

<section id="footer">
        <div class="container">

                <?=$this->Form->create(null,[
                  'type' => 'post',
                  'url' => ['controller' => $url_a, 'action' => $url_c ]]
                ) ?>

                <?php $lang = filter_input(INPUT_COOKIE, 'lang' ); ?>
                <?=$this->Form->select( 'lang' , [ 
                    ['value'=> 'ja', 'text'=> 'Japanese' ] ,
                    ['value'=>'en_US', 'text'=> 'English' ] ,
                    ['value'=>'test', 'text'=> 'test'] ,
                ],['default' => $lang]) ?>

                <?= $this->Form->button(__('Submit')) ?>
                <?= $this->Form->end() ?>

        </div>
</section>

次に、config/bootstrap.phpに下記を追加して、各ページのセレクトボックスから保存されたクッキー情報(ロケールID)をセットしています。

$lang = filter_input(INPUT_COOKIE, 'lang' );
ini_set('intl.default_locale', $lang);

そこでわからないことが2つでてきました。

① 同一のコントローラー内のアクションでは、クッキーが保持され、セレクトボックスからのポストよりクッキー保存がうまくいくいきセレクトボックスで表示した言語で表示されるのですが、コントローラーが変わると、クッキーが、保持されず、どうやら次のコントローラーで別のクッキーが作られているので、コントローラーが変わるともう一度セレクトボックスで言語を指定しなくてはいけなくなります。

おそらく、setcookie()の部分のオプションがおかしいのだとおもったので、
下記のようにかいたのですが、サイト全体に共通するような形でクッキーが保持されません。

setcookie( 'lang', $lg, 0 , '/' );


どのように全体にでもクッキーを適応するのかがわかりません。

② サイトURLのルートからのアクセスだと、セレクトボックスで選択しても、クッキーに保存されません。なので、セレクトボックスが機能しないです。
URLのルートでは、もともとは、ルーティングでindexに設定した、コントローラーとアクション(私の場合、indexs/index)を設定しています。なのでURIが表示されないので、フォームからポストするときは、ポスト先をindexs/index になるようにしています。しかし、ルートへのアクセスからだとセレクトボックスでクッキーに保存できませんでした。

私自身、フレームワークを利用しはじめてから、1か月くらいなので、よくわかってない部分の方が多いので、どこにどのように書けばよいのかが、非効率になっていると思います。おそらく、もっと楽にできると思うので、手動で言語を変換する際に、もっとよい方法がありましたら、上記の回答以外にもアドバイスください。よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問に回答があった場合に通知・メールを受け取ることができます。

    クリップした質問はマイページの「クリップ」タブからいつでも見ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

CakePHP3でということなので、CakePHP3の機能を使った方法を紹介します。

言語の設定はAppControllerで切り替えるといいと思います。
AppControllerは基本的に全てのコントローラー共通の処理を行います。

// AppController
use Cake\Event\Event;
use Cake\I18n\I18n; // I18n::locale()を使えるようにする

public function initialize()
{
  parent::initialize();
  $this->loadComponent('Cookie'); // クッキーコンポーネントを使う
}

// 他の処理を開始する前に、先に言語を設定する
public function beforeFilter(Event $event)
{
  if (!empty($this->Cookie->read('lang'))) {
    I18n::locale($this->Cookie->read('lang')); // クッキーの値で言語を切り替える
  }
}

クッキーの値はクッキーの値を変更するためのコントローラー・アクションにPOSTして変更します。

// POST先のコントローラー

public function changeLanguage()
{
  if (!$this->request->is(['post'])) return; // POSTのみ許可

  $this->Cookie->write('lang', $this->request->data['lang']); // クッキーに言語をセット
  return $this->redirect($this->referer()); // 元のURLへリダイレクト
}


元のURLへ飛ぶ際にAppControllerの処理を通って言語を設定しているので、Kosuke_Shibuyaさんのおっしゃっている問題も起こらないはずです。

投稿 2016/07/23 11:25

編集 2016/07/23 11:30

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2016/07/23 23:59

    ありがとうございます。サンプルコードまで書いていただいたおかげで解決しました。クッキーコンポーネントがあったりすることは知りませんでした。また、コントローラーだけ呼び出すこともできるという使い方の発想がなかったので、同一ファイルにとりあえず書いてしまったのですが、まだまだよくわかっていないことだらけなので、とても感謝しています。

    キャンセル

+1

前提となる知識として、
セッション -> サーバー
クッキー -> ブラウザ
にデータを保存する仕組みであることは、問題ないですね。

記述されたソースを簡略化すると、

<?php
setcookie( 'lang', $lg ); // 何らかの値をクッキーにセット
〜
filter_input(INPUT_COOKIE, 'lang' ); // クッキーから値を読み込む

これが、一つのファイルに書かれています。
このファイルが実行されている間には、セットから読み込みの間に、サーバーとブラウザの通信はありません。
クッキーに保存された値はブラウザからサーバーに送信されて初めてスクリプトで読み込みが可能になります。

ですので、set_cookie() されてから少なくとも一度はブラウザと通信がされない限り、$_COOKIES に値は設定されないので、取得もできません。

投稿 2016/07/23 03:14

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2016/07/23 23:54

    ありがとうございます。クッキーの知識がほぼなかったので、非常に勉強になりました。同一ファイルに書かずにコントローラーに書いて解決しました。

    キャンセル

teratailには29人のエキスパートがいます

今すぐはじめる

もっと詳しく

関連した質問

同じタグがついた質問を見る

  • PHP

    12496questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • CakePHP

    1691questions

    CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

閲覧数の多いPHPの質問