Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Railsで海外9ヵ国にサービス展開している話 / Rails i18n
Search
rince
February 26, 2021
Programming
3
1.7k
Railsで海外9ヵ国にサービス展開している話 / Rails i18n
2021/2/26 @銀座Rails#30
Railsでのi18nの進め方と少人数で海外展開する上での設計・実装・テスト・デプロイの工夫についてお話ししました。
rince
February 26, 2021
Tweet
Share
More Decks by rince
See All by rince
あらゆる商品を扱う商品データベースを再設計した話 / product db re-architecture
rince
12
6k
Elasticsearch入門 〜前編〜
rince
0
260
ActiveSupport::Concern で学ぶRuby
rince
1
300
Railsを6年間やってきたぼくが最近Railsでハマったこと
rince
3
560
プロジェクトをまたいだIssue管理
rince
0
2.2k
そうだ Rack 作ろう。
rince
2
92
Lean Startup
rince
0
180
Yahoo!主催のOpenHackDayJapanに参加してJAXA賞をいただきました
rince
1
130
Other Decks in Programming
See All in Programming
Amazon S3 NYJavaSIG 2024-12-12
sullis
0
100
アクターシステムに頼らずEvent Sourcingする方法について
j5ik2o
4
280
SymfonyCon Vienna 2025: Twig, still relevant in 2025?
fabpot
3
1.2k
Mermaid x AST x 生成AI = コードとドキュメントの完全同期への道
shibuyamizuho
0
160
責務を分離するための例外設計 - PHPカンファレンス 2024
kajitack
6
1.1k
ドメインイベント増えすぎ問題
h0r15h0
2
340
CQRS+ES の力を使って効果を感じる / Feel the effects of using the power of CQRS+ES
seike460
PRO
0
130
快速入門可觀測性
blueswen
0
370
rails statsで大解剖 🔍 “B/43流” のRailsの育て方を歴史とともに振り返ります
shoheimitani
2
940
42 best practices for Symfony, a decade later
tucksaun
1
180
Jakarta EE meets AI
ivargrimstad
0
250
今年一番支援させていただいたのは認証系サービスでした
satoshi256kbyte
1
260
Featured
See All Featured
Thoughts on Productivity
jonyablonski
67
4.4k
Raft: Consensus for Rubyists
vanstee
137
6.7k
How GitHub (no longer) Works
holman
311
140k
The Invisible Side of Design
smashingmag
298
50k
Building Flexible Design Systems
yeseniaperezcruz
327
38k
Visualization
eitanlees
146
15k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Building Adaptive Systems
keathley
38
2.3k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
1.2k
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.4k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Transcript
Railsで海外9ヵ国に サービス展開している話 2021/2/26 @銀座Rails rince (@kazumax1218)
rince (@kazumax1218) • 2011- カカクコム(食べログ→キナリノ) • 2018- メルカリ(ソウゾウ→メルペイ) • 2020-
mybest 旅とキャンプとサウナが好き。 自己紹介 0. はじめに
• Railsのi18nの基本をお伝えして、海外展開の開発面でのハードル がそこまで高くないことを知っていただく • 少人数での海外展開の工夫をお伝えして、少人数でも海外展開でき るということを知っていただく • 日本から海外にチャレンジするプロダクトが増えたらいいな😊 本発表のゴール 0.
はじめに
本日のアジェンダ 1. Railsのi18nの基本 2. どんなサービスを海外展開してるのか 3. 少人数で開発/運用するための工夫 ◦ 設計・実装 ◦
テスト・デプロイ 4. まとめ 0. はじめに
1. Railsのi18nの基本
i18n = internationalization • 国際化・多言語化 • 先頭のiと末尾のnとの間に18文字あるのでこのように略される i18nとは? 1. Railsのi18nの基本
国際化 • 使われるすべての文言やロケール固有の要素 (日付や通貨フォー マットなど) の抽象化 ローカライズ • 具体的な翻訳方法を提供したり、そのためのフォーマットを提供し たりすること
国際化とローカライズ 1. Railsのi18nの基本
1. ロケールの設定 2. コード中の文言を抽象化する 3. 訳文を与えて翻訳する 4. 日時や金額をローカライズする i18nの進め方 1.
Railsのi18nの基本
• デフォルトのロケールを変更する場合 config/application.rb • パラメータやドメインに応じてロケールを変更する場合 application_controller.rb 1. ロケールの設定 config.i18n.default_locale =
:en around_action :switch_locale def switch_locale(&action) locale = extract_locale || I18n.default_locale # paramsやドメインからlocaleを抜き出す I18n.with_locale(locale, &action) end ※ I18n.locale= を使うと同じスレッドで処理される以後のリクエストも影響を受けてしまう 1. Railsのi18nの基本
I18n.t (translate) メソッドでコード中の文言を置き換える • 各訳文の意味を適切に表すキーを与える 2. コード中の文言を抽象化する <p>Hello!</p> <p>Hello, itadori!</p>
<p><%= t :hello %></p> <p><%= t :greeting, name: 'itadori' %></p> 1. Railsのi18nの基本 動的な値は引数で渡す
各国の辞書ファイルに訳文を追加する 3. 訳文を与えて翻訳する 1. Railsのi18nの基本 # config/locales/en.yml en: hello: 'Hello!'
greeting: 'Hello, %{name}!' # config/locales/pt-BR.yml pt-BR: hello: 'Olá!' greeting: 'Olá, %{name}!' %{} で変数を式展開できる
I18n.l (localize) メソッドやヘルパーメソッドで日時や金額を現地の フォーマットに変換する 4. 日時や金額をローカライズする 1. Railsのi18nの基本 ※ https://github.com/svenfuchs/rails-i18n
にほとんどの言語の翻訳ファイルがある <h3><%= locale %></h3> <p><%= l Date.today %></p> <p><%= number_to_currency 1000 %></p>
簡単😊
Viewに大量の文章が含まれている場合は言語別にテンプレートを分ける ことも可能 • ex) プライバシーポリシー, 利用規約など • ビューファイルの拡張子の前にロケールを付ける 補足1: ローカライズ済みビューテンプレート
1. Railsのi18nの基本 app/views/pages ├── privacy_policy.en.html.slim ├── privacy_policy.pt-BR.html.slim ├── ... └── privacy_policy.vi.html.slim
Viewファイルのパスに沿った階層で訳文を定義すると、対応するView 内で「. +キー名」で訳文を参照できる • 同じキー名がいろんなページで使われる場合に便利 補足2: 訳文の遅延探索 1. Railsのi18nの基本 en:
users: index: title: 'Title A' show: title: 'Title B' app/views/users/index.html.erb <%= t '.title' %> <%# => "Title A" %> <%= t '.title' %> <%# => "Title B" %> app/views/users/show.html.erb config/locales/en.yml
2. どんなサービスを海外展開してるのか
徹底した自社検証と専門家の声をもとに 本当に良いモノを紹介して、 あなたの”選ぶ”をお手伝いする おすすめ情報サービス サービス内容 https://my-best.com 3,300万人 月間訪問者数(MAU)
商品を自社で実際に購入し、 比較・検証してデータベース化 各々に最適な商品をランキングで紹介 ①比較コンテンツ 専門家やインフルエンサーが 自身の愛用品の中からおすすめ ②アイテムリスト
世界11ヵ国にサービス展開 アメリカ ブラジル イギリス 中国 日本 タイ ベトナム インドネシア 台湾
展開国数 11 ヵ国 インド フィリピン 2. どんなサービスを海外展開してるのか ブラジル・インドネシア・タイ・台湾では既に月間数百万PVのアクセス
各国に合わせたコンテンツを作成 2. どんなサービスを海外展開してるのか Brazil (https://mybest-brazil.com.br) Thailand (https://my-best.in.th) 各国の編集者・ライターがいて、各国に合わせたコンテンツを作成している
3. 少人数で開発/運用するための工夫
• フルタイムのエンジニアが4人しかおらず、国内でのPMFが最優先の ため、海外に割けるリソースは1名以下 (We are hiring!) • 国内版は機能開発が頻繁に行われるため、国内版とはコードを分ける • 中国は各種SaaSが使えないため、中国以外の海外9ヵ国に対応する
(中国はWordPressで運用) • 機能は国によらず同じだが、コンテンツは各国で異なる • 今後まだまだ展開国は増える可能性がある 前提 3. 少人数で開発/運用するための工夫
• できるだけ開発/運用コストを抑える ◦ 1名のリソースで開発/運用が回るか? • 今後展開国が増えても破綻しない仕組みにする ◦ 20ヵ国になっても開発/運用が回るか? 基本方針 3.
少人数で開発/運用するための工夫
3-1 設計・実装 👈 3-2 テスト・デプロイ
• 開発メンバーが少なく、できるだけ運用コストを減らすため • 現状では国ごとの機能のローカライズはそこまで必要ないため 1リポジトリ複数DBで運用 選択肢 説明 向くケース 複数リポジトリ 複数DB
国ごとにコードもDBも分ける ・開発リソースがある / 展開国が少ない ・各国で機能のローカライズが必要 1リポジトリ 複数DB 各国コードは共通で、国ごとに DBを分ける ・開発リソースがない / 展開国が多い ・各国で機能のローカライズが少ない 1リポジトリ 1DB 各国コードもDBも共通で、カラ ムやテーブルでデータを分ける ・データは同じで言語が異なる ・翻訳サイト 3. 少人数で開発/運用するための工夫(設計・実装)
• 開発メンバーが少なく、できるだけ運用コストを減らすため • 現状では国ごとの機能のローカライズはそこまで必要ないため 1リポジトリ複数DBで運用 選択肢 説明 向くケース 複数リポジトリ 複数DB
国ごとにコードもDBも分ける ・開発リソースがある / 展開国が少ない ・各国で機能のローカライズが必要 1リポジトリ 複数DB 各国コードは共通で、国ごとに DBを分ける ・開発リソースがない / 展開国が多い ・各国で機能のローカライズが少ない 1リポジトリ 1DB 各国コードもDBも共通で、カラ ムやテーブルでデータを分ける ・データは同じで言語が異なる ・翻訳サイト 3. 少人数で開発/運用するための工夫(設計・実装) どの国かを環境変数で持ち、database.ymlのdatabaseやhostの値を切り替える 👈
保守性・可読性を高めるためになるべく国ごとの分岐を入れない • ex) タイムゾーン, 機能のON/OFF, GAのトラッキングIDなどの各種設定 コード内に国ごとの分岐を入れない 3. 少人数で開発/運用するための工夫(設計・実装) config.time_zone
= case ENV['OVS_CODE'] when 'br' 'Brasilia' when 'id' 'Jakarta' ... when 'vn' 'Hanoi' end
https://github.com/rubyconfig/config を使って定数を出し分ける コード内に国ごとの分岐を入れない 3. 少人数で開発/運用するための工夫(設計・実装) # config/settings/br/settings.yml time_zone: 'Brasilia' #
config/settings/id/settings.yml time_zone: 'Jakarta' # config/application.rb Settings.add_source!("#{Rails.root}/config/settings/#{ENV['OVS_CODE']}/settings.yml") Settings.add_source!("#{Rails.root}/config/settings/#{ENV['OVS_CODE']}/#{Rails.env}.yml") Settings.reload! config.time_zone = Settings.time_zone
管理画面のアカウント管理のコストを削減するためにAWSのCognitoを用い てアカウントを一元管理し、グループでアクセス権限を分ける Cognitoでアカウントを一元管理 3. 少人数で開発/運用するための工夫(設計・実装)
3-1 設計・実装 3-2 テスト・デプロイ 👈
GitHub Actionsのstrategy.matrixを用いて各国でRSpecを並列実行 各国並列でテストを行う jobs: rspec: ... strategy: fail-fast: false matrix:
ovs_code: ['br', 'id', 'in', 'ph', 'th', 'tw', 'uk', 'us', 'vn'] env: ... OVS_CODE: ${{ matrix.ovs_code }} 3. 少人数で開発/運用するための工夫(テスト・デプロイ)
運用コストを最小限にするためのインフラ 3. 少人数で開発/運用するための工夫(テスト・デプロイ) ・・・ Indonesia (ap-southeast-1) Brazil (sa-east-1) AWSのFargateを用いて、トラフィックや展開国が増えてもスケールする 仕組みを構築
Slackから全世界に一括デプロイできるようにして、デプロイの手間を削減 ChatOpsで全世界に一括デプロイ 3. 少人数で開発/運用するための工夫(テスト・デプロイ)
国とPR番号を指定して、レビュー環境にデプロイ • 本番相当のデータで各国の動作確認が可能 • 各国の開発用データの準備の手間を削減 リリース前の各国での動作確認 3. 少人数で開発/運用するための工夫(テスト・デプロイ)
大きな問題もなく、 海外9ヵ国に展開できています😊 (小さな問題はいろいろとあったので、その話もまたどこかでw)
4. まとめ
• Railsのi18nのサポートのおかげで、開発面においては海外展開の ハードルはそこまで高くない • 少人数のリソースでも開発/運用を工夫することで、複数ヵ国に海外 展開可能 • 日本から海外にチャレンジするプロダクトを増やしていきましょう 💪 まとめ
4. まとめ
ご清聴ありがとうございました!