You can keep translations in one shared workspace package and let Expo and Next.js handle locale selection in their own way. The shared package should define supported locale IDs, dictionaries, the default fallback locale, and—if both apps need it—a lookup helper that falls back when a key is missing. Expo can read device or app language settings; Next.js can use a locale in the URL or a request preference. Validate either choice against the same supported-locale list before loading strings.
How the shared-dictionary design works
Put framework-neutral translation data and locale definitions in a workspace package that both apps can import. Keep platform decisions in each app: Expo reads native language preferences, while Next.js resolves a web locale from routing or request preferences. This division shares the source of truth without forcing the two runtimes to share locale-detection behavior.
As an Amazon Associate I earn from qualifying purchases.
Expo documents workspace monorepos for sharing code, and Next.js provides transpilePackages to bundle local packages. The package structure itself is a project choice, not a framework requirement.
Suggested shared exports
- A finite
localeslist and correspondingLocaletype. - A single
fallbackLocaleconstant, such asenif English is the product default. - Translation dictionaries, organized as locale modules or another shared data format.
- A language-neutral lookup helper if both apps should use identical missing-key behavior.
Keep the shared package usable in both browser and native code: do not import server-only modules or framework-specific runtime APIs into it. For Next.js, dictionary loading can remain on the server when the page is a Server Component, avoiding sending the full dictionary to the client unnecessarily.
#1 Best Overall
Define locale selection and fallback separately
There are two distinct cases: a requested locale may not be supported, or a supported locale may lack a particular translation key. Choose a supported fallback locale for the first case—or deliberately reject an unsupported route. For the second, check the active dictionary first and then the fallback dictionary. Do not assume a framework handles both cases automatically.
Normalize tags deliberately. For example, decide whether a request for en-US should map to the supported key en; a regional tag and a base-language key are not interchangeable unless your app explicitly makes them so.
Rank #2
Set up the shared package
- Choose the supported locale IDs. Define them once and reuse the same identifiers in Expo settings, Next.js routing, and dictionary keys.
- Choose the fallback locale. Make it explicit in the package rather than letting each app quietly invent a different default.
- Store or generate dictionaries from one source. Both apps should import the same translation data or build their dictionaries from a shared source, not maintain parallel copies.
- Confirm each app can resolve the workspace package. Expo’s monorepo guide covers workspace support; Next.js documents
transpilePackagesfor local packages. - Keep package code cross-platform. Put data and language-neutral functions there; put device APIs, request handling, and framework-specific loading in the consuming app.
Choose and apply a language in Expo
Expo’s localization guide demonstrates reading device preferences with expo-localization and using i18n-js to hold dictionaries. Its example selects a device language code and enables fallback when a key is missing. In a shared-package design, retain that platform-specific preference reading, but resolve the result against the shared locale list before selecting a dictionary.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Device preference need not be the only choice: an app can also provide a language selector where appropriate. Expo notes that iOS resets the app when the device language changes while it is running, whereas Android does not. An Android app may therefore need to refresh locale state when the app becomes active.
If users should be able to set the app language through system settings, declare supported native locales. Also check right-to-left layout behavior on the platforms you support; translating strings alone does not configure the entire interface.
Choose and apply a language in Next.js
For locale-specific URLs in the App Router, place route files under a dynamic segment such as app/[lang]. The Next.js internationalization guide describes subpath and domain routing, matching Accept-Language against supported locales, and using a default locale. The application remains responsible for validating the selected locale and loading its dictionary.
Rank #4
- Select a locale source. Use the route locale, a request preference, a cookie, or an explicit selector according to the product’s URL and persistence requirements.
- Validate before loading. Match the candidate against the shared locale list. For an unsupported route, decide whether to use the fallback or call
notFound(). - Load the corresponding shared dictionary. Prefer server-side loading in a Server Component when client-side access is not needed.
- Enumerate static locale routes if useful. Next.js supports listing locale paths with
generateStaticParams. - Set the document language. Ensure the rendered HTML exposes the chosen locale through an appropriate
langattribute.
The Next.js guide demonstrates locale validation and dictionary loading, but does not prescribe per-key fallback. If the web app needs the same missing-key behavior as the native app, use an explicit shared lookup helper or implement that behavior in the web app.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Keep message lookup separate from localized formatting
A dictionary translates message text; it does not by itself format dates, numbers, currencies, units, lists, or plural forms. Once the locale is known, use standardized Intl APIs for locale-sensitive formatting. This keeps formatting behavior separate from choosing a message string and avoids hard-coding conventions into translations.
Quick Recap
Best Value
Decisions to make before shipping
- Locale source: device or app settings in Expo; URL, request headers, cookies, or a selector on the web.
- URL strategy: locale subpaths such as
/fr/productsor locale-specific domains, and whether the default locale has a prefix. - Fallback semantics: define separately what happens for an unsupported locale and for a missing key.
- Dictionary loading: choose an eager shared object, per-locale modules, or lazy loading based on bundle needs.
- Message features: decide whether keyed strings suffice or whether you need pluralization, extraction, translator context, or translation-management integration.
- Platform coverage: check HTML language metadata, native locale declarations, right-to-left layout, and locale changes while the app runs.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




