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

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

ただいまの
回答率

89.07%

CakePHPでデータベースを利用したi18n。多言語を一括でデータ登録する方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 2,320

pack

score 196

前提・実現したいこと

CakePHPにて多言語対応のシステムを構築しております。
ユーザー登録画面にて、通常のユーザー登録と同時に日本語表示名の登録を行いたいです。

  • 多言語化の基本的な部分はできている
  • 選択言語はクッキーに保存している(jpn or eng)
  • Userテーブルは、Authコンポーネントを利用している。

登録フォームinputフィールド
username:user1
password:pass1
japanese_username(日本語表示名):ユーザー1

usersテーブル

id username password group_id created modified
1 user1 pass1 1 0000-00-00 00:00:00 0000-00-00 00:00:00
2 user2 pass2 1 0000-00-00 00:00:00 0000-00-00 00:00:00

user_i18nsテーブル

id locale model foreign_key field content
1 jpn User 1 username ユーザー1
2 jpn User 2 username ユーザー2

最終的に上記のように、データベースに登録を行いたいです。
i18nの基本的な使い方しか理解しておりませんので、方針などご提案いただければと思います。

課題

  • 選択言語に係らず、usernameはusernameに、日本語表示名をuser_i18nsテーブルのjpnのcontentに入れたい。

該当のソースコード

class AdminsController extends AppController{
  public $name = 'Admins';
  public $uses = array('User');

  public function beforeFilter() {
    parent::beforeFilter();
    //read cookie, language setting: 'eng' or 'jpn'
    switch ($this->Cookie->read('selectlanguage')){
      case 'jpn':
        Configure::write('Config.language', 'jpn');
        $this->User->locale='jpn';
        break;
      default:
        Configure::write('Config.language', 'eng');
        $this->User->locale=false;
        break;
    }
  }

  public function add(){
    if($this->request->is('post')) {
      $this->User->save($this->request->data);
    }
  }

}
<?= $this->Form->create('User', array('url' => 'add')) ?>
<?= $this->Form->input('User.username',array('label'=>__('username'))) ?>
<?= $this->Form->input('User.password',array('label'=>__('password'))) ?>

<!--- ここに input 日本語表示名を追加したい --->

<?= $this->Form->end(__('send')) ?>
class User extends AppModel {
  public $name   = 'User';
  public $actsAs = array(
    'Translate' => array(
      'username'
    )
  );
  public $translateModel = 'UserI18n';
}

現状

  • 選択言語により、usernameフィールドに入力された値がuser_i18nsのcontentに保存される。
$this->User->locale='jpn';

の場合、userのusername、user_i18nsのcontent、両方に保存される

試したこと

http://book.cakephp.org/2.0/ja/core-libraries/behaviors/translate.html

の"フィールドに対するすべての翻訳レコードを取得する"を参考に、取得できるなら保存もできるかと思ったが、動作は変わらず。

public $actsAs = array(
    'Translate' => array(
      'username'=>'usernameTranslation'
    )
  );
<?= $this->Form->input('User.username',array('label'=>__('username'))) ?>
<?= $this->Form->input('User.usernameTranslation.jpn',array('label'=>__('japanese_username'))) ?>

http://book.cakephp.org/3.0/en/orm/behaviors/translate.html

CakePHP3では、TranslateTraitというものがあるようですが、実現したいことはこのような事だと思います。

補足情報(言語/FW/ツール等のバージョンなど)

CakePHP 2.8.5
PHP 5.6.22
MySQL 5.5.45

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

    クリップした質問は、後からいつでもマイページで確認できます。

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2016/08/29 23:23

    i18nHelper を作ってそのヘルパーで翻訳をする以外思い浮かばないや

    キャンセル

  • pack

    2016/08/30 03:12

    お返事ありがとうございます。自己解決いたしました。

    キャンセル

回答 2

check解決した方法

+1

まず方針を変えて、userテーブルに新たにnicknameフィールドを追加するようにしました。
usernameを翻訳しようとすると、Authコンポーネントの認証が思ったように動かないなど不都合がありました。
そのうえで、

class User extends AppModel {
    public $actsAs = array(
            'Translate' => array(
                    'nickname'
            )
    );
    public $translateModel = 'UserI18n';
}


とします。

http://kristofferdarj.se/2012/05/cakephp-how-to-actually-use-i18n/

を参考に、下記の通りに保存をしてみたら、思い通りの結果になりました。

$this->User->locale='eng';

$add_data=array('User'=>array(
  'username'=>'tanaka',
  'password'=>'pass',
  'nickname'=>array(
    'jpn'=>'田中',
    'eng'=>'Tanaka',
    'hin'=>'तनाक'
  )
));
$this->User->saveMany($add_data); //** saveではダメ **

userテーブル

id username password nickname
19 tanaka pass Tanaka

user_i18nsテーブル

id locale model foreign_key field content
1 jpn User 19 nickname 田中
2 eng User 19 nickname Tanaka
3 hin User 19 nickname तनाक

最終的には、下記のようになりました。

//add.ctp
<?= $this->Form->create('User', array('url' => 'add')) ?>
<?= $this->Form->input('username') ?>
<?= $this->Form->input('password') ?>
<?= $this->Form->input('User.nickname.eng') ?>
<?= $this->Form->input('User.nickname.jpn') ?>
<?= $this->Form->end(__('send')) ?>

//Controller
public function add(){
  if($this->request->is('post')) {
    $this->User->locale='eng';
    $this->User->saveMany($this->request->data);
  }
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

とりあえず、以下のようにすることで、user_i18nsテーブルに日本語名が格納できることまでは、確認しました
一覧取得に際には、behaviorの機能なのか、適当にカラム名称を変換するため、注意が必要ですね
※変換された名称は、DebugKitでSQLを表示するとわかります

class User extends AppModel {
    public $actsAs = array(
            'Translate' => array(
                    'nicknameJpn'
            )
    );
    public $translateModel = 'UserI18n';
}

// add.ctp
<div class="users form">
<?php echo $this->Form->create('User'); ?>
    <fieldset>
        <legend><?php echo __('Add User'); ?></legend>
    <?php
        echo $this->Form->input('email');
        echo $this->Form->input('password');
        echo $this->Form->input('username');
        echo $this->Form->input('nicknameJpn');
    ?>
    </fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>

DBには、以下のように格納されます
id,    locale,    model,    foreign_key,    field,    content
'8', 'jpn', 'User', '11', 'nicknameJpn', 'テスト007'

Cakeの仲間では追いきれていませんが、おそらくカラム名称が重複するとどちらか一方のデータしか取得しないため、同一の値でi18nのテーブルにも登録されるのだと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/30 02:06

    お返事ありがとうございます。

    いただいたお返事がヒントになり、少し方針を変えました。
    そうしたら、解決できました。

    助かりました。ありがとうございました。

    キャンセル

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

  • ただいまの回答率 89.07%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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