Harden RTL language detection

This commit is contained in:
Eric Bailey
2026-08-28 14:52:49 -05:00
parent 5bde4cddb2
commit 29e16bdd42
3 changed files with 19 additions and 5 deletions
+1 -1
View File
@@ -340,7 +340,7 @@
"^cborg$": "<rootDir>/node_modules/cborg/cborg.js"
},
"transformIgnorePatterns": [
"node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|nanoid|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|normalize-url|react-native-svg|@sentry/.*|sentry-expo|bcp-47-match|@atproto/.*|@bsky/sdk|tlds|multiformats|uint8arrays|@ipld/.*|cborg|await-lock)"
"node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|nanoid|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|normalize-url|react-native-svg|@sentry/.*|sentry-expo|bcp-47-match|@formatjs/.*|@formatjs_generated/.*|@atproto/.*|@bsky/sdk|tlds|multiformats|uint8arrays|@ipld/.*|cborg|await-lock)"
],
"modulePathIgnorePatterns": [
"__tests__/.*/__mocks__",
+7
View File
@@ -1,3 +1,5 @@
import '@formatjs/intl-locale/polyfill-force.js'
import {describe, expect, it, jest} from '@jest/globals'
/*
@@ -33,6 +35,11 @@ describe('forceLTR', () => {
})
describe('isRTL', () => {
it('uses the Intl.Locale implementation forced in production', () => {
expect(Intl.Locale).toHaveProperty('polyfilled', true)
expect(Intl.Locale.prototype).toHaveProperty('getTextInfo')
})
it('recognizes right-to-left languages and scripts', () => {
expect(isRTL('he')).toBe(true)
expect(isRTL('ar')).toBe(true)
+11 -4
View File
@@ -2,6 +2,7 @@ import {IS_WEB} from '#/env'
const LEFT_TO_RIGHT_EMBEDDING = '\u202A'
const POP_DIRECTIONAL_FORMATTING = '\u202C'
const languageDirectionCache = new Map<string, boolean>()
/*
* Force LTR directionality in a string.
@@ -24,10 +25,16 @@ export function forceLTR(str: string) {
export function isRTL(language: string | undefined) {
if (!language) return false
const cached = languageDirectionCache.get(language)
if (cached !== undefined) return cached
try {
return new Intl.Locale(language).getTextInfo().direction === 'rtl'
} catch (error) {
if (error instanceof RangeError) return false
throw error
const isRightToLeft =
new Intl.Locale(language).getTextInfo().direction === 'rtl'
languageDirectionCache.set(language, isRightToLeft)
return isRightToLeft
} catch {
languageDirectionCache.set(language, false)
return false
}
}