React-Native accessibilityRole i18n support for iOS and Android

Valtteri Laine
3 min readMar 27, 2021

--

When implementing changes required by EU accessibility Compliance legislation to your React-Native app, you may notice that the accessibilityRole prop is not translated automatically by the screenreader. Instead you will have to add the translations yourself.

Some of them are already translated and some of them weren’t. I assume this depends on how React-Native has implemented the component. If React-Native is just using some native Android component in the background, instead of creating it’s own, then it’s likely translated already. This is also platform dependant. Some values are translated on iOS, but not on Android and other way around.

Here is how to add them all on Android and iOS!

What is accessibilityRole?

accessibilityRole prop is a prop you can give a component to identify it as an element of specific type e.g. a button, header, radio etc. This will affect how the element is announced by screenreader.

For instance the following is not accessible, as screenreader only says “Read more!”

<TouchableOpacity
onPress={openURL}
>
<Text>Read more!</Text>
</TouchableOpacity>

With accessibilityRole the screenreader knows to announce the component as a link to the user. This way the user knows the element is interactable, and is also likely to open up a browser upon activation.

<TouchableOpacity
accessibilityRole="link"
onPress={openURL}
>
<Text>Read more!</Text>
</TouchableOpacity>

This works great, until you have to support other languages than just English.

Here is how to add translations for accessibilityRole for any language.

How to add Android accessibilityRole translations

In your React-Native project add a file for each language you want. For example, for Finnish translations we would add:

android/app/src/main/res/values-fi/strings.xml

Just replace the “fi” part with your desired languages country code.

For example, in order to translate “accessibilityRole=”button”, we add the following into strings.xml:

<resources>  
<string
name="button_description"
translatable="false"
>
Painike
</string>
</resources>

After you have done added the code above and saved, you can build your Android version, and now your component should be read out as “Painike” when your screenreader is set to Finnish.

This same approach should work for most accessibilityRole props on Android.

A list of strings you may want to translate on Android can be found from here: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/res/views/uimanager/values/strings_unlocalized.xml

Read more about Android localisation.

Solution source

How to add iOS accessibilityRole translations

With iOS it gets a bit more tricky. The translations are defined in the path:

my-react-native-project/node_modules/react-native/React/AccessibilityResources/en.lproj/Localizable.strings

Yikes! That is in node_modules! This is why we have to use npm package called patch-package. It allows us to modify node_modules and save the changes to git. Another option would be forking React-Native repo, but then you would have to maintain that fork. Using patch-package requires less effort.

Install patch-package

npm i patch-package --save-dev

In package.json add:

"scripts": {
+ "postinstall": "patch-package"
}

This makes sure our changes are applied to node_modules every time npm install is ran.

Then, for example, to translate accessibilityRole=”radio” to Finnish, we would add the following:

/* Localizable.strings React */"radio"="valintanappi";

to file path (again replace “fi” in folder name with desired countrycode):

my-react-native-project/node_modules/react-native/React/AccessibilityResources/fi.lproj/Localizable.strings

And then run:

npx patch-package package-name 

This creates the following file:

my-react-native-project/patches/react-native+0.63.4.patch

The file contains the instructions to modify node_modules to include the translations file we just added. Make sure to commit it into your git!

Thats it! Now whatever accessibilityRole prop value you use on iOS it should be translated! Simply rebuild your application and change your screenreader to the desired language and give it a spin :)

--

--