SketchとGoogleスプレッドシートを連携させてアプリの文言を管理する
アプリのボタンの文言を決めるとき、「体言止めにする? 動詞にする? あれ、既存画面の文言はどうしてたっけ?」ってなるときがあります。Kanmu のデザイナー小山内です。
アプリ内文言の一覧があれば、表記ゆれに気づきやすいかなって。あわよくば、それを Sketch にシームレスに取り込めたらラクかなって。そう思っていたら、Kanmu Tech Day がやってまいりました。
Kanmu Tech Day とは
テクノロジーを使って業務の効率化や、何かおもしろそうな試みをやってみようという、月に1回おとずれる社内アクティビティ。
新しいツールを試してみるもよし。プログラムを書いてみるもよし。18:00頃から缶ビールをあけ、ひとり1〜2分で今日やったことをゆるく発表しあう会。
文言管理のしくみが欲しいと思って、ぼくが作ってみたものがコレ↓
アプリのボタン文言を一覧するスプレッドシートと、
スプレッドシートのセル値を Sketch に反映する仕組み。
この記事はデザイナーのぼくが GAS(Google Apps Script)を書いて、スプレッドシートと Sketch を連携を試みた記録です。
── とある10月23日の水曜日
10:30_今日は何を作ろう
冒頭に書いた課題について考えていた。
アプリ内文言の管理だ。
現状は明文化された文言表現のルールはない。
ひょっとして自分が作ったアプリの画面に、気づかずに紛れこませてしまった表記ゆれがあるのではないか?
だとしたら、だらしがないぞ。
許すまじ、表記ゆれ。
今後の文言管理のために、既存のアプリ内文言をスプレッドシートにまとめてみるか。
時間がないから、いったんボタンの文言のみで。
ただ、それだけではつまらない。
せっかく社内のエンジニアさんに GAS 勉強会をひらいてもらってたんだ、GAS を使ってなんかできないだろうか。
そういえば先日、こんな記事を見た。
スプレッドシートで作ったデータを Sketch のデザインに反映するやり方だ。
なるほど、スプレッドシートの中身をテキストデータ(.txt)で書き出せば、それを Sketch で読みにいける。
スプレッドシートと Sketch の連携ができあがる。
これを作っちゃおう。
──
11:00_ちがう、そうじゃない
Sketch の機能のおさらいをすると、Sketch Dataという仕組みがあって、ローカルの画像やテキストデータを読み込んで、オブジェクトに適用することができる。
(↑ Using the new Data feature in Sketch 52 より)
先ほどのGain a Real Advantage with Sketch 💎 Dataって記事の動画を見たところ、リストからデータの種類を選択して値を入力している様子があった。
やってみたいのは、たとえば上図のようなリストから「ボタン文言」をクリックして、表示された文言一覧の中から入力したいテキストを選んでオブジェクトに反映するということ。
さっそくボタン文言の一覧をテキストデータで作って、Sketch Data の動作を試してみた。
新規登録
ログイン
チャージリクエストを作成
リアルカードを発行
↑こいつを「ボタン文言.txt」ってファイル名で保存して、Sketch から読み込む。
すると、どうだろう。
「ボタン文言」をクリックすると、テキストオブジェクトに「チャージリクエストを作成」と反映された。
テキストファイルの中身がリスト化されるわけではないのか。
そっか、もともと Sketch Data はダミーデータを入れる用途を想定しているから、「ボタン文言.txt」に書かれた4行のテキストのうち、いずれかがランダムで反映されるのな。
ちがう、やりたいのはそれじゃない。
──
11:30_じゃ、こうしよう
リストから「新規登録」をクリックするとテキストオブジェクトに「新規登録」と反映させるようにしたい。
そのためには、「新規登録」とだけ書かれたテキストファイルを「新規登録.txt」ってファイル名で用意すればよい。
つまりディレクトリ構造はこう。
ボタン文言/
├─ 新規登録.txt
├─ ログイン.txt
├─ チャージリクエストを作成.txt
└─ リアルカードを発行.txt
上記でデータを用意して、「ボタン文言」フォルダを Sketch から読みにいけば、選んだテキストをオブジェクトに反映するってことができそうだ。
スプレッドシートを作って、上記ディレクトリ構造になるようにテキストファイルを書き出せば、スプレッドシートと Sketch が繋がるはず。
よし、ごはん食べよう。
──
13:00_まずはスプシー
さっそくスプレッドシートで文言リストをつくる。
A列がボタンの文言、B列はヘルプページへ遷移するテキストリンクの文言、という具合に書いていく。
ほんとはもっとたくさんあるけど、いったんここまで。
おいおい。
さっそくボタンの文言に「認証」と「認証する」のユレが存在するじゃないか。
これは自分が作った画面に存在するボタン。。反省だ。
しかしこうやってリスト化すると、表記ゆれや表現の違いに気づきやすい。
テキストリンクも「〜について」と「〜について詳しくはこちら」と「〜って?」があるけど、これって意図的に使い分けてるんだっけ?とか。
うん、悪くない。
そして、このスプレットシートから下記のようなディレクトリ構成でテキストファイルを書き出そう。
ボタン文言/
└─ ボタン/
├─ 新規登録.txt
├─ ログイン.txt
├─ チャージリクエストを作成.txt
└─ ・・・
└─ サポートページへのテキストリンク/
├─ 申込み金額について.txt
├─ 手数料について詳しくはこちら.txt
└─ ・・・
└─ ドキュメントへのテキストリンク/
├─ 新規登録.txt
└─ ログイン.txt
スプレッドシートの1行目を「フォルダ名」、2行目以降を「テキストの内容 & ファイル名」というロジックでファイルを書き出す GAS を書けば良さそう。
うん、良さそう。
──
15:00_そしてGAS
GAS を書く。
スプレッドシートのメニューから「ツール > スクリプト エディタ」と選ぶとGAS エディタが登場。
まずはシート内のセル値をごそっと取得する、ための関数を書く。
/**
* シートのセル値を取得
* @param {string} sheetId スプレッドシートID
* @param {string} sheetName シート名
*/
function _getSheetValues(sheetId, sheetName){
var sheet = SpreadsheetApp.openById(sheetId).getSheetByName(sheetName);
var lastRow = sheet.getLastRow();
var lastCol = sheet.getLastColumn();
var values = sheet.getRange(1, 1, lastRow, lastCol).getValues();
return values;
}
シートIDとシート名を受け取って、セルの値を2次元配列で返す。
A列〜C列を順番にながめていって、1行目ならフォルダ作る、2行目以降はテキストファイル作ってフォルダに入れる、ってことをやっていけば良さそう。
フォルダつくって、テキストファイルつくればいいんだ。
先生、それってどうやるんですか。
──
17:00_なおもGAS
社内のエンジニア先生に GAS のドキュメントの読み方は教わっていた。
そして Google 先生のアドバイスを受け、こういう記述でテキストファイルを書き出せそうだとわかった。
/**
* ファイル書き出し
* @param {string} folder フォルダ名
* @param {string} content コンテンツ内容 兼 ファイル名
*/
function _createFile(folder, content){
var contentType = 'text/plain';
var charset = 'utf-8';
var fileName = content + ".txt";
var blob = Utilities.newBlob('', contentType, fileName).setDataFromString(content, charset);
folder.createFile(blob);
}
フォルダ名とテキストを受け取って、.txt のデータを書き出す。
書き出し先は Google Drive になるのだけど、Google Drive File Stream でローカルのディレクトリと同期すれば、Sketch からアクセス可能だね!
見えた、道が。
発表まであと10分。
...あ、間に合わないや。
──
17:30_発表
カシュっ。
缶ビール飲みながらほかの人の発表を聞く。
エンジニアじゃない人もゴリゴリプログラム書いてたりしておもしろいなー。
Slack のワークフローって、そう使うのか。
・・・
そして自分の番。
ビール片手にゆるーく発表しました。
やろうとしていること、ここまでできましたよ、まだできてないよ、と。
「いままで既存の文言確認するのに過去にとったスクショとか探してました」という声。
そうすよね。自分もそうしてました。
そんな面倒はなくすぞ。
さて、定時までに片をつけよう。
──
18:40_できあがりへ
できた。
function exportTextFiles(){
// 書き出し先のフォルダ
var targetFolder = DriveApp.getFolderById(【フォルダのID】);
// 文言一覧スプレッドシート
var sheetValues = _getSheetValues(【スプレッドシートID】, 【シート名】);
if (sheetValues.length == 0) {
return false;
}
// サブフォルダを削除する
var oldFolder = targetFolder.getFolders();
while (oldFolder.hasNext()) {
targetFolder.removeFolder(oldFolder.next());
}
// ファイルを書き出す
for(var j in sheetValues[0]){
var folderName = sheetValues[0][j]; //1行目がフォルダ名
var folder = targetFolder.createFolder(folderName);
for(var i = 1; i < sheetValues.length; i++){
// 空セルを見つけたらスキップ
if (sheetValues[i][j] == "") {
break;
}
// テキストファイルを作成
_createFile(folder, sheetValues[i][j]);
}
}
}
//--------------------------------------------------------------------------------------------------
/**
* シートのセル値を取得
* @param {string} sheetId シートID
* @param {string} sheetName シート名
*/
function _getSheetValues(sheetId, sheetName){
var sheet = SpreadsheetApp.openById(sheetId).getSheetByName(sheetName);
var lastRow = sheet.getLastRow();
var lastCol = sheet.getLastColumn();
var values = sheet.getRange(1, 1, lastRow, lastCol).getValues();
return values;
}
/**
* ファイル書き出し
* @param {string} folder フォルダ名
* @param {string} content コンテンツ内容 兼 ファイル名
*/
function _createFile(folder, content){
var contentType = 'text/plain';
var charset = 'utf-8';
var fileName = content + ".txt";
var blob = Utilities.newBlob('', contentType, fileName).setDataFromString(content, charset);
folder.createFile(blob);
}
このスクリプトを実行すると、書き出し先のフォルダの中身を空にして(ここ注意)、テキストファイルを新たに書き出す。
Sketch Data は一度読み込み先のフォルダを指定すれば、フォルダ内のデータが書き換わっても、再設定なしで最新のテキストを呼び出せる。
スクリプトを実行したあと、ファイルの書き出しに少々時間がかかるのが難点ではあるけど、いったんこれで使ってみよう。
表記ゆれ、なおさなきゃ。
(完)
──
ちなみに
スプレッドシートの内容をデザインデータに反映する手段はいくつかありまして、Sketch だと例えばこれ↓とか、
Figma だとこういうプラグイン↓使うとか。
いずれもテーブル等に一括でテキストを反映するという用途に向いてますね。
今回は Sketch からスプレッドシートの中身を一覧する → Overrides でシンボルに反映する、というものがほしくて作ってみました。
そのうちもっと便利なプラグインや機能が出てくるかもしれませんね。スクリプト書かなくてもよいやつ。もしご存知だったら教えてください。
最後に
現在カンムでは新規事業の開発も進めており、絶賛メンバー募集中です。
「特定の領域にフォーカスして発明を行い、発明をつなげて結果的に強いプラットフォームを構築する」
ご興味のある方はぜひご連絡ください!
・フロントエンドエンジニア
・バックエンドエンジニア
・インフラエンジニア
・新規事業リードエンジニア
・デザイナー
・プロジェクトマネージャー
・採用PM
・CS/オペレーション責任者
・オペレーション(不正モニタリング)
・マーケティングマネージャー
・オンライン広告担当
・法務・コンプライアンス
・総務
・ガバメントリレーションズ
次回記事のため、書籍代等のインプットに使わせていただきます!