カテゴリー
Uncategorized

Rails7におけるdata-confirm

Railsではフォームやリンクを生成するヘルパーを使う時、共通して data-confrm という属性をつけると、確認アラートを表示することができました。しかし、Rails7においてはこれだけでは動きませんでした。

そもそも、どのようにこの動作を実現しているかといえば、 rails-ujs というgem(中身はjs)のおかげです。rails-ujs はrails5.1.0以降、rails本体に取り込まれました。

https://github.com/rails/rails/tree/main/actionview/app/assets/javascripts

rails-ujs の役割として、confirmの制御、非getリクエストの実行、非同期リクエストの実行、サブミットボタンの非活性制御を行うライブラリとなっています。railsの便利機能を実現するためのフロントエンドで動く小さなjavascriptです。

Rails7においては、このgemはデフォルトでインストールされていません。つまり rails-ujs を単体でインストールすれば動くということです。

npm install @rails/ujs --save

実態としては小さなjsであるため、npm経由でインストール可能です。このjsをassetsパイプライン経由などで読み込ませることで今までの開発体験を取り戻すことができます。

しかし、なぜRails7ではデフォルトでインストールされていないか、そこを知っておく必要があるでしょう。

Rails7では、新しいフロントエンドフレームワークとして、TurboとStimlus(2つ合わせてhotwiredと呼ばれます)が導入されました。Turbo自体は rails-ujs の置き換えという立場ではありませんが、rails-ujs の機能を一部取り込んでいます。それが今回、data-confirm が動作しな理由の一つです。

Turboを前提とした確認ダイアログの実装

Turboを使用する場合、data-confirm の代わりに data-turbo-confirm を使用します。

form_tag "#action", method: "post" ,data: { turbo_confirm: "送信しますか?" }

そしてこの属性は常にformタグに設定する必要があります。これが一癖。例えば、formを生成するbutton_toの場合は、下記のように指定する必要があります。

= button_to "削除", "#button", method: "delete", form: { data: { turbo_confirm: "削除しますか?" } }

link_toはどうなるの?

こちらも data-turbo_confirm に置き換えです。

data-turbo_method を指定すると、data-turbo_confirm が有効になるようです。

= link_to "削除リンク", "#button",  data: { turbo_method: "get", turbo_confirm: "削除しますか?" }
カテゴリー
Uncategorized

[css/js]bundling-railsを使用したRails7プロジェクトをDockerCompose化する

[css/js]bundling-railsの使用を前提としているため、開発環境のサーバー立ち上げは ./bin/dev を使用します。今回の環境の構成は下記の通りです。

Rails 7.0.3.3 / Ruby 3.0.0 / Bundler 2.3.9 / Nodejs 12 / MySQL 8.0

FROM ruby:3.0.0-buster

# for nodejs
RUN curl -fsSL https://deb.nodesource.com/setup_12.x | bash -

# for yarn
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y build-essential nodejs yarn vim zlib1g-dev liblzma-dev patch

RUN node -v
RUN yarn -v

RUN gem uninstall bundler
RUN gem install bundler -v 2.3.9

RUN mkdir /tmp/app-init
WORKDIR /tmp/app-init
ADD Gemfile .
ADD Gemfile.lock .
RUN bundle install

RUN mkdir /app
WORKDIR /app
services:
  mysql:
    image: mysql:8.0
    restart: always
    cap_add:
      - SYS_NICE
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_PASSWORD: password
    volumes:
      - ./mysql-confd:/etc/mysql/conf.d
  rails:
    build: .
    tty: true
    command: >
      sh -c "
        rails db:create && rails db:migrate &&
        rm -f tmp/pids/server.pid &&
        yarn install
        ./bin/dev
      "
    environment:
      TZ: Asia/Tokyo
      NODE_ENV: development
      RAILS_ENV: development
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - mysql
[mysqld]
default_authentication_plugin=mysql_native_password
web: bin/rails server -p 3000 -b 0.0.0.0
js: yarn build --watch
css: yarn build:css --watch
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  host: mysql

Dockerfileの内容

ruby-3.0.0の公式イメージをベースとして、nodejs12、yarn、その他サーバーライブラリのインストールを行い、bundle installを実行してイメージ化しておきます。

こうするとbundle installをキャッシュしてくれるので起動が早いはずです。

docker-compose.ymlの内容

mysql8.0コンテナと、railsコンテナの2つを実行します。

mysqlコンテナは、mysql-confd/default_authentication.cnf に設置した設定ファイルの入ったディレクトリをコンテナ内にマウントします。設定ファイルは、パスワード認証を許可する設定が書かれています。

railsコンテナは、db:create db:migrate を実行したのち、./bin/dev を実行します。このとき、tty: true オプションをつけなれけばならないようです。

Procfile.devの内容

Dockerコンテナの外からHTTPアクセスできるようにする必要があります。Railsサーバーの起動オプションに -b 0.0.0.0 を追加することで、127.0.0.1/localhost以外からのアクセスを許可します。

config/database.yml

コンテナtoコンテナのホスト名はdocker-compose.ymlで定義した名前でアクセスできるようになります。hostmysqlを指定します。

コンテナの起動

docker-compose build
docker-compose up

Gemfileの追加があったら、buildとupをやり直します。(startではボリュームが作り直されない)

カテゴリー
Uncategorized

cssbundling-railsのtailwindcssがslimで効かない

時間を相当無駄にした。

tailwind.config.jsのcontentを確認してみましょう。

'./app/views/**/*.html.erb'
↓
'./app/views/**/*.html.slim'

言い訳だけど、知ってたんです。本当に。
知ってたのに思い出せなかった。

カテゴリー
Uncategorized

Rails7時代のJS/CSSバンドルの新常識

Rails7では、jsをバンドルせずにimportmapでjsを直接読み込む方式がデフォルトとなりました。しかしwebpack等でのバンドル方式の選択肢を完全に失ったわけではありません。特定のターゲット(ES5など)にトランスパイルすることができます。レガシーブラウザをサポートする要件下ではバンドル方式を選択することもあるでしょう。そこで来たるRails7時代に、我々アプリケーションエンジニアにとってどのような手段があるのか、Railsの基礎知識をアップデートしていくのがこの記事の目的になります。早速始めましょう!

JSの読み込ませ方

かつてのRailsではSprocketsでバンドルして単一のjsファイルとして配信する方法が常識でした。Sprocketsはトランスパイルはしないものの、minifyする仕組みを持っていました。

Rails7からは、importmapまたはwebpack/esbuild/rollupでのバンドルの方法を採用できます。rails newする際にオプションを明示しない限り、デフォルトでimportmapがが使用されます。railsとimportmapの組み合わせはimportmap-railsというGemが受け持ちます。もしくは、-j [webpack/esbuild/rollup]を指定すると、jsbundling-railsというGemがよしなにしてくれます。

importmapはトランスパイルを行いませんので、最新のブラウザをターゲットとする場合以外には採用が難しいかもしれません。その場合はwebpackやesbuildなどのバンドラーでES6やES5などをターゲートとしてトランスパイルしたものを配信する式を採用するのが良いでしょう。

importmap-rails

importmapを使用するには、bundlerでimportmap-railsをインストールし、コマンドを実行します。

./bin/rails importmap:install

サードパーティのESModuleを追加するには、コマンドを実行します。Railsの場合、app/javascript/application.jsもまた、sprocketsでビルドされたものをimportmap経由でロードされます。

./bin/importmap pin react react-dom

レイアウトやビューファイルではjavascript_importmap_tagsヘルパーがjsを呼び出す起点となります。

<%= javascript_importmap_tags %>

jsbundling-rails

jsbundlingを使用するには、bundlerでjsbundling-railsをインストールし、インストールコマンドを実行します。

./bin/rails javascript:install:[esbuild|rollup|webpack]

注)npx -vが7.1以下の場合はpackage.jsonにbuild設定が自動で追加されないので、手動で追記する必要があります。

"scripts": {
    "build": "esbuild app/javascript/*.* --bundle --outdir=app/assets/builds"
}

サードパーティのESModuleを追加するには、yarnやnpmコマンドでプロジェクトルートにインストールしたライブラリをimportして使用します。

yarn add react react-dom

開発中には、./bin/devコマンドを使用することで、RailsサーバーとJSビルドウォッチャーの両方を同時に起動できます。cssbundling-railsを使用している場合、cssビルドウォッチャーも同時に起動します。事前にgemをインストールしておきましょう。(foremanがなければ自動でgemがインストールされます)

gem install foreman

esbuildの場合、デフォルトのターゲットはesnext(es6)です。変更したい場合は、package.jsonのbuildコマンドでtargetを指定できます。

webpackの場合はwebpack.config.json、rollupの場合はrollup.config.jsでビルド設定を行うことができます。

esbuildでのトランスパイルは、ターゲットがデフォルトでesnextのため、es6をターゲットにしておくとよさそうでした。なお、esbuildではes5向けのトランスパイルをサポートしていないため、IEをターゲットとする場合はwebpackを使うとよさそうです。

"build": "esbuild app/javascript/*.* --target=es6 --bundle --outdir=app/assets/builds",

CSSの読み込ませ方

使い慣れたSprocketsのアセットパイプラインを使用できます。Rails7では加えてバンドルの必要なTailwind CSSBootstrapBulmaPostCSS,Dart Sassなどを組み込むためにcssbundling-railsというGemを使用できます。cssbundling-railsでバンドルされたCSSはassets/buildsに出力され、アセットパイプラインを介して配信されます。

cssbundling-railsを使用するには、bundlerでcssbundling-railsをインストールし、コマンドを実行します。

./bin/rails css:install:[tailwind|bootstrap|bulma|postcss|sass]

注)npx -vが7.1以下の場合はpackage.jsonにbuild設定が自動で追加されないので、手動で追記する必要があります。

"scripts": {
    "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css"
}

開発中には、./bin/devコマンドを使用することで、RailsサーバーとCSSビルドウォッチャーの両方を同時に起動できます。jsbundling-railsを使用している場合、jsビルドウォッチャーも同時に起動します。事前にforeman gemをインストールしておきましょう。(foremanがなければ自動でgemがインストールされます)

tailwindcssを導入し@importを使用して別のcssファイルをバンドルするには、postcss-importyarn addします。詳細はこちら

カテゴリー
Uncategorized

Rails7 rails/importmap-railsの概要

Rails7からWebpack等のBundlerを使用しないアプリケーション開発手法が主軸となるようです。その中でESModuleをブラウザ上で直接フェッチするような形がとられています。ImportMapについて学びましょう!

ImportMapとは

ImportMapとは、import句でモジュールを取得する際の取得先URLを制御する仕組みです。webpackやrollupなどのバンドラーを使用せずにESModuleを読み込むことのできるブラウザ環境で使用します。

import moment from "moment";
import { partition } from "lodash";

バンドラーを使用しない環境では上記のような記載をした場合エラーをスローします。それを回避するにはURLを指定する必要があるでしょう。

import moment from "/node_modules/moment/src/moment.js";
import { partition } from "/node_modules/lodash-es/lodash.js";

そこでImportMapを提供することで、モジュール名を指定するだけでどこから取得すべきかをマッピングすることができます。

<script type="importmap">
{
  "imports": {
    "moment": "/node_modules/moment/src/moment.js",
    "lodash": "/node_modules/lodash-es/lodash.js"
  }
}
</script>

WICG/import-maps

Rails7におけるImportMapの利用

Rails7ではconfig/importmap.rbの設定ファイルを介してImportMapの設定を行います。

Rails.application.importmap do
end

ImportMapは<%= javascript_importmap_tags%>を介して<head>タグに挿入されます。

<%= javascript_importmap_tags%>

これにより、application.jsなどのjavascriptからモジュールを参照できるようになります。application.jsもまた、これを介してインポートされます。

ESModule非対応ブラウザの場合

Rails7ではES Module Shimsをインポートします。これによりESModule非対応ブラウザの場合でも動作が保証されます。

Rails7でのimportmapの使い方

インストールコマンドでimportmapを使う準備を行います。

$ ./bin/rails importmap:install

Add Importmap include tags in application layout
      insert  app/views/layouts/application.html.erb
Create application.js module as entrypoint
      create  app/javascript/application.js
Ensure JavaScript files are in the Sprocket manifest
      append  app/assets/config/manifest.js
Configure importmap paths in config/importmap.rb
      create  config/importmap.rb
Copying binstub
      create  bin/importmap

例えばvueを使いたい場合、importmap pinコマンドでマッピングします。自動的に2.6.14がマッピングされました。

$ ./bin/importmap pin vue
Pinning "vue" to https://ga.jspm.io/npm:vue@2.6.14/dist/vue.runtime.esm.js

しかし、自動でマッピングされるvueはブラウザでは動作しないものでしたので、browser esm互換のものへ手動で書き換えました。

pin "application"
pin "vue", to: "https://ga.jspm.io/npm:vue@2.6.14/dist/dist/vue.esm.browser.js"

実際に動かしてみる。

import Vue from 'vue'
var vm = new Vue({
  el: '#example',
  data: {
    domain: 'HAZM.JP'
  }
})
<div id="example">
  <h1>{{domain}}</h1>
</div>

出力結果

importmapがhead内に提供され、vueがマッピングされた場所からインポートされたこと、そして動作を確認できました。

まとめ

HTTP/2とES6がほとんどのブラウザで標準サポートされるようになった現代では、トランスパイルをせずともあらゆるJSを動作させることができました。importmapはその一端を担います。

カテゴリー
Uncategorized

別PCで動作するRailsアプリにlocalhost:3000でアクセスしたい

Webカメラとマイクを利用するアプリケーションの開発で複数の端末で動作検証をしたいと思いました。

しかし、WebカメラとマイクはlocalhostまたはSSL化されたサイトでしか動作できないというブラウザ仕様があるため、localhost:3000で別のPCで動作するRailsアプリケーションにアクセスできるようにする必要があります。

ローカルで起動したRailsアプリケーションにアクセスする分には、localhost:3000でアクセス可能ですが、/etc/hostsにドメインを定義する方法では、localhostでアクセスする事ができません。

では、どうすれば良いか。Nginxでプロキシすることで、それが可能です。

Railsアプリケーションを起動しているPC:Ubuntu
アクセスしたいPC:Mac

まず、接続元であるPCにnginxをインストールし、nginxの設定ファイルでserverを定義します。設定内容はシンプルで、server_nameがlocalhostである3000番ポートをリッスンするserverで、別PCのローカルIPへproxyするというものです。

server {
    listen       3000;
    server_name  localhost;

    proxy_set_header    X-Forwarded-Host $http_host;

    location / {
        proxy_pass http://192.168.1.12:3000;
    }
}

注意点として、RailsはCSRF対策の仕組みがデフォルトで有効なため、適宜必要なヘッダを設定してあげる必要があります。

# プロキシ先にHostを知らせます。この設定が無いと、originと一致しないためCSRFチェックがエラーになります。
proxy_set_header    X-Forwarded-Host $http_host;

以上!

カテゴリー
Uncategorized

Daily AWS

今後、エンジニアとして社会で活躍していくには、より広い視野を持ってシステム全体を俯瞰して見る必要があると考え、インフラ面にも手を広げていこうと考えています。

業務ではAWSを使っていて、部分的な改修・調整作業は稀に行う事があるものの、必要な情報を集めて、その場凌ぎの対応することが多いです。また、システムの全体図は頭に入っているけれどそれらがどのような設定で組み合わさっているかまでは把握できていない事があります。

インフラ面の知識を叩き込めていないが故に、その領域の提案ができない事がもどかしい、とも感じます。

ということで、AWSの各種サービスがどのようなソリューションを提供し、何ができるのかを1つづつ知って行こう、という目的を持って、Daily AWSというTwitterアカウントを作りました。

このアカウントの目的は、AWSの各種サービスで何が実現できるのかを知ることです。それによって、プログラム側だけで解決しようとするのではなく、インフラ側で解決するという新しい提案ができるようになることを最終目的としています。

ツイートする前にやっていることは、ドキュメントを読み込んで、インスタンスを立ててみることです。一通り触ってみると、頭に入ってきて自分なりに解釈できるからです。本当は一つ一つの設定の挙動を検証したり、というところまでできれば良いですが、時間的な制約が大きいのと、毎日継続することを第2目標としているため、一定の解釈を持ってツイートに流しています。

継続できるようにがんばります。笑

カテゴリー
Uncategorized

MySQL全文検索について調べたこと

業務案件で全文検索を使うことになった。とはいえ全文検索について全く知識がなかったのでここでインプットしておこうということで、いろいろ調べてみた。

全文検索とは

コンピュータにおいて、複数の文書から特定の文字列を検索すること。複数文書にまたがって文書に含まれる全文を対象とした検索。

  • grep型(逐次走査検索)

    事前に索引を作成せず、複数のファイルを順次走査していく。検索対象の増加によって検索速度が低下する。
  • 索引型(インデックス)

    事前に検索対象となる文書を走査し、索引データを準備しておく。これをインデクシングとよび、これにより生成されるファイルをインデックス(インデクス)と呼ぶ。

索引文字列の抽出手法

インデックスを作成するために検索対象の文書を解析・分割を行う。その手法として主に下記2手法がある。

  • 形態素解析

    英文は単語の間にスペースが入るため、これで区切れば索引データの作成は容易である。しかし日本語の場合それができないため形態素解析技術を用いて、文書の解析、単語分解を行い、それをもとにインデックスを作成する。形態素解析を行うためには解析用の辞書が必要であり、辞書に品質を受けやすく、検索漏れが生じる場合がある。
  • N-Gram

    「N-文字インデックス」「N-グラム法」なとどもいう。単語単位ではなく文字単位で分解し、後続のN-1文字を含めた状態で出現頻度を求める方法。N=1は「ユニグラム(uni-gram)」N=2は「バイグラム(bi-gram)」N=3は「トライグラム(tri-gram)」と呼ばれる。検索漏れが生じず、辞書の必要がない。しかし形態素解析と比べるとノイズの発生とインデックスサイズの肥大化という2つの欠点がある。
全文検索技術
↓
全文/文検/検索/索技/技術/術

MySQLにおける全文検索

MySQLでは、バージョン5.6.4 より全文検索をサポートしている。しかし、これは空白で単語が区切られるラテン語ベースの言語に対してのみ有効である。

これに対し、バージョン5.7.6 よりCJK(日韓中文字)で使用できるn-gramパーサ がサポートされました。(組み込みのサーバープラグイン。サーバーの起動時に自動的にロードされる。)

同タイミングで MeCab全文パーサプラグイン も提供されていて、形態素解析によるインデクシングも可能。(RDSだと使えないらしい?要調査)

MySQLサーバー設定

プロパティ説明備考
innodb_ft_min_token_size単語の最小長0~16 デフォルト3
innodb_ft_max_token_size単語の最大長10~84 デフォルト10
ft_min_word_lenmyIsamの場合はこれ(後で調べよう)
ft_max_word_lenmyIsamの場合はこれ(後で調べよう)
ngram_token_sizen-gramパーサを使用する際の分割文字数デフォルト2
innodb_ft_sort_pll_degreeインデックスを作成するスレッド数1~32 デフォルト2大きなテーブルにFULLTEXTインデックスを作成するときは、スレッドの数を増やすことを検討
innodb_ft_cache_size補助インデックステーブルごとのキャッシュ容量デフォルト 8000000bytes

InnnoDB全文検索の要素

InnoDB Full-Text Index Tables

InnoDB FULLTEXTインデックスを作成すると、FTS_から始まるインデックステーブルのセットが作成される。これらを転置インデックスという。

InnoDB Full-Text Index Cache

ドキュメントがインサートされると、FULLTEXT INDEXにもインサートが実行される。小さなドキュメントの場合でもインサートアクセスが実行されることになり、補助インデックステーブルへのアクセスが競合する場合があります。これを回避するために、最近インサートされた行の挿入はキャッシュされる。キャッシュ領域がいっぱいになると、ディスクに書き込まれまれる。これにより競合を防いでいる。Innodb_ft_cache_sizeはこのキャッシュ容量を設定できる。

InnoDB Full-Text Index Deletion Handling

FULLTEXT INDEX列をもつレコードを削除すると、補助インデックステーブルへの同時アクセスで競合が発生する場合があります。これを防ぐために削除されたドキュメントIDをFTS_*_DELETEDテーブルに記録する。クエリ結果を返す前に、FTS_*_DELETEDテーブルの情報を使用して削除されたドキュメントIDを除外する。補助インデックステーブルの値は保持されるため容量は減らない。補助インデックステーブルの値を削除するには、OPTIMIZE TABLE句を用いて実行できる。

一部引用元:
https://ja.wikipedia.org/wiki/%E5%85%A8%E6%96%87%E6%A4%9C%E7%B4%A2
https://dev.mysql.com/doc/refman/5.7/en/fulltext-search.html

カテゴリー
Uncategorized

IFTTTでWebサービスのイベントをLINEグループに通知できるようにした

友人と作っているWebプロダクトがあります。このサービスは特定のジャンルの人同士の友達探しをサポートするサービスであり、クローズドなやりとりが多く、サービスが盛り上がっているのかどうか?どれくらいの頻度でユーザ登録があるか?といったデータが把握しにくいという状況でした。1ヶ月前に公開したばかりのサービスでもあり管理画面を実装するほどでもないと思ったので、より簡単な方法を模索しました。友人との連絡はLINEグループを使用しています。そのため今回はLINEグループに通知をする方針としました。

個人開発は、いかに工数をかけずに実装するか?という観点を重要視しています。そこで記憶の片隅にあったIFTTT(イフト)を活用することにしました。

幸いなことに、IFTTTはLINE Notifyというサービスと簡単に連携することができます。LINE Notifyは様々なサービスからの通知を受信して、端末にメッセージ等を送信してくれるサービスです。このサービスの公式アカウントをLINEグループに招待することで、LINEグループへメッセージ通知を流し込むことが可能です。

さて、Webアプリケーションでユーザ通知が行われた場合、どのようにIFTTTに通知するでしょうか。最も簡単な方法は、Webhookでしょう。よって構成は下記の通りになります。

早速始めましょう。IFTTT

IFTTTでレシピを作成します。

IFTTTは「もし何かがあったら」「その時何をする」をセットで設定します。今回は「Webhookを受信したら」「LINE Notifyで通知する」という設定を行います。

If Thisを選択して、Webhookを設定します。

次に、Then Thatをクリックし、LINEを選択します。

初回はLINEアカウント連携に飛ばされると思うので、連携してください。Send messageのRecipientで、送信先のグループ名を選択します。ここで、「1:1でLINE Notifyから通知を受け取る」を選択すれば、自分だけに届くはずです。

Value1,2,3はプレースホルダです。これらの値はWebhookリクエスト毎に自由に設定でき、LINEにはその値で置き換えられたメッセージが送信されます。

これで設定完了です。

次に、WebアプリケーションからIFTTTにWebhookリクエストを投げる必要があります。事前に、エンドポイントのURLを取得しましょう。右上アイコン>My services>Webhooks>右上 Documents を選択しましょう。

WebアプリケーションからWebhookリクエストを送信する部分を実装します。

# LINE通知
# value1 ユーザ名
# value2 登録日時
# value3 URL
begin
  uri = URI.parse(IFTTTから取得したエンドポイント)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  params = { value1: 値1, value2: 値2, value3: 値3}
  headers = { "Content-Type" => "application/json" }
  response = http.post(uri.path, params.to_json, headers)
  ap response
rescue => e
  Raven.capture_exception(e)
end

最後に、お手持ちのスマホのLINEでLINE Notifyを友達追加したあと、グループに招待しましょう。

喜んでもらえて、エンジニア冥利に尽きますね!

まとめ

IFTTTを使うことで、Webhookを契機にLINE通知を行う仕組みを簡単に実現することができました。

IFTTTはLINEの他、Slackなど様々なサービスと連携することができます。活用方法によっては実装なしに便利な自動化ができるようになることでしょう。

個人的には、IFTTTを使った自動化を体験できたのは知見が広がったという意味でよかったかなと思います。それでは。

カテゴリー
Uncategorized

FlutterのCupertinoTimerPickerを日本語化する

何も考えずにCupertinoTimePickerを追加すると、端末の言語設定に関わらず、英語表記になってしまいます。

Widgetのプロパティでどうにかできると思いきやそのような機能は提供されていませんでした。いろいろ調べた結果、Flutterアプリケーションの多言語化対応が必要でした。

まず、Flutter公式のflutter_localizationsプラグインをインストールします。公式プラグインは、pub.devで提供されるのではなく、Flutter内部に内包されているようです。https://github.com/flutter/flutter/tree/master/packages/flutter_localizations

pubspecにプラグインを追記します。

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

main.dartでMaterialAppを使用しているので、ここでlocalizationsDelegatesとsupportedLocalesプロパティを追記します。

return MaterialApp(
  localizationsDelegates: [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: [
    Locale('English'),
    Locale('ja')
  ],
  title: 'xxx',
  home: HomeScreen(title: "xxx"),
  //...
);

最後に、iOSアプリで使用するためにInfo.plistに対応言語を追記します。XCodeでInfo.plistを開きます。

  1. Information Property ListLocalizationsを追加
  2. ValueにJapaneseEnglishを追加

結果、このようになりました!(結構苦労しました…)