Repository navigation
feat(react-native-plugin): take $app_language from JS instead of native detection - #5602
turnipdabeets wants to merge 4 commits into
Conversation
…ve detection Turn off posthog-ios/posthog-android app-language detection and add a setAppLanguage bridge method, so native events (crashes, push opens) carry the language the JS app displays.
bfbd67a to
8fba5dd
Compare
Coherence📄 0 spec file errors · ⛔ 0 broken rules · 🚪 2 unchecked inputs · 🐛 0 bugs that came back What is Coherence?Coherence compares the code with its spec files ( This check read 44 parts of the code and 7 rules. Note These findings do not make this check fail. None of these findings are in files that this pull request changes. You do not need to fix them in this pull request. 🚪 Unchecked inputs (2)
What this means and how to fix itInput from outside this code comes in at these places. The spec does not say what checks that input. 10 more places were already like this when Coherence was added. This list does not show them. To close one of these, find the place by its name in the
To get the line to add, run |
SDK performance: posthog-nodeBenchmarks completed. No changes flagged for review. Flags require at least a 5% change in the median and all six pairs agreeing on direction. This is a noise filter, not proof of a performance change or a CI gate. View all results
Values are medians of paired measurements. Not flagged does not mean unchanged. Unavailable means a measurement could not be provided, not zero. Estimated allocation measurements retain their instrumentation uncertainty. RSS measures the whole process, not just SDK allocations; observed peaks are sampled checkpoints. Paired ranges in the diagnostics describe variability, not confidence intervals. Each shard uses its own runner; compare Before PR against With PR within a row, not across shards. Compared 102 metric rows; 102 rows shown in all results. Omitted or shortened data remain in |
|
…so cold-start push opens carry it
Problem
On plugin 3.0 (posthog-ios / posthog-android 4.0), native events such as crashes and push opens get
$app_languagefrom native detection. RN apps usually translate in JavaScript, so that's often wrong. On iOS, an app with no.lprojresources reports its development region (for exampleen) while the screen is in German. On Android 13+ detection reads thelocaleConfig, not the JS language. JS events don't carry the detected value, so native and JS events disagree.posthog-flutter had the same problem. PostHog/posthog-flutter#699 turned native detection off and forwards the app's language to native through
setAppLanguage. This PR does the same for RN.Why JS sets it and native detection is off
Native detection doesn't look at the screen. It asks the OS which of the app's native resources it picked:
Bundle.main.preferredLocalizations, the device languages matched against the.lprojfolders the app ships.localeConfig. Below 13 it reports nothing.That's right for native apps, because the OS loads their strings. In React Native the strings come from the JS bundle (i18next, react-intl, a hand-rolled table), so the OS never knows which language is on screen. JavaScript can't detect it generically either, because there's no standard "current app language" outside each i18n library. The device locale is already sent as
$locale, and copying it would be wrong whenever the app doesn't support that language. Only the app knows, so the app passes it in.Detection is turned off rather than left on with
setAppLanguageoverriding it. With detection on, apps that never callsetAppLanguagewould send a value that looks right but is wrong (enon a German screen). With it off, they send nothing.posthog-kmp (PostHog/posthog-kmp#115) keeps native detection on and adds
setAppLanguage()as an override. Many KMP apps share only logic and keep native UI with.lproj/res/values-*strings, so detection is right for them. In RN, native resources never decide the language on screen.Changes
detectAppLanguage = falseinsetup(). It's SPI/internal on posthog-ios 4.0 (@_spi(PostHogInternal), already imported) and posthog-android 4.0 (@PostHogInternal).setAppLanguage(language: string | null)bridge method that calls the nativesetAppLanguage. It always resolves.appLanguagesetup option (sent by feat(react-native): add setAppLanguage() for $app_language #5601) on the native SDK just beforesetup(), so the push open captured on a cold launch carries it. A missing ornullvalue clears one an earlier JS client left.@internal, same asmarkFatalExceptionHandled.$app_language. Until the app callsposthog.setAppLanguage(), native events carry no$app_language, the same as JS events.Caller:
posthog-react-native's newsetAppLanguage()(companion PR againstmain, #5601). It calls the method only when it exists, so any combination of plugin and RN versions keeps working.Release info Sub-libraries affected
Libraries affected
Checklist
If releasing new changes
pnpm changesetto generate a changeset file🤖 Agent context
Autonomy: Human-driven (agent-assisted)
PosthogFlutterPlugin.swift/.ktfrom feat!: report the device language as $locale and add $app_language posthog-flutter#699.app-language.test.ts). Android::posthog_react-native-plugin:compileDebugKotlin testDebugUnitTestpasses against a locally published posthog-android 4.0.0 (mavenLocal, not committed). iOS: the RN example wasn't built because posthog-ios 4.0.0 isn't tagged yet. The two new Swift calls were type-checked against posthog-ioschore/v4-remove-deprecatedin a scratch package. The later pre-setupsetAppLanguagecall (2b1f170) hasn't been compiled on either platform: CI's example builds can't resolve the unreleased 4.0.0 artifacts.MIGRATION.mdgets a section on$app_language, which assumes the RN change ships inposthog-react-native4.86.0. Confirm the version at release.🤖 Generated with Claude Code