技術スタック
- Laravel
- docker
- vue
- typescript
- sass
多言語化で考える事
- 各開発レイヤごとの多言語対応の方針
- design(mock/markup)
- gulp
- backend, api
- Laravel
- frontend
- vue
- typescript
- design(mock/markup)
- 開発環境でのテスト
- dockerでなにかすることはあるか?
- URL
- https://xxx.com?lang=en とかする?
- デプロイ
- 懸念は有るか?
各開発レイヤごとの多言語対応の方針
基本的な方針として同じ文字ファイル?を使ってどのレイヤーも管理したい。
国際化の対応にはi18n, l10nなどがある。一般的なのは前者だがライブラリを提供していないレイヤーも有る。あとなるべく固有のスクリプトとかで解決したくない。属人化したり保守が面倒なので、やるにしてもなるべくシンプルに。
各レイヤの要件
- design
Markupの作成、sass/htmlで完結する世界。ここでも各言語ごとに見え方が異なるので確認ほうがいい。仕組みとしてはhtml templateにejsを使う今回のケースの場合、変数として渡して描画を分けることになるので、どうにでもなる、jsonならいい。
英語、日本語両方を出力すればいい。
- backend(Laravel)
Accept-Languageを見て動的に表示。
Laravel5.4以上からjsonでの多言語対応をサポートしている。
{
"sample": "サンプル",
"required": ":attribute は必ず入力してください"
}
もしくは
{
"sample": "サンプル",
"required": ":attribute は必ず入力してください"
}
// アプリケーション内から呼び出し
echo __('sample');
// blade
{{ __('sample') }}
- backend(API)
Laravelに乗るので同じ。
ただapiのレスポンスをそのまま表示するようなUIを許容できなくなる。
この辺はエラーコードを返してそれに応じてフロントでjs形で表示を分けるのがいい。
- frontend(Vue)
2パターンある。
{
"ja": {
"message": {
"title": "タイトルだよーん",
"subtitle": "ここがサブタイトルになります"
}
},
"en": {
"message": {
"title": "title dayo-n",
"subtitle": "sub title dayo-n"
}
}
}
{
"message": {
"title": "タイトルだよーん",
"subtitle": "ここがサブタイトルになります"
}
}
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.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('./'));
});