10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-05-21

技術スタック

  • Laravel
  • docker
  • vue
  • typescript
  • sass

多言語化で考える事

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

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

基本的な方針として同じ文字ファイル?を使ってどのレイヤーも管理したい。
国際化の対応には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を生成するという方法です。

こういう方法のejs版が必要。

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


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

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

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

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

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?