Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
実行場所を意識させない i18n API を作った話
Search
ANDPAD inc
August 21, 2026
Programming
280
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
入社半年で感じた、急成長するプロダクトを支えるCREに求められるソフトスキルとは?
andpad
0
61
R8 の設定見直しでアプリサイズ削減
andpad
0
250
Go 探無比ワークショップ開催レポート
andpad
0
100
self-service-infrastructure-with-argocd-and-atlantis
andpad
0
25
Go 1.27 における memory allocation の高速化
andpad
0
490
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
240
OS アップデート対応の取り組み方がもっと共有されてほしい
andpad
0
170
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
660
ANDPAD Ruby sponsor session in RubyKaigi 2026
andpad
0
340
Other Decks in Programming
See All in Programming
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
140
作れるエンジニアから、価値を届けるエンジニアへ
ryunakayama
1
240
Spec-driven Development with AI
simas
PRO
0
2.3k
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
15
11k
AI-Powered Domain-Driven Design
ziobrando
0
420
Railsバージョンを4倍にした話
optim
0
970
作って学ぶSpring BootのAuto Configuration / JJUG Night Seminar 2026-10-19
rshindo
0
220
まずはコードより業務と向き合う:テーブル解体のためにPdMを呼んだ話
sakawe_ee
0
190
Snowflake Openflow Connector利用の勘所 / 20261024developersio2026tokyo-snowflake-openflow
kasacchiful
PRO
0
310
Python Lambdaにおけるテストしやすい設計とAI支援の活用 / Designing Testable Python Lambda Functions with AI
kitano_yuichi
1
310
Vue.jsで作る空間解析アプリとCapacitorプラグインのData Bridge
hal_spidernight
1
170
SODA - FACT BOOK(JP)
sodainc
1
40k
Featured
See All Featured
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
400
Mind Mapping
helmedeiros
1
430
How to Think Like a Performance Engineer
csswizardry
28
2.9k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
470
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
970
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
460
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.6k
We Are The Robots
honzajavorek
0
440
Into the Great Unknown - MozCon
thekraken
41
2.8k
RailsConf 2023
tenderlove
30
1.6k
エンジニアに許された特別な時間の終わり
watany
109
250k
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