Skip to content

Commit aebf54a

Browse files
xuelgongfacebook-github-bot
authored andcommitted
Add localized accessibility strings to React Core pod (#27995)
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
1 parent 24e0bad commit aebf54a

File tree

3 files changed

+77
-39
lines changed

3 files changed

+77
-39
lines changed

React-Core.podspec

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Pod::Spec.new do |s|
4444
s.author = "Facebook, Inc. and its affiliates"
4545
s.platforms = { :ios => "10.0", :tvos => "10.0" }
4646
s.source = source
47+
s.resource_bundle = { "AccessibilityResources" => ["React/AccessibilityResources/*.lproj"]}
4748
s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
4849
s.header_dir = "React"
4950
s.framework = "JavaScriptCore"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
Localizable.strings
3+
React
4+
*/
5+
"alert"="alert";
6+
"checkbox"="checkbox";
7+
"combobox"="combo box";
8+
"menu"="menu";
9+
"menubar"="menu bar";
10+
"menuitem"="menu item";
11+
"progressbar"="progress bar";
12+
"radio"="radio button";
13+
"radiogroup"="radio group";
14+
"scrollbar"="scroll bar";
15+
"spinbutton"="spin button";
16+
"switch"="switch";
17+
"tab"="tab description";
18+
"tablist"="tab list";
19+
"timer"="timer";
20+
"toolbar"="tool bar";
21+
"checked"="checked";
22+
"unchecked"="not checked";
23+
"busy"="busy";
24+
"expanded"="expanded";
25+
"collapsed"="collapsed";
26+
"mixed"="mixed";

React/Views/RCTView.m

+50-39
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,51 @@ - (BOOL)didActivateAccessibilityCustomAction:(UIAccessibilityCustomAction *)acti
202202

203203
- (NSString *)accessibilityValue
204204
{
205+
static dispatch_once_t onceToken;
206+
static NSDictionary<NSString *, NSString *> *rolesAndStatesDescription = nil;
207+
208+
dispatch_once(&onceToken, ^{
209+
NSString *bundlePath = [[NSBundle mainBundle]pathForResource:@"AccessibilityResources" ofType:@"bundle"];
210+
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
211+
212+
if (bundle) {
213+
NSURL *url = [bundle URLForResource:@"Localizable" withExtension:@"strings"];
214+
if (@available(iOS 11.0, *)) {
215+
rolesAndStatesDescription = [NSDictionary dictionaryWithContentsOfURL:url error:nil];
216+
} else {
217+
// Fallback on earlier versions
218+
rolesAndStatesDescription = [NSDictionary dictionaryWithContentsOfURL:url];
219+
}
220+
}
221+
if (rolesAndStatesDescription == nil) {
222+
NSLog(@"Cannot load localized accessibility strings.");
223+
rolesAndStatesDescription = @{
224+
@"alert" : @"alert",
225+
@"checkbox" : @"checkbox",
226+
@"combobox" : @"combo box",
227+
@"menu" : @"menu",
228+
@"menubar" : @"menu bar",
229+
@"menuitem" : @"menu item",
230+
@"progressbar" : @"progress bar",
231+
@"radio" : @"radio button",
232+
@"radiogroup" : @"radio group",
233+
@"scrollbar" : @"scroll bar",
234+
@"spinbutton" : @"spin button",
235+
@"switch" : @"switch",
236+
@"tab" : @"tab",
237+
@"tablist" : @"tab list",
238+
@"timer" : @"timer",
239+
@"toolbar" : @"tool bar",
240+
@"checked" : @"checked",
241+
@"unchecked" : @"not checked",
242+
@"busy" : @"busy",
243+
@"expanded" : @"expanded",
244+
@"collapsed" : @"collapsed",
245+
@"mixed": @"mixed",
246+
};
247+
}
248+
});
249+
205250
if ((self.accessibilityTraits & SwitchAccessibilityTrait) == SwitchAccessibilityTrait) {
206251
for (NSString *state in self.accessibilityState) {
207252
id val = self.accessibilityState[state];
@@ -214,41 +259,7 @@ - (NSString *)accessibilityValue
214259
}
215260
}
216261
NSMutableArray *valueComponents = [NSMutableArray new];
217-
static NSDictionary<NSString *, NSString *> *roleDescriptions = nil;
218-
static dispatch_once_t onceToken1;
219-
dispatch_once(&onceToken1, ^{
220-
roleDescriptions = @{
221-
@"alert" : @"alert",
222-
@"checkbox" : @"checkbox",
223-
@"combobox" : @"combo box",
224-
@"menu" : @"menu",
225-
@"menubar" : @"menu bar",
226-
@"menuitem" : @"menu item",
227-
@"progressbar" : @"progress bar",
228-
@"radio" : @"radio button",
229-
@"radiogroup" : @"radio group",
230-
@"scrollbar" : @"scroll bar",
231-
@"spinbutton" : @"spin button",
232-
@"switch" : @"switch",
233-
@"tab" : @"tab",
234-
@"tablist" : @"tab list",
235-
@"timer" : @"timer",
236-
@"toolbar" : @"tool bar",
237-
};
238-
});
239-
static NSDictionary<NSString *, NSString *> *stateDescriptions = nil;
240-
static dispatch_once_t onceToken2;
241-
dispatch_once(&onceToken2, ^{
242-
stateDescriptions = @{
243-
@"checked" : @"checked",
244-
@"unchecked" : @"not checked",
245-
@"busy" : @"busy",
246-
@"expanded" : @"expanded",
247-
@"collapsed" : @"collapsed",
248-
@"mixed": @"mixed",
249-
};
250-
});
251-
NSString *roleDescription = self.accessibilityRole ? roleDescriptions[self.accessibilityRole]: nil;
262+
NSString *roleDescription = self.accessibilityRole ? rolesAndStatesDescription[self.accessibilityRole]: nil;
252263
if (roleDescription) {
253264
[valueComponents addObject:roleDescription];
254265
}
@@ -259,16 +270,16 @@ - (NSString *)accessibilityValue
259270
}
260271
if ([state isEqualToString:@"checked"]) {
261272
if ([val isKindOfClass:[NSNumber class]]) {
262-
[valueComponents addObject:stateDescriptions[[val boolValue] ? @"checked" : @"unchecked"]];
273+
[valueComponents addObject:rolesAndStatesDescription[[val boolValue] ? @"checked" : @"unchecked"]];
263274
} else if ([val isKindOfClass:[NSString class]] && [val isEqualToString:@"mixed"]) {
264-
[valueComponents addObject:stateDescriptions[@"mixed"]];
275+
[valueComponents addObject:rolesAndStatesDescription[@"mixed"]];
265276
}
266277
}
267278
if ([state isEqualToString:@"expanded"] && [val isKindOfClass:[NSNumber class]]) {
268-
[valueComponents addObject:stateDescriptions[[val boolValue] ? @"expanded" : @"collapsed"]];
279+
[valueComponents addObject:rolesAndStatesDescription[[val boolValue] ? @"expanded" : @"collapsed"]];
269280
}
270281
if ([state isEqualToString:@"busy"] && [val isKindOfClass:[NSNumber class]] && [val boolValue]) {
271-
[valueComponents addObject:stateDescriptions[@"busy"]];
282+
[valueComponents addObject:rolesAndStatesDescription[@"busy"]];
272283
}
273284
}
274285

0 commit comments

Comments
 (0)