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
11
5.9k
Elasticsearch入門 〜前編〜
rince
0
250
ActiveSupport::Concern で学ぶRuby
rince
1
300
Railsを6年間やってきたぼくが最近Railsでハマったこと
rince
3
550
プロジェクトをまたいだIssue管理
rince
0
2.2k
そうだ Rack 作ろう。
rince
2
90
Lean Startup
rince
0
170
Yahoo!主催のOpenHackDayJapanに参加してJAXA賞をいただきました
rince
1
130
Other Decks in Programming
See All in Programming
型付き API リクエストを実現するいくつかの手法とその選択 / Typed API Request
euxn23
8
2.2k
Why Jakarta EE Matters to Spring - and Vice Versa
ivargrimstad
0
1.1k
Duckdb-Wasmでローカルダッシュボードを作ってみた
nkforwork
0
130
as(型アサーション)を書く前にできること
marokanatani
10
2.7k
Creating a Free Video Ad Network on the Edge
mizoguchicoji
0
120
聞き手から登壇者へ: RubyKaigi2024 LTでの初挑戦が 教えてくれた、可能性の星
mikik0
1
130
よくできたテンプレート言語として TypeScript + JSX を利用する試み / Using TypeScript + JSX outside of Web Frontend #TSKaigiKansai
izumin5210
6
1.7k
AWS Lambdaから始まった Serverlessの「熱」とキャリアパス / It started with AWS Lambda Serverless “fever” and career path
seike460
PRO
1
260
TypeScript Graph でコードレビューの心理的障壁を乗り越える
ysk8hori
2
1.1k
WebフロントエンドにおけるGraphQL(あるいはバックエンドのAPI)との向き合い方 / #241106_plk_frontend
izumin5210
4
1.4k
AI時代におけるSRE、 あるいはエンジニアの生存戦略
pyama86
6
1.2k
광고 소재 심사 과정에 AI를 도입하여 광고 서비스 생산성 향상시키기
kakao
PRO
0
170
Featured
See All Featured
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
The World Runs on Bad Software
bkeepers
PRO
65
11k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
93
16k
Teambox: Starting and Learning
jrom
133
8.8k
Happy Clients
brianwarren
98
6.7k
Thoughts on Productivity
jonyablonski
67
4.3k
KATA
mclloyd
29
14k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
28
8.2k
Art, The Web, and Tiny UX
lynnandtonic
297
20k
Code Reviewing Like a Champion
maltzj
520
39k
Building Applications with DynamoDB
mza
90
6.1k
Statistics for Hackers
jakevdp
796
220k
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. まとめ
ご清聴ありがとうございました!