よくあるLaravelを中心としたPJで多言語化対応で考えたことメモ

# 技術スタック
- Laravel 
- docker
- vue
- typescript
- sass

# 多言語化で考える事

- 各開発レイヤごとの多言語対応の方針
    - design(mock/markup)
        - gulp
    - backend, api
        - Laravel
    - frontend
        - vue
        - typescript
- 開発環境でのテスト
    - dockerでなにかすることはあるか？
- URL
    - https://xxx.com?lang=en とかする？
- デプロイ
    - 懸念は有るか？
  

# 各開発レイヤごとの多言語対応の方針

基本的な方針として同じ文字ファイル?を使ってどのレイヤーも管理したい。
国際化の対応にはi18n, l10nなどがある。一般的なのは前者だがライブラリを提供していないレイヤーも有る。あとなるべく固有のスクリプトとかで解決したくない。属人化したり保守が面倒なので、やるにしてもなるべくシンプルに。

## 各レイヤの要件

- design

Markupの作成、sass/htmlで完結する世界。ここでも各言語ごとに見え方が異なるので確認ほうがいい。仕組みとしてはhtml templateにejsを使う今回のケースの場合、変数として渡して描画を分けることになるので、どうにでもなる、jsonならいい。
英語、日本語両方を出力すればいい。

- backend(Laravel)

Accept-Languageを見て動的に表示。
Laravel5.4以上からjsonでの多言語対応をサポートしている。

```resources/lang/ja.json
{
  "sample": "サンプル",
  "required": ":attribute は必ず入力してください"
}
```

もしくは

```resources/lang/ja/message.json
{
  "sample": "サンプル",
  "required": ":attribute は必ず入力してください"
}
```


```
// アプリケーション内から呼び出し
echo __('sample');

// blade
{{ __('sample') }}
```

- backend(API)

Laravelに乗るので同じ。
ただapiのレスポンスをそのまま表示するようなUIを許容できなくなる。
この辺はエラーコードを返してそれに応じてフロントでjs形で表示を分けるのがいい。

- frontend(Vue)

2パターンある。

```message.json
{
  "ja": {
    "message": {
      "title": "タイトルだよーん",
      "subtitle": "ここがサブタイトルになります"
    }
  },
  "en": {
    "message": {
      "title": "title dayo-n",
      "subtitle": "sub title dayo-n"
    }
  }
}
```

```jp.json
{
  "message": {
    "title": "タイトルだよーん",
    "subtitle": "ここがサブタイトルになります"
  }
}
```


```App.js
const i18n = new VueI18n({
  locale: 'ja',
  messages: {
    en: require('./locales/en.json'),
    ja: require('./locales/ja.json')
  }
})

// もしくは
const i18n = new VueI18n({
  locale: 'ja', // デフォルト言語はjaにしておくが、ブラウザの言語を拾ってきてここに入れる => 言語変更されたら書き換える
  messages: data
});

// 追加も可能
const translationsEn = {
	"content": "This is some {type} content"
};

// translations can be kept in separate files for each language
// i.e. resources/i18n/de.json.
const translationsDe = {
	"My nice title": "Ein schöner Titel",
	"content": "Dies ist ein toller Inhalt"
};

// add translations directly to the application
Vue.i18n.add('en', translationsEn);
Vue.i18n.add('de', translationsDe);
```

前者の1ファイルのまとめるとjsでロード時にパフォーマンスに影響する可能性がある。後者の場合動的にjpファイルをrequireするような実装が必要。
画面ごとに分ける必要がありそう。
ここはPHPから渡してもいいかも。

### 懸念

vueとlaravelで多言語化フォーマットが異なる。PHPの方は制約が多いので、こっちで処理するのが良さそう。ここで以下の方針が取れる。


##　概ねの方針

- resources/design/src/lang/{lang}に画面ごとにjsonで言語ソースを設置
- 
```
resources/design/src/lang/common/jp.json
resources/design/src/lang/common/en.json
resources/design/src/lang/dashboard/jp.json
resources/design/src/lang/dashboard/en.json
...
```
- design(ejs)はこれをgulp内で読み込んで変数として読み込んで利用する
    - ビルド時にphp側にも設置

```gulp.example.js
gulp.task('build', function(){
  return gulp.src('./templates.ejs')
  .pipe(ejs({
    jsonData: [require('./land/common/{lang}.json'),
               require('./land/dashboard/{lang}.json');] //jsonData に data.json を取り込む
  }))
  .pipe(gulp.dest('./'));
});
```
- backend(Laravel)は5.4から利用できる仕組みを使ってこれを読み込んで利用する

```
views/lang/common/jp.json
views/lang/common/en.json
views/lang/dashboard/jp.json
views/lang/dashboard/en.json
...
```
- frontend(vue)はライブラリのVueI18nでこれを読み込んで利用する

```
Vue.i18n.add('jp', require('views/lang/common/jp.json'));
Vue.i18n.add('jp', require('views/lang/dashboard/jp.json'));
```

とりあえずこの手順ならリソースファイルを共有しつつ管理できそう。

# 開発環境でのテスト

普通にブラウザの設定を変更してテストすればいい。

# URLについて

基本的にAccept-Languageを見る。強制のものはクエリをつけて表示する方針。

# デプロイ時

ある程度のロジックを入れていくと思うので、抜け漏れないかをテストする仕組みが必要。

--- 
↓方針確定後に調査

### design

mockはejs, sass, jsで実装されている。
これの国際化はどうするのか？
gulpで多言語化するような仕組みはデフォルトではない。

> GulpでJadeをHTMLに変換する際に、文言を定義しているJSONファイルを流し込んで2つのHTMLを生成するという方法です。

[こういう方法](http://deepblue-will.hatenablog.com/entry/2015/06/12/%E9%9D%99%E7%9A%84%E3%81%AA%E5%A4%9A%E8%A8%80%E8%AA%9EWeb%E3%82%B5%E3%82%A4%E3%83%88%E3%82%921%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8B%E6%96%B9%E6%B3%95)のejs版が必要。

この仕組はjadeが引数を受けれる仕様になっているので動いている。

```js

gulp.task('jade', function() {
  var option = {
    pretty: true,
    locals: {
      siteName: 'かもメモ',
      lang: 'ja',
      devMode: true
    }
  };
```

jsonで変数定義できるところを工夫すればいけるのでは？

```js
gulp.task('build', function(){
  return gulp.src('./templates.ejs')
  .pipe(ejs({
    jsonData: jsonData //jsonData に data.json を取り込む
  }))
  .pipe(gulp.dest('./'));
});
```

http://tttttahiti.hatenablog.com/entry/2015/10/16/163320


＊参考
http://dotnsf.blog.jp/archives/1069456483.html