RORK LABEN
BUILD — Rork Max はクラウド上の実機 Mac に Xcode と iOS SDK を載せ、SwiftUI を書き、ビルドし、エラーを読んで直す反復を回します。コードを吐いて終わりではない点が生成物の質に効いていますNATIVE — 生成されるのは React Native ではなく純粋な Swift / SwiftUI です。AR や Metal、ウィジェットなど React Native からは届かない機能に手が届くことが、他ビルダーとの実質的な差になりますPLATFORMS — 対応は iPhone・iPad・Apple Watch・Apple TV・Vision Pro に加えて iMessage まで含みます。ウォッチや拡張から入る設計を試すのに向いていますCOMPANION — Rork Companion により、有料の Apple Developer アカウントなしで生成したアプリを実機の iPhone で確認できます。最初の一本を試す段階の障壁が一段下がりましたPRICING — 無料で開始でき有料プランは月額25ドルから、Rork Max は月額200ドルの Max プランです。回収できる本数と規模を先に見積もっておく価値がありますDEADLINE — Google Play は2026年8月31日以降、新規アプリと更新の双方に対象 API レベル36 以上を要求します。残り10日で、生成物の targetSdkVersion は自分で確認が必要ですBUILD — Rork Max はクラウド上の実機 Mac に Xcode と iOS SDK を載せ、SwiftUI を書き、ビルドし、エラーを読んで直す反復を回します。コードを吐いて終わりではない点が生成物の質に効いていますNATIVE — 生成されるのは React Native ではなく純粋な Swift / SwiftUI です。AR や Metal、ウィジェットなど React Native からは届かない機能に手が届くことが、他ビルダーとの実質的な差になりますPLATFORMS — 対応は iPhone・iPad・Apple Watch・Apple TV・Vision Pro に加えて iMessage まで含みます。ウォッチや拡張から入る設計を試すのに向いていますCOMPANION — Rork Companion により、有料の Apple Developer アカウントなしで生成したアプリを実機の iPhone で確認できます。最初の一本を試す段階の障壁が一段下がりましたPRICING — 無料で開始でき有料プランは月額25ドルから、Rork Max は月額200ドルの Max プランです。回収できる本数と規模を先に見積もっておく価値がありますDEADLINE — Google Play は2026年8月31日以降、新規アプリと更新の双方に対象 API レベル36 以上を要求します。残り10日で、生成物の targetSdkVersion は自分で確認が必要です
記事一覧/アプリ開発
アプリ開発/2026-06-27上級

アラビア語に切り替えても画面が鏡像化されない — Rork(Expo)アプリのRTL対応と再起動の罠

Rork が生成した Expo アプリにアラビア語を足したのに、画面が左右反転せず戻るボタンが逆側に残る——その原因は I18nManager.forceRTL が再起動を要求することにあります。expo-localization での方向判定、Updates.reloadAsync での確実な反映、marginStart への置き換え、矢印だけの鏡像化まで、動くコードで RTL 対応の本番設計を示します。

Rork539React Native227Expo175多言語対応3RTL

プレミアム記事

アラビア語を話す利用者から「戻るボタンが画面の左にあって押しにくい」という連絡をもらったのは、壁紙アプリにアラビア語のメタデータを足して数日後のことでした。文言は確かにアラビア語になっています。けれどレイアウトはそのまま左から右のままで、本来は右上にあるべき戻る矢印が左上に居座っていました。文言だけ翻訳して RTL(右から左)のレイアウト反転を忘れていたのです。

やっかいなのは、コードで I18nManager.forceRTL(true) を呼んでもその場では何も変わらないことでした。ログには反映済みと出るのに、画面は左から右のまま。私自身、最初はコードが間違っているのかと小一時間コードを見つめていました。原因はもっと単純で、React Native の RTL はネイティブ側のレイアウトエンジンに渡るため、アプリを作り直さない限り切り替わらないという仕様だったのです。

ここでは Rork が出力する Expo アプリを題材に、その再起動の壁をどう越えるか、そして「文言は翻訳できたのにレイアウトだけ壊れる」を仕組みで防ぐ設計を、個人開発で実際に踏んだ落とし穴とあわせて共有します。

鏡像化は自動、でも有効化は手動

最初に押さえておきたいのは、RTL が有効になりさえすれば flexDirection: 'row' のような並びは React Native が自動で左右反転してくれる、という点です。手で全画面を組み替える必要はありません。問題は「有効にする」操作のほうにあります。

RTL の有効・無効はネイティブのビュー階層に焼き込まれる設定で、JavaScript 実行中に動的に切り替えても、既に組み上がった画面には適用されません。I18nManager には次の2つがあります。

API役割反映タイミング
I18nManager.allowRTL(bool)RTL を許可するかどうかの土台。これが false だと forceRTL も効かない次回起動時
I18nManager.forceRTL(bool)実際に RTL レイアウトを強制する次回起動時(=アプリ再構築が必要)

どちらも「次回起動時」というのが肝です。つまり呼んだ直後にユーザーへ見せたいなら、こちらから作り直しを起こす必要があります。Expo なら expo-updatesUpdates.reloadAsync() が一番確実です。

端末の言語方向を読んで、初回起動の向きを決める

まず、端末がアラビア語やヘブライ語のような RTL 言語に設定されているかを判定します。expo-localizationgetLocales() は各ロケールに textDirection を返すので、これを使うのが正確です。言語コードを自前で RTL 判定するより、OS の判断に乗るほうが取りこぼしがありません。

// lib/rtl.ts
import * as Localization from 'expo-localization';
import { I18nManager } from 'react-native';
import * as Updates from 'expo-updates';
 
// 端末の最優先ロケールが RTL かどうか
export function deviceWantsRTL(): boolean {
  const [primary] = Localization.getLocales();
  return primary?.textDirection === 'rtl';
}
 
// アプリ起動時に一度だけ呼ぶ。向きが食い違っていたら作り直す
export async function syncLayoutDirection(): Promise<void> {
  const wantsRTL = deviceWantsRTL();
 
  // 既に望む向きなら何もしない(無限リロード防止)
  if (I18nManager.isRTL === wantsRTL) return;
 
  I18nManager.allowRTL(wantsRTL);
  I18nManager.forceRTL(wantsRTL);
 
  // 開発中の Fast Refresh では reload が効かないことがあるためガード
  if (!__DEV__) {
    await Updates.reloadAsync();
  }
}

if (I18nManager.isRTL === wantsRTL) return; のガードが地味ですが重要です。これを忘れると、起動するたびに「向きが違う→reload→また起動→…」と無限ループに入ります。私は最初このガードを書かず、シミュレータが延々と再起動を繰り返すのを眺めることになりました。

呼び出しはルートで、UI を描く前に行います。

// app/_layout.tsx(Expo Router)
import { useEffect, useState } from 'react';
import { syncLayoutDirection } from '../lib/rtl';
 
export default function RootLayout() {
  const [ready, setReady] = useState(false);
 
  useEffect(() => {
    syncLayoutDirection().finally(() => setReady(true));
  }, []);
 
  if (!ready) return null; // reload が走る場合はここで止まる
  return <Stack /* ... */ />;
}

app.json 側でも RTL を許可しておきます。Expo の場合、ビルド時に allowRTL を入れておくと初回から安定します。

{
  "expo": {
    "extra": { "supportsRTL": true },
    "ios": { "infoPlist": { "CFBundleAllowMixedLocalizations": true } }
  }
}

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
アラビア語へ切り替えても鏡像化されない原因が I18nManager.forceRTL の再起動要件にあると理解し、Updates.reloadAsync で確実に反映させる実装を手に入れられる
marginLeft/right や position:left の直書きを marginStart/end と logical property に置き換え、全画面ビューアの閉じるボタンが逆側に出る事故を防げる
戻る矢印やチェブロンだけを transform で鏡像化し、壁紙サムネイル本体は反転させない『UIだけRTL化』の線引きを実装できる
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

アプリ開発2026-08-16
グラフが壊れて見えるのは、データが多いときではなく最初の数日でした
記録アプリの折れ線グラフが、データの少ない最初の数日だけ線が消える。原因はY軸の幅が0になり座標がNaNになることでした。実測した挙動と、描画前に置く小さな正規化層を紹介します。
アプリ開発2026-08-06
壁紙の上の文字が読めるかを、端末ではなく取り込み時に決める — 判定指標を4つ測り比べた記録
壁紙の上に置くステータスバーや見出しが読めるかを、端末での画像解析ではなく取り込み時のメタデータで決める設計です。240枚のコーパスで判定指標を4つ実測し、縮小画像での判定が何と一致するのかまで記録しました。
アプリ開発2026-07-14
壁紙を長押しして、プレビューと保存メニューを出す — Rork の Expo アプリで context menu を組む
壁紙ギャラリーのカードを長押ししても何も起きない。iOS利用者はプレビュー付きのメニューを期待します。Pressableだけでは届かない理由から、zeegoでのネイティブcontext menu実装、スクロールとの競合解消、保存・共有アクション、Android向けの自前フォールバックまで、動くコードでまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →