【PHPフレームワークFlow】Flowで多言語に対応したページを作成する

# 初めに
FlowではL10n（Localization）やI18n（Internationalization）に対応したページを作成することができます。今回は、Flowにおける対言語対応の方法をまとめていきます。

# Flowにおける多言語対応処理
Flowにおける多言語対応は以下の2ステップで行います。
* **文言を定義したメッセージファイルを言語（日本語、英語など）ごとに作成**
* **言語を指定し、対応するメッセージファイルを利用する**

翻訳は、以下の2つのクラスを使って行います。

* **Localeクラス**
* **Translaterクラス**

## Localeクラス
日本語や英語など、どの言語を使うかの情報を持つクラスです。

```php
$locale = new Locale('ja');
```

## Translaterクラス
実際に翻訳を行うクラスです。
Localeを引数に、対応した文言を返すメソッドなどが定義してあります。


# 多言語対応やってみた
ということで、実際にやってみましょう。
今回は以下の二種類を試します。
* **PHPソース内で翻訳するパターン**
* **HTML内で翻訳するパターン**

ディレクトリ構成は以下です。

```
Project
  └ Packages/
      └ Application/
           ├ Neos.Welcome/
           |    └ Classes/
           |         └ Controller/
           |              ├ I18nController.php（★）
           |              └ I18nHtmlController.php（★）
           |
           └ Resources/
                ├ Private/
                |    └ Templates
                |         └ I18nHtml/
                |              └ index.html（★）
                └ Translatins/
                     ├ en/
                     |  └ Main.xlf（★）
                     └ ja/
                        └ Main.xlf（★）
```

## 準備：言語ごとのメッセージファイルの作成
FLowでは、XLIFF形式のファイルを用いて各言語のメッセージがファイルを作成します。
今回は日本語と英語の二種類を作成しました。

日本語がこちら。
```xml: ja/Main.xlf
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
	<file original="" product-name="Neos.Welcome" source-language="ja" datatype="plaintext">
		<body>
			<trans-unit id="test.id">
				<source>テスト</source>
			</trans-unit>
		</body>
	</file>
</xliff>

```

英語がこちら。
```xml:en/Main.xlf
<?xml version="1.0" encoding="UTF-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
	<file original="" source-language="ja" target-language="en" datatype="plaintext">
		<body>
			<trans-unit id="test.id">
				<source>テスト</source>
				<target>test</target>
			</trans-unit>
		</body>
	</file>
</xliff>

```

:::note info
XLIFFは「XML Localization Interchange File Format」の略で、L10n（Localization）やI18n（Internationalization）などの翻訳が必要な場面で使用されるファイルの形式です。
:::


## パターン1：PHPソース内で翻訳する
PHPソース内で翻訳したメッセージを返すパターンを試してみましょう。

### 日本語
まずは日本語です。
以下のようなControllerを作成しました。

```php: I18nController
<?php
namespace Neos\Welcome\Controller;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\I18n\Locale;

/**
 * Event controller for the Neos.Welcome package
 */
class I18nController extends \Neos\Flow\Mvc\Controller\ActionController
{
    /**
     * @Flow\Inject
     * @var \Neos\Flow\I18n\Translator
     */
    protected $translator;
    
    /**
    * @Flow\Inject
    * @var \Neos\Flow\Mvc\View\JsonView
    */
    protected $view;

    /**
    * @return void
    */
    public function indexAction()
    {
        $locale = new Locale('ja');
        $response = $this->translator->translateById('test.id', [], null, $locale, 'Main', 'Neos.Welcome');
        $this->view->assign('value', $response);
    }
}
```

**ポイント**
* **返却したい言語を引数に`Locale`のインスタンスを作成**
* **`translateById`で対応した言語に翻訳**


実際に叩くと、以下のように日本語のレスポンスが返ってきます。
```sh
> curl -s http://localhost:8081/neos.welcome/I18n/index | jq .
"テスト"
```


### 英語

続いて英語にしてみます。
`Locale`を英語に変更するだけでOKです。
```php: I18nController
    public function indexAction()
    {
        $locale = new Locale('en');  // <--- 英語に変更
        $response = $this->translator->translateById('test.id', [], null, $locale, 'Main', 'Neos.Welcome');
        $this->view->assign('value', $response);
    }
```

レスポンスはこちら。英語で返ってきてますね！
```sh
> curl -s http://localhost:8081/neos.welcome/I18n/index | jq .
"test"
```


:::note info

`translateById`メソッドに渡す引数は以下になります

| 第〇引数 | 説明                                             |
|----|--------------------------------------------------|
| 1  | XLIFFファイルに定義したメッセージID                                 |
| 2  | 文言に渡す引数                                   |
| 3  | 数（翻訳語に複数形の単語にするかどうかで使用）   |
| 4  | Localeクラス                                     |
| 5  | XLIFFファイル名                                    |
| 6  | パッケージ名                                     |
:::



## パターン2：HTML上で翻訳する
続いて、HTML上で翻訳する方法です。

### 日本語

まずは日本語から。
```html: I18nHtml.html
{namespace original=Neos\Welcome\ViewHelpers}
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTMLファイル</title>
</head>
<body>
    <h1>
        <f:translate id="test.id" locale="ja" source="Main" />
    </h1>
</body>
</html>
```

**ポイント**
* **`f:translate`タグを使用する**
* **パッケージを指定しない場合、HTMLファイルがおいてあるパッケージを指定する**

実際にアクセスすると、日本語で表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/4e7319be-a2a8-f0d6-6346-aa2f2e26b03e.png)

### 英語

続いて英語にしてみます。
こちらもlocaleの引数を変えるだけでOKです。

```html: I18nHtml.html
<f:translate id="test.id" locale="en" source="Main" />
```

無事に英語になりました。簡単ですね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430841/11470485-fc0c-59fc-0bd3-1bd30ad11cbd.png)



# 終わりに
今回はPHPフレームワークFlowで多言語対応のページを作成する方法を解説しました。実際に作る場合は設定ファイルなどにデフォルトの言語を用意したり、セッションにユーザが指定した言語を持たせたりなどすると思うので、もう少し複雑になると思いますが、基本的にはこんな感じです。

また何か知ったらアウトプットします！
ここまで読んでいただきありがとうございました！