Skip to content

Commit

Permalink
Add support for RTL languages (#77)
Browse files Browse the repository at this point in the history
* add expo-localization and declare app to support RTL

* add function to find best language match with reported locale

* make EditableNumberSlider work in RTL mode

* cherry pick prebuild changes

---------

Co-authored-by: tmgrask <[email protected]>
  • Loading branch information
daveosborne and tmgrask authored Dec 4, 2024
1 parent ba9aa10 commit e17045c
Show file tree
Hide file tree
Showing 19 changed files with 441 additions and 72 deletions.
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
<activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
<activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode|locale|layoutDirection" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
Expand Down
2 changes: 2 additions & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@
<string name="notification_conduit_failed_to_restart_text">Conduit service failed to restart. Tap the notification for more information</string>
<!-- Notification text for Conduit starting notification -->
<string name="conduit_service_starting_notification_text">Conduit service is starting…</string>
<!-- Added by expo-localiztion -->
<string name="ExpoLocalization_supportsRTL" translatable="false">true</string>
</resources>
6 changes: 5 additions & 1 deletion app.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@
},
"package": "ca.psiphon.conduit"
},
"extra": {
"supportsRTL": true
},
"plugins": [
"expo-router"
"expo-router",
"expo-localization"
],
"experiments": {
"typedRoutes": true
Expand Down
2 changes: 2 additions & 0 deletions ios/conduit/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
</array>
<key>CFBundleVersion</key>
<string>23</string>
<key>ExpoLocalization_supportsRTL</key>
<true/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
Expand Down
35 changes: 19 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"moduleNameMapper": {
"micro-key-producer/src/slip10": "micro-key-producer/slip10.js"
},
"setupFiles": ["./src/jestSetup.js"]
"setupFiles": [
"./src/jestSetup.js"
]
},
"prettier": {
"tabWidth": 4,
Expand Down Expand Up @@ -54,12 +56,12 @@
"react-i18next": "^15.0.2",
"react-native": "0.74.5",
"react-native-gesture-handler": "~2.16.1",
"react-native-localize": "^3.2.1",
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
"zod": "^3.23.8",
"expo-keep-awake": "~13.0.2"
"expo-keep-awake": "~13.0.2",
"expo-localization": "~15.0.3"
},
"devDependencies": {
"@babel/core": "^7.20.0",
Expand Down
1 change: 1 addition & 0 deletions src/app/(app)/onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ export default function OnboardingScreen() {
const paragraphStyle = {
textAlign: TextAlign.Center,
};

const textStyle: SkTextStyle = {
color: Skia.Color(palette.blueTint2),
fontFamilies: ["Jura"],
Expand Down
1 change: 1 addition & 0 deletions src/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export default function RootLayout() {
const [loaded] = useFonts({
JuraRegular: fonts.JuraRegular,
JuraBold: fonts.JuraBold,
Rajdhani: fonts.Rajdhani,
});

useEffect(() => {
Expand Down
44 changes: 31 additions & 13 deletions src/components/ConduitSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,16 @@ import {
InproxyParametersSchema,
} from "@/src/inproxy/types";
import { getProxyId } from "@/src/inproxy/utils";
import { lineItemStyle, palette, sharedStyles as ss } from "@/src/styles";
import {
lineItemRTLStyle,
lineItemStyle,
palette,
sharedStyles as ss,
} from "@/src/styles";

export function ConduitSettings() {
const { t } = useTranslation();
const { t, i18n } = useTranslation();
const isRTL = i18n.dir() === "rtl" ? true : false;
const win = useWindowDimensions();
const router = useRouter();

Expand Down Expand Up @@ -176,12 +182,18 @@ export function ConduitSettings() {
const scrollRef = React.useRef<ScrollView | null>(null);

function Settings() {
let lineStyle;
if (isRTL) {
lineStyle = lineItemRTLStyle;
} else {
lineStyle = lineItemStyle;
}
return (
<View style={[ss.flex]}>
<View
style={[
ss.padded,
ss.row,
isRTL ? ss.rowRTL : ss.row,
ss.alignCenter,
ss.greyBorderBottom,
]}
Expand Down Expand Up @@ -245,7 +257,7 @@ export function ConduitSettings() {
originalValue={inproxyParameters.maxClients}
min={1}
max={INPROXY_MAX_CLIENTS_MAX}
style={[...lineItemStyle, ss.alignCenter]}
style={[...lineStyle, ss.alignCenter]}
onChange={updateInproxyMaxClients}
scrollRef={scrollRef}
/>
Expand All @@ -256,13 +268,13 @@ export function ConduitSettings() {
)}
min={8}
max={INPROXY_MAX_MBPS_PER_PEER_MAX}
style={[...lineItemStyle, ss.alignCenter]}
style={[...lineStyle, ss.alignCenter]}
onChange={updateInproxyLimitBytesPerSecond}
scrollRef={scrollRef}
/>
<View
style={[
...lineItemStyle,
...lineStyle,
ss.flex,
ss.alignCenter,
ss.justifySpaceBetween,
Expand All @@ -280,17 +292,17 @@ export function ConduitSettings() {
</View>
<View
style={[
...lineItemStyle,
ss.greyBorderBottom,
ss.flex,
ss.alignCenter,
ss.height120,
{ height: 140 },
ss.column,
ss.padded,
]}
>
<View
style={[
ss.row,
isRTL ? ss.rowRTL : ss.row,
ss.fullWidth,
ss.justifySpaceBetween,
ss.alignCenter,
Expand All @@ -310,7 +322,13 @@ export function ConduitSettings() {
/>
)}
</View>
<View style={[ss.flex, ss.row, ss.alignCenter]}>
<View
style={[
isRTL ? ss.rowRTL : ss.row,
ss.flex,
ss.alignCenter,
]}
>
<Text style={[ss.whiteText, ss.bodyFont]}>
{t("ALIAS_I18N.string")}:
</Text>
Expand All @@ -319,7 +337,7 @@ export function ConduitSettings() {
</View>
<View
style={[
...lineItemStyle,
...lineStyle,
ss.flex,
ss.alignCenter,
ss.justifySpaceBetween,
Expand All @@ -334,7 +352,7 @@ export function ConduitSettings() {
notificationsPermission != "GRANTED" && (
<View
style={[
...lineItemStyle,
...lineStyle,
ss.flex,
ss.alignCenter,
ss.justifySpaceBetween,
Expand All @@ -345,7 +363,7 @@ export function ConduitSettings() {
)}
<View
style={[
...lineItemStyle,
...lineStyle,
ss.flex,
ss.alignCenter,
ss.justifySpaceBetween,
Expand Down
18 changes: 12 additions & 6 deletions src/components/ConduitStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ import {
LinearGradient,
Paragraph,
Rect,
SkParagraphStyle,
SkTextStyle,
Skia,
TextAlign,
TextDirection,
interpolateColors,
useFonts,
vec,
Expand Down Expand Up @@ -58,7 +61,8 @@ export function ConduitStatus({
width: number;
height: number;
}) {
const { t } = useTranslation();
const { t, i18n } = useTranslation();
const isRTL = i18n.dir() === "rtl" ? true : false;
const win = useWindowDimensions();

const { logErrorToDiagnostic } = useInproxyContext();
Expand Down Expand Up @@ -143,10 +147,13 @@ export function ConduitStatus({
if (!fontMgr) {
return null;
}
const paragraphStyle = {
let paragraphStyle: SkParagraphStyle = {
textAlign: TextAlign.Center,
};
const mainTextStyle = {
if (isRTL) {
paragraphStyle.textDirection = TextDirection.RTL;
}
const mainTextStyle: SkTextStyle = {
color: Skia.Color(palette.statusTextBlue),
fontFamilies: ["Jura"],
fontSize: fontSize,
Expand All @@ -155,7 +162,7 @@ export function ConduitStatus({
},
letterSpacing: 1, // 5% of 20
};
const runningTextStyle = {
const runningTextStyle: SkTextStyle = {
color: Skia.Color(palette.red),
fontFamilies: ["Jura"],
fontSize: fontSize,
Expand All @@ -164,8 +171,7 @@ export function ConduitStatus({
},
letterSpacing: 1, // 5% of 20
};

const waitingTextStyle = {
const waitingTextStyle: SkTextStyle = {
color: Skia.Color(palette.grey),
fontFamilies: ["Jura"],
fontSize: fontSize,
Expand Down
28 changes: 24 additions & 4 deletions src/components/EditableNumberSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ import Animated, {
} from "react-native-reanimated";

import { AnimatedText } from "@/src/components/AnimatedText";
import { lineItemStyle, palette, sharedStyles as ss } from "@/src/styles";
import {
lineItemRTLStyle,
lineItemStyle,
palette,
sharedStyles as ss,
} from "@/src/styles";
import { useTranslation } from "react-i18next";
import {
Gesture,
GestureDetector,
Expand All @@ -63,6 +69,12 @@ export function EditableNumberSlider({
onChange,
scrollRef,
}: EditableNumberSliderProps) {
const { i18n } = useTranslation();
const isRTL = i18n.dir() === "rtl" ? true : false;

if (isRTL) {
style = lineItemRTLStyle;
}
const value = useSharedValue(originalValue);
const displayText = useDerivedValue(() => {
const changed = value.value === originalValue ? " " : "*";
Expand Down Expand Up @@ -137,9 +149,10 @@ export function EditableNumberSlider({
prevCircleCxPct.value = circleCxPct.value;
})
.onUpdate((event) => {
const rtl = isRTL ? -1 : 1;
const newCircleCxPct = clamp(
prevCircleCxPct.value +
(event.translationX / usableWidth.value) * 100,
((rtl * event.translationX) / usableWidth.value) * 100,
0,
100,
);
Expand All @@ -152,7 +165,14 @@ export function EditableNumberSlider({
return (
<View style={[...style, ss.flex, ss.justifySpaceBetween]}>
<Text style={[ss.bodyFont, ss.whiteText]}>{label}</Text>
<View style={[ss.row, ss.flex, { maxWidth: 180 }]}>
<View
style={[
isRTL ? ss.rowRTL : ss.row,
isRTL ? { transform: "scaleX(-1)" } : {},
ss.flex,
{ maxWidth: 180 },
]}
>
<View style={[ss.flex]}>
<Canvas style={[ss.flex]} onSize={canvasSize}>
<RoundedRect
Expand Down Expand Up @@ -202,7 +222,7 @@ export function EditableNumberSlider({
/>
</Canvas>
<GestureDetector gesture={sliderGesture}>
<Animated.View style={overlayStyle} />
<Animated.View style={[overlayStyle]} />
</GestureDetector>
</View>
<View style={[ss.row, ss.alignCenter]}>
Expand Down
Loading

0 comments on commit e17045c

Please sign in to comment.