8
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

kurogoma939のひとりアドベントカレンダーAdvent Calendar 2024

Day 5

【Flutter】モノレポでslangを用いる場合の注意点

Last updated at Posted at 2024-12-04

モノレポ構成とは

例えばフィットネス系のトレーナーアプリ・ユーザーアプリを同時に開発する場合、どのようにアプリを管理しますか?また、どのようにアプリを配布しますか?

  • 1つのアプリとして、トレーナーログイン・ユーザーログインのページを用意し、とルートで切り分けていく
  • リポジトリを完全に分けて別物として扱う

しかし、上記の方法は以下のようなメリデメを含むと思います。

1つのアプリとして、トレーナーログイン・ユーザーログインのページを用意し、とルートで切り分けていく

メリット デメリット
1つのリポジトリで一括管理ができる
ロジックを共通化させやすい
リポジトリ内のメインディレクトリが
肥大化していく(Flutterで言うlib)

リポジトリを完全に分けて別物として扱う

メリット デメリット
固有のロジックの切り分けが容易である。
全く違うデザインにしても問題ない
共通ロジック・設定があった場合二重で実装することになる

そのため、特にデメリットの方が負担に感じるような場合、モノレポ構造のアプリ開発を推奨します。

モノレポ構造って何?と言う方はAltive社のflutter_app_templateが参考になります。

リポジトリの一番上の階層にpackagesディレクトリを容易し、その中に以下のようにそれぞれ管理したいグループ単位で配置します。

スクリーンショット 2024-12-03 9.13.42.png

例えばflutter_appからthemeのものを呼び出したい場合、直接ディレクトリを参照するのではなくpackageとして取り込んで利用します。

このモノレポ構成は以下のメリデメを含みます

メリット デメリット
各パッケージの責務が明確になる。
共通要素の実装がスムーズになる
各種モノレポ用の設定をしなくてはならない

多言語化対応の話

アプリ開発の際にはTextクラスにセットする文字列をハードコーディングしない目的や、複数言語に対応したアプリケーションとする場合localizationパッケージを用いると思います。

多言語化パッケージの紹介

多言語化パッケージはいくつかありますが、代表して以下のようなものがあります

Flutter Gems

代表パッケージ

slangの紹介

今回はその中でSlangの紹介をします。

基本的な使い方は以下の通りです。

packageのインストール

build.yamlの実装

build.yaml
targets:
  $default:
    builders:
      slang_build_runner:
        options:
          base_locale: ja
          input_directory: lib/i18n # 多言語ファイルを設置する場所
          input_file_pattern: .yaml # フォーマット形式
          output_directory: lib/gen # 自動生成後の出力ディレクトリ
          timestamp: false # 自動生成の度にファイルに記録される
          statistics: false

yamlの記載

strings.i18n.yaml
app:
  title: "APP NAME"

アプリへの設定

MyApp()を以下のようにラップしてください

TranslationProvider(
    child: const MyApp()
),

使い方

自動生成のため、build_runnerコマンドを走らせると以下のように利用できます。

context.t.app.title // APP NAME

モノレポ特有の複数パッケージでまたがる場合の問題

ここでタイトルの問題ですが、例えば共通パーツ用パッケージとアプリ本体のパッケージそれぞれでslangを用いる場合に注意が必要です。
slangを用いる際にはTranslationProviderでラップする必要があるので、別パッケージのslangを用いたい場合もそのクラスのTranslationProviderでさらにラップする必要があります。
ただその場合クラスの衝突が発生します。

回避方法

以下のissueのようにasを用いるなどして表記を分けてあげれば良いだけです。

import 'package:package1/i18n/translations.g.dart' as package1;
import 'package:package2/i18n/translations.g.dart' as package2;

void main() {
  runApp(
    package1.TranslationProvider(
      child: package2.TranslationProvider(
        child: const MyApp(),
      ),
    ),
  );
}

しかし、以下のような書き方もできます。importの際にはasだけではなく個別クラスだけを取得するshow、逆に個別クラスは排除するhideがあるのでそれを用います。

import 'package:themes/themes.dart' as theme show TranslationProvider;
import 'package:themes/themes.dart' hide TranslationProvider;

// ...

TranslationProvider(
    child: theme.TranslationProvider(
        child: const MyApp(),
    ),
),

結局やっていることはissueと大差ないのですが、せっかくならこう言う書き方もありますよと言う紹介でした。
ちなみにSlangはyaml形式でワードの定義ができる点もおすすめです。

8
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?