Skip to content

Commit

Permalink
Add localized accessibility strings to React Core pod (#27995)
Browse files Browse the repository at this point in the history
Summary:
The accessibility roles and states description strings are not able to be localized on iOS platform. Those strings are exposed to the end users so it should be localized. This PR is to add localized strings as a resource bundle to the React Core Pod so that any React Native app integrating the React Native dependencies using CocoaPods can get the localized accessibility roles and states description.

## Changelog

[iOS] [Added] - Add localized accessibility strings to React Core pod
Pull Request resolved: #27995

Test Plan: Verified with RNTester app.

Differential Revision: D19975587

Pulled By: PeteTheHeat

fbshipit-source-id: f8eb4e25194f0cd603c98a6221ec87503a2826ed
  • Loading branch information
xuelgong authored and facebook-github-bot committed Feb 20, 2020
1 parent 24e0bad commit aebf54a
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 39 deletions.
1 change: 1 addition & 0 deletions React-Core.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Pod::Spec.new do |s|
s.author = "Facebook, Inc. and its affiliates"
s.platforms = { :ios => "10.0", :tvos => "10.0" }
s.source = source
s.resource_bundle = { "AccessibilityResources" => ["React/AccessibilityResources/*.lproj"]}
s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
s.header_dir = "React"
s.framework = "JavaScriptCore"
Expand Down
26 changes: 26 additions & 0 deletions React/AccessibilityResources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
Localizable.strings
React
*/
"alert"="alert";
"checkbox"="checkbox";
"combobox"="combo box";
"menu"="menu";
"menubar"="menu bar";
"menuitem"="menu item";
"progressbar"="progress bar";
"radio"="radio button";
"radiogroup"="radio group";
"scrollbar"="scroll bar";
"spinbutton"="spin button";
"switch"="switch";
"tab"="tab description";
"tablist"="tab list";
"timer"="timer";
"toolbar"="tool bar";
"checked"="checked";
"unchecked"="not checked";
"busy"="busy";
"expanded"="expanded";
"collapsed"="collapsed";
"mixed"="mixed";
89 changes: 50 additions & 39 deletions React/Views/RCTView.m
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,51 @@ - (BOOL)didActivateAccessibilityCustomAction:(UIAccessibilityCustomAction *)acti

- (NSString *)accessibilityValue
{
static dispatch_once_t onceToken;
static NSDictionary<NSString *, NSString *> *rolesAndStatesDescription = nil;

dispatch_once(&onceToken, ^{
NSString *bundlePath = [[NSBundle mainBundle]pathForResource:@"AccessibilityResources" ofType:@"bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];

if (bundle) {
NSURL *url = [bundle URLForResource:@"Localizable" withExtension:@"strings"];
if (@available(iOS 11.0, *)) {
rolesAndStatesDescription = [NSDictionary dictionaryWithContentsOfURL:url error:nil];
} else {
// Fallback on earlier versions
rolesAndStatesDescription = [NSDictionary dictionaryWithContentsOfURL:url];
}
}
if (rolesAndStatesDescription == nil) {
NSLog(@"Cannot load localized accessibility strings.");
rolesAndStatesDescription = @{
@"alert" : @"alert",
@"checkbox" : @"checkbox",
@"combobox" : @"combo box",
@"menu" : @"menu",
@"menubar" : @"menu bar",
@"menuitem" : @"menu item",
@"progressbar" : @"progress bar",
@"radio" : @"radio button",
@"radiogroup" : @"radio group",
@"scrollbar" : @"scroll bar",
@"spinbutton" : @"spin button",
@"switch" : @"switch",
@"tab" : @"tab",
@"tablist" : @"tab list",
@"timer" : @"timer",
@"toolbar" : @"tool bar",
@"checked" : @"checked",
@"unchecked" : @"not checked",
@"busy" : @"busy",
@"expanded" : @"expanded",
@"collapsed" : @"collapsed",
@"mixed": @"mixed",
};
}
});

if ((self.accessibilityTraits & SwitchAccessibilityTrait) == SwitchAccessibilityTrait) {
for (NSString *state in self.accessibilityState) {
id val = self.accessibilityState[state];
Expand All @@ -214,41 +259,7 @@ - (NSString *)accessibilityValue
}
}
NSMutableArray *valueComponents = [NSMutableArray new];
static NSDictionary<NSString *, NSString *> *roleDescriptions = nil;
static dispatch_once_t onceToken1;
dispatch_once(&onceToken1, ^{
roleDescriptions = @{
@"alert" : @"alert",
@"checkbox" : @"checkbox",
@"combobox" : @"combo box",
@"menu" : @"menu",
@"menubar" : @"menu bar",
@"menuitem" : @"menu item",
@"progressbar" : @"progress bar",
@"radio" : @"radio button",
@"radiogroup" : @"radio group",
@"scrollbar" : @"scroll bar",
@"spinbutton" : @"spin button",
@"switch" : @"switch",
@"tab" : @"tab",
@"tablist" : @"tab list",
@"timer" : @"timer",
@"toolbar" : @"tool bar",
};
});
static NSDictionary<NSString *, NSString *> *stateDescriptions = nil;
static dispatch_once_t onceToken2;
dispatch_once(&onceToken2, ^{
stateDescriptions = @{
@"checked" : @"checked",
@"unchecked" : @"not checked",
@"busy" : @"busy",
@"expanded" : @"expanded",
@"collapsed" : @"collapsed",
@"mixed": @"mixed",
};
});
NSString *roleDescription = self.accessibilityRole ? roleDescriptions[self.accessibilityRole]: nil;
NSString *roleDescription = self.accessibilityRole ? rolesAndStatesDescription[self.accessibilityRole]: nil;
if (roleDescription) {
[valueComponents addObject:roleDescription];
}
Expand All @@ -259,16 +270,16 @@ - (NSString *)accessibilityValue
}
if ([state isEqualToString:@"checked"]) {
if ([val isKindOfClass:[NSNumber class]]) {
[valueComponents addObject:stateDescriptions[[val boolValue] ? @"checked" : @"unchecked"]];
[valueComponents addObject:rolesAndStatesDescription[[val boolValue] ? @"checked" : @"unchecked"]];
} else if ([val isKindOfClass:[NSString class]] && [val isEqualToString:@"mixed"]) {
[valueComponents addObject:stateDescriptions[@"mixed"]];
[valueComponents addObject:rolesAndStatesDescription[@"mixed"]];
}
}
if ([state isEqualToString:@"expanded"] && [val isKindOfClass:[NSNumber class]]) {
[valueComponents addObject:stateDescriptions[[val boolValue] ? @"expanded" : @"collapsed"]];
[valueComponents addObject:rolesAndStatesDescription[[val boolValue] ? @"expanded" : @"collapsed"]];
}
if ([state isEqualToString:@"busy"] && [val isKindOfClass:[NSNumber class]] && [val boolValue]) {
[valueComponents addObject:stateDescriptions[@"busy"]];
[valueComponents addObject:rolesAndStatesDescription[@"busy"]];
}
}

Expand Down

0 comments on commit aebf54a

Please sign in to comment.