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
実行場所を意識させない i18n API を作った話
Search
ANDPAD inc
August 21, 2026
Programming
24
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
実行場所を意識させない i18n API を作った話
柿森 隆生
2026 年 8 月 21 日
React Tokyo ミートアップ #19
ANDPAD inc
August 21, 2026
More Decks by ANDPAD inc
See All by ANDPAD inc
Go 1.27 における memory allocation の高速化
andpad
0
270
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
160
OS アップデート対応の取り組み方がもっと共有されてほしい
andpad
0
130
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
490
ANDPAD Ruby sponsor session in RubyKaigi 2026
andpad
0
250
AWS WAFの運用を地道に改善し、自社で運用可能にするプラクティス
andpad
2
1.2k
アプリから 360 度カメラ「RICOH THETA」に接続して写真を撮影する
andpad
0
79
アンドパッドが提供する Drinks and Local Meals と Drinkup を大公開
andpad
0
140
建設DXを支えるANDPAD: 2025年のセキュリティの取り組みと卒業したいセキュリティ
andpad
0
570
Other Decks in Programming
See All in Programming
Android CLI
fornewid
0
230
Cloudflare is Agents
chimame
0
170
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
150
レビュー履歴をAIに食わせて、 Compose移行を加速するs
shihochan
0
150
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
240
20260722_microCMSで考える、AI時代のコンテンツ運用設計
yosh1
0
440
S3 を使うアプリケーションをローカル完結で動かすことに全力を注いでみた / Running S3 Apps Offline
contour_gara
0
550
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
600
Flow は今どうなっているか
mizdra
PRO
0
650
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
1.8k
AIと壁打ちしながら進めるコスト管理
fufuhu
0
380
複数の Claude Code が"放置"されてしまう問題をCLI ダッシュボードを自作して解決した話
sumihiro3
1
710
Featured
See All Featured
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
210
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
120
120k
Designing for Timeless Needs
cassininazir
1
450
Site-Speed That Sticks
csswizardry
13
1.5k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
800
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
410
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
500
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6.1k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Technical Leadership for Architectural Decision Making
baasie
3
510
Transcript
実行場所を意識させないi18n APIを作った話 colocaleというOSSを作りました © 2026 ANDPAD All Rights Reserved. Confidential
自己紹介 | Speaker 柿森 隆生 GitHub | Urotea ポジション: TechLead(プロダクトのためになんでもやる人)
最近よく書いている言語: skills(言語なのか?) 趣味: LoL / OW © 2026 ANDPAD All Rights Reserved. Confidential 2
ただ表示する言葉を変えるだけのはずだった どの言語を表示するかの分岐はスコープ外とさせてください。 今回の話は言語ごとにラベルを入れ替えるだけの小さな部品の話です。 ラベルを日本語と英語で切り替えたい 該当のコンポーネントはサーバーコンポーネントからもクライアントからも使いたい next-intlのようなi18nライブラリは、サーバーとクライアントでAPIが分かれているので、コンポーネントが 動く場所を意識せざるを得ない さらにプラグインの追加やProviderの追加も必要になる ラベルを差し替えるだけなのに、なぜか設計の話になった。 ©
2026 ANDPAD All Rights Reserved. Confidential 3
動く場所を先に決めさせられる | next-intl の場合 'use client'; // ← これでサーバーから使えなくなる import
{ useTranslations } from 'next-intl'; export const ReportListItem = (props: Props) => { const t = useTranslations('report'); // ← サーバーでは getTranslations return ( <li> <span>{t('date')}:{props.date}</span> <span>{t('count', { count: props.count })}</span> </li> ); }; クライアントは useTranslations 、サーバーは getTranslations と関数が分かれる 加えて next.config へのプラグイン追加と、Provider がもう一段 © 2026 ANDPAD All Rights Reserved. Confidential 4
動く場所を意識させるAPIは再利用性を殺す 先の例のような小さな部品ほど、サーバーとクライアントの両方で使いたい なのにi18nのAPIが場所ごとに分かれていると、部品が動く場所に縛られる サーバーとクライアントで実行モデルが違うのは当然。問題はその違いをコンポーネント自身に意識させてい ること プラグインやProviderの追加も不要で、実行場所を意識せず、ラベルを差し替えるだけのAPIが欲しい © 2026 ANDPAD All
Rights Reserved. Confidential 5
単純に引数で渡す | colocale import { createTranslator, type Messages } from
'colocale'; import { reportItemTranslations } from './translations'; export const ReportListItem = (props: Props & { messages: Messages }) => { const t = createTranslator(props.messages, reportItemTranslations); return ( <li> <span>{t('date')}:{props.date}</span> <span>{t('count', { count: props.count })}</span> </li> ); }; 場所を知る責任が呼び出し側に移り、コンポーネントはどこでも動く 利用する辞書は translations.ts に置く: defineRequirement('report', ['date', 'count']) © 2026 ANDPAD All Rights Reserved. Confidential 6
代償とまだ解けていないこと Propsに messages が増える。いわゆるバケツリレー requirementを取り違えて絞ると、型は通るのに実行時にキーが足りない Messages 型がrequirementでパラメータ化されていないため 回避策はある: requirementを大きめの粒度で作ったり、requirementを省略して指定言語の全辞書を渡す(小 規模ならこれで十分)
宿題: 足りないキーをコンパイルエラーにする方法を探しています。心当たりのある方は教えてください。 © 2026 ANDPAD All Rights Reserved. Confidential 7
まとめ RSC時代に欲しかったのは、動く場所を知らなくていいi18n API Providerを捨てて引数で渡すだけで、同じコンポーネントがサーバーでもクライアントでも動く 副産物として、React以外でも同じ書き方が使える(Vueにも対応) colocale github.com/Urotea/colocale おまけ: 翻訳をYAMLで書いてJSONに変換するyamlocaleも公開しています(i18next /
react-intl / vue-i18n でも使えます) github.com/Urotea/yamlocale © 2026 ANDPAD All Rights Reserved. Confidential 8