booklista tech blog

booklista のエンジニアリングに関する情報を公開しています。

多言語展開のためにFigmaプラグインを開発した話

アイキャッチ

はじめに

株式会社ブックリスタのプロダクト開発部/新規事業開発チームでエンジニアをしている城と申します。 iOS向け推し活アプリOshibanaとショートマンガまとめ読みアプリヨムコマをより良くすべく日々奮闘しています。

Oshibanaについては以前の記事で紹介をしていますので、ぜひともご一読ください。

App Storeで3位になったアプリをFlutterでつくっている話 https://techblog.booklista.co.jp/entry/2022/07/11/155531

Oshibanaは日本語表示のみ対応しておりましたが、多言語展開をすべくまずは中国語での表示を実装中です。 多言語展開するにあたりUIラベリングの翻訳データをどのように管理するかチームで話し合い、最終的にFigma1のプラグインを開発するに至りました。 この記事ではチームで検討したことを中心に、Figmaプラグイン開発でのつまずきポイントもお伝えします。

プラグインの紹介

今回Oshibanaが公開したFigmaプラグインText to variablesです。

Figma内のテキストを一括でバリアブルズに取り込む事が可能です。 バリアブルズ取り込み時にテキストとバリアブルズの紐付けも自動で行います。 取り込み不要なレイヤーはロックをかければ取り込まない設定が可能で、さらに取り込み対象テキストをチェックボックスで選択可能です。

Figmaベースで多言語対応を検討されている方はぜひ使ってみて頂けると嬉しいです。

Oshibana開発の流れ

Oshibanaでは次にリリースする機能の概要が決まると、デザイナーが中心となってFigmaでデザインデータを作成しています。 この時SlackやミーティングでPdM / デザイナー / エンジニアが集まってFigmaを囲んで機能詳細を詰めていきます。 デザインや仕様の議論はSlackやミーティングで直接聴くこともありますが、後で見返しやすいようFigmaのコメント機能を使うことが多いです。 こうして完成したFigmaデザインデータを見ながら担当エンジニアがアプリを実装し、検証を経てリリースします。

OshibanaはFigmaに仕様が詰め込まれた状態となっていて、Figmaの各レイヤーには日本語テキストが置かれた状態です。 日本国内でアプリ展開している場合、よくある状況なのではないでしょうか。

さてここで”中国語表示に対応しよう”となったら多言語リソースの管理はどのように行えばよいでしょう。

プラグイン開発までの経緯

新規事業開発チームはアジャイルで開発しているので、素早く価値を提供し検証していく事をとても大切にしています。 仕様を詰めてから開発するよりも「素早く提供できる方法」を大切な仕様選定方法としています。 結論としてOshibanaでは多言語翻訳データの管理のためにFigmaプラグインを開発するのですが、そこに辿りつくまでには別案もありました。 新規事業開発チームがなぜプラグイン開発に至ったか、その経緯を公開します。

エンジニアの要望

エンジニアの要望は2点ありました。

1つ目

多言語リソースの管理方法にかかわらず、最終的にJSONでエクスポートが可能なこと 欲しいJSONイメージはこのようなものです。

日本語.json {
  "推し": "推し",
  "生年月日": "生年月日",
  "プレミアム": "プレミアム"
}

中国語.json {
  "推し": "我推",
  "生年月日": "出生日期",
  "プレミアム": "会员专享区"
}

2つ目

できる限り実装時に見るウィンドウを増やしたくない 普段エンジニアはFigmaとVSCodeの2つのウィンドウを見て実装しています。 さらに別ウィンドウで言語リソースファイルを見る必要が出てきたら実装時の負担が増えます。 必要ならある程度は仕方がない事ですが、少ない負担で気持ちよく仕事をする環境作りは大事な事なので要望としてあがりました。

見送った案その①

まず「多言語表示がFigmaで完結できたらいいね」という意見が真っ先に出ました。 日本語で入力されたテキストから長い矢印を引いて他の言語を書くというもので、イメージはこんな感じです。   案①

Pros

  • 訳語がUI上のどの位置に紐づいているのか視覚的に分かりやすい
  • UIに関する情報はFigmaで完結できる

Cons

  • デザイナーが中国語表示時のレイアウト崩れに気がつきにくい
  • JSONデータに整形する際、Figmaからテキストをコピペする必要がある
  • デザイナーがUI作成時に矢印を引く必要があるのでUI作成負荷が上がる
  • Figma内が矢印だらけで情報が煩雑になる

Summary

この方法はメリットよりデメリットが勝ります。 特にFigma内の情報が煩雑になる事がクリティカルであるため別案を模索することになりました。

見送った案その②

次に出たのはスプレッドシートを使った案でした。 アプリのソースコード内にあるUIラベリングをすべてスプレッドシートA列へ抜き出しB列に中国語を書く、別言語を足す時はC列に書くというものです。

案②

Pros

  • シンプルで直感的に分かりやすい

Cons

  • デザイナーが中国語表示時のレイアウト崩れに気がつきにくい
  • スプレッドシートに追加文言を転記するのが大変
  • 初回の文言抜き出し時及びUI追加時に文言更新もれが起きそう
  • エンジニアが実装時に開くウィンドウが増える

Summary

すぐにでも作業を始められるシンプルさは大きなメリットです。 デメリットは案①と比較してクリティカルと思われる欠点はありませんが、デメリット数は気になるところです。

採用した案

前述のように素早く価値を提供することも重要なので、仕様が分かりやすいスプレッドシート案に決まり一度舵を切りました。 ですが”他にいい方法はないものか…デザインデータと仕様の管理はFigmaで完結できたらいいのに”という思いが残っていました。 Figmaのプラグインを探しているうちに、Figmaには後述のバリアブルズというオープンベータ機能(202403時点)が存在することに気がつきました。

バリアブルズとは

ここでは簡単に説明するので、詳細はFigma公式のガイドを参照してください。

バリアブルズとはその名の通りFigma上で定義できる変数を指し、1つの名前に対し複数ので構成された変数を定義できます。 バリアブルズはコレクション > グループ > バリアブル > 名前 > 値 という階層構造になっていて、目的に応じてコレクションやグループ分けが可能です。

バリアブルズがどんなものか、下記の画像を参照ください。

バリアブルズとは

左がバリアブルズの中身、右がウィジェット/サイズ選択/という画面のデザインデータです。 バリアブルズの中身はブログサンプルというコレクションの中に、ウィジェット/サイズ選択/と画面名でグループ化されていて、値には画面に必要な全てのテキストを入れています。 は2つ作成し、それぞれの値のタイトルを日本語と中国語に設定しました。

またテキストに対し単一のバリアブルを紐付けることで、セクションやフレーム内のテキストを一括で日本語/中国語の切り替えることができます。 テキストにバリアブルを適用するには、紐付けしたいテキストを選択した状態で画像赤丸のバリアブルズ適用を押すとバリアブルがリストされるので、紐付けたいバリアブルを選択するだけです。 テキストとバリアブルの紐付け

全てのテキストにバリアブルを適用したら、中国語UIに一括で切り替えてみましょう。 ウィジェット/サイズ選択/画面全体のレイヤーを選択し、右のデザインパネルで六角形のバリアブルズボタンを押し、コレクションと値を選択します。 値は自動になっていましたが中国語を選択します。

言語切り替え

画面全体が中国語に切り替わりました。

💡 Tip
レイヤーに対するバリアブルズ設定はレイヤーの親子要素それぞれに設定できます。 親子レイヤーそれぞれにバリアブルズが設定されている場合は子レイヤーの設定が優先されます。 親レイヤーの選択でテキストが切り替わらない場合は、子レイヤー個別にが適用されていないか確認してみてください。

Pros

  • Figma上で日本語/中国語の表示切り替えが可能
  • エンジニア要望を全て満たせる
  • UIに関する情報はFigmaで完結できる

Cons

  • Figma上の全テキストをバリアブルズに設定する方法が未定
  • バリアブルズ機能がベータ

Summary

バリアブルズを使うメリットが多いのでこちらの案を採用することになりました。

バリアブルズを使う

バリアブルズを使えば多言語リソース管理をFigmaで完結して、Oshibanaの多言語展開にマッチすることはわかりました。

問題は今あるFigmaのレイヤーに配置されたテキストをどうやってバリアブルズに取り込むのか。 私たちはこれを実現する機能を備えたFigmaプラグインをこんな条件で探し始めました。

  1. テキストを一括でバリアブルズに取り込める
  2. Figma内には説明文章等も配置されているので、特定のセクションやフレーム内のテキストだけを拾いたい
  3. バリアブルの名前と同じものを値にも入れたい
  4. バリアブルズへ取込む時にグループを指定したい

条件に近いものは見つけましたが、取り込み対象がFigmaドキュメント全体だったり、グループ指定できなかったりと完全にマッチするプラグインを見つけることができませんでした。 もっと時間をかければ希望のプラグインが見つかった可能性はありますが、そこに時間をかけず必要な機能は自分達で作れば良いし、プラグインを作ってみたら楽しそうという思いもあり作ることに決まりました。

バリアブルズをJSONにエクスポートする機能はFigma Variables to JSONというプラグインで満たせたため、開発スコープから外しました。

ここまでが私たち新規事業開発チームが検討した流れです。

Figmaプラグイン開発

プラグインはHTMLとTypeScriptで開発できます。

Figmaプラグイン開発の公式ドキュメントは英語のみですが、わかりやすく書かれているのでアイデアを形にできるか悩まれた際は見てみることをおすすめします。

サンプルのプラグインを作って動かしてみます。

必要なもの

  1. Figmaデスクトップ版
  2. VSCodeなどのエディタ

サンプルプラグインを作成

Figmaデスクトップ版でプラグイン > 開発 > プラグインの新規作成...を選択します。 サンプルプラグインを作成①

プラグイン名は後からでも変更可能ですがFigmaコミュニティに表示される名称となります。 Figmaデザイン+FigJamを選択したまま次へを押します。 サンプルプラグインを作成②

今回は画面を伴うプラグインを作るのでカスタムUIを選択して名前を付けて保存を押します。 保存先を聞かれるので、ソースコードを置く場所を選択してください。 サンプルプラグインを作成③

完了を選択して作成されたフォルダをVSCodeで開きます。 サンプルプラグインを作成④

作成されたフォルダ配下で下記コマンドを実行します。

  1. npm install
  2. npm install -D @figma/plugin-typings
  3. npm run watch

Figmaデスクトップでプラグイン > 開発 > 作成したプラグイン名を押すと下記の画面が起動します。 サンプルプラグインを作成⑤

Createを押して画像のようなオレンジの四角が出てきたら成功です。 サンプルプラグインを作成⑥

解説

ui.html

プラグインのUI部分で、普通のhtmlと同様にstyleとscript要素も置けます。 ui.html > a.htmlのような画面遷移はできないようなので、表示内容を切り替えたい場合はstyle.displayを使ってdomの表示/非表示を切り替える事で実現可能です。

後述するcode.ts内の処理を呼び出すには下記にように書きます。

parent.postMessage({ pluginMessage: { type: 'create-shapes', count } }, '*')
parent.postMessage({ pluginMessage: { type: 'cancel' } }, '*')

code.tsから値を受け取る時は下記の書き方です。

onmessage = (event) => {
    const msg = event.data.pluginMessage;
    if (msg.type === 'receive-shapes') {
    // receive-shapes受信時の処理
  } else if (msg.type === 'on-error') {
    // on-error受信時の処理
  }
}

code.ts

FigmaAPIを使用することでFigmaに配置済みのレイヤーを取得したり、バリアブルズを操作する処理を書くファイルです。

先述のui.htmlを開く処理です。

figma.showUI(__html__);

ui.htmlでparent.postMessage()を実行した時に呼ばれる処理です。 ui.htmlでも記載しましたがtypeで処理を分けて記述すると良いでしょう。

figma.ui.onmessage =  (msg: {type: string, count: number}) => {
  if (msg.type === 'create-shapes') {
    // ui.htmlからcreate-shapesが呼び出された
  } else if (msg.type === 'cancel') {
    // ui.htmlからcancelが呼び出された
  }
};

ui.htmlの処理を呼び出したい時は下記の書き方です。

figma.ui.postMessage({
  payload: {
    id: shape.id,
  },
  type: 'receive-shapes',
});

code.js

code.tsをコンパイルした後のファイルで、このファイルを直接修正することはしません。

manifest.json

プラグインのメタ情報が書かれたファイルです。 Figmaコミュニティで表示されるプラグイン名の指定や、実行ファイル名が記述されていますが詳細は公式のPlugin Manifestを参照してください。

あとがき

ブックリスタの新規事業開発チームは「やってみたい」を尊重してくれる環境です。 チームみんな「やってみたい」に対して「やってみようか、こんな感じの機能がいつまでにあると嬉しい〜」と背中を押してくれるので感謝しています。 チームの雰囲気①

新規事業開発チームは、素早く最小機能でリリースをしてからユーザーフィードバックに基づいて改善を繰り返すMVP開発を採用しています。 Figmaプラグインについても同様で、まずは1日でも早くチームのデザイナーに使ってもらう事を目的として最小機能でリリースしました。 その後現在も、このような雰囲気でデザイナーからフィードバックをもらい改善するサイクルが不定期で走っています。 チームの雰囲気②


  1. Figmaとはブラウザもしくはデスクトップアプリで使えるリアルタイムコラボレーションに特化したデザインツールです。