Harden RTL language detection
This commit is contained in:
+1
-1
@@ -340,7 +340,7 @@
|
|||||||
"^cborg$": "<rootDir>/node_modules/cborg/cborg.js"
|
"^cborg$": "<rootDir>/node_modules/cborg/cborg.js"
|
||||||
},
|
},
|
||||||
"transformIgnorePatterns": [
|
"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": [
|
"modulePathIgnorePatterns": [
|
||||||
"__tests__/.*/__mocks__",
|
"__tests__/.*/__mocks__",
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import '@formatjs/intl-locale/polyfill-force.js'
|
||||||
|
|
||||||
import {describe, expect, it, jest} from '@jest/globals'
|
import {describe, expect, it, jest} from '@jest/globals'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -33,6 +35,11 @@ describe('forceLTR', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('isRTL', () => {
|
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', () => {
|
it('recognizes right-to-left languages and scripts', () => {
|
||||||
expect(isRTL('he')).toBe(true)
|
expect(isRTL('he')).toBe(true)
|
||||||
expect(isRTL('ar')).toBe(true)
|
expect(isRTL('ar')).toBe(true)
|
||||||
|
|||||||
+11
-4
@@ -2,6 +2,7 @@ import {IS_WEB} from '#/env'
|
|||||||
|
|
||||||
const LEFT_TO_RIGHT_EMBEDDING = '\u202A'
|
const LEFT_TO_RIGHT_EMBEDDING = '\u202A'
|
||||||
const POP_DIRECTIONAL_FORMATTING = '\u202C'
|
const POP_DIRECTIONAL_FORMATTING = '\u202C'
|
||||||
|
const languageDirectionCache = new Map<string, boolean>()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force LTR directionality in a string.
|
* Force LTR directionality in a string.
|
||||||
@@ -24,10 +25,16 @@ export function forceLTR(str: string) {
|
|||||||
export function isRTL(language: string | undefined) {
|
export function isRTL(language: string | undefined) {
|
||||||
if (!language) return false
|
if (!language) return false
|
||||||
|
|
||||||
|
const cached = languageDirectionCache.get(language)
|
||||||
|
if (cached !== undefined) return cached
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new Intl.Locale(language).getTextInfo().direction === 'rtl'
|
const isRightToLeft =
|
||||||
} catch (error) {
|
new Intl.Locale(language).getTextInfo().direction === 'rtl'
|
||||||
if (error instanceof RangeError) return false
|
languageDirectionCache.set(language, isRightToLeft)
|
||||||
throw error
|
return isRightToLeft
|
||||||
|
} catch {
|
||||||
|
languageDirectionCache.set(language, false)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user